summaryrefslogtreecommitdiffstats
path: root/libmpcodecs/dec_video.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmpcodecs/dec_video.c')
-rw-r--r--libmpcodecs/dec_video.c186
1 files changed, 101 insertions, 85 deletions
diff --git a/libmpcodecs/dec_video.c b/libmpcodecs/dec_video.c
index 1dd6e42313..8cc7a6407c 100644
--- a/libmpcodecs/dec_video.c
+++ b/libmpcodecs/dec_video.c
@@ -17,13 +17,14 @@
*/
#include "config.h"
+#include "options.h"
#include <stdio.h>
#include <stdlib.h>
+#include <stdbool.h>
#include <unistd.h>
#include "mp_msg.h"
-#include "help_mp.h"
#include "osdep/timer.h"
#include "osdep/shmem.h"
@@ -57,26 +58,24 @@ int field_dominance = -1;
int divx_quality = 0;
-const vd_functions_t *mpvdec = NULL;
-
int get_video_quality_max(sh_video_t *sh_video)
{
vf_instance_t *vf = sh_video->vfilter;
if (vf) {
int ret = vf->control(vf, VFCTRL_QUERY_MAX_PP_LEVEL, NULL);
if (ret > 0) {
- mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_UsingExternalPP, ret);
+ mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "[PP] Using external postprocessing filter, max q = %d.\n", ret);
return ret;
}
}
- if (mpvdec) {
- int ret = mpvdec->control(sh_video, VDCTRL_QUERY_MAX_PP_LEVEL, NULL);
+ const struct vd_functions *vd = sh_video->vd_driver;
+ if (vd) {
+ int ret = vd->control(sh_video, VDCTRL_QUERY_MAX_PP_LEVEL, NULL);
if (ret > 0) {
- mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_UsingCodecPP, ret);
+ mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "[PP] Using codec's postprocessing, max q = %d.\n", ret);
return ret;
}
}
-// mp_msg(MSGT_DECVIDEO,MSGL_INFO,"[PP] Sorry, postprocessing is not available\n");
return 0;
}
@@ -88,8 +87,9 @@ void set_video_quality(sh_video_t *sh_video, int quality)
if (ret == CONTROL_TRUE)
return; // success
}
- if (mpvdec)
- mpvdec->control(sh_video, VDCTRL_SET_PP_LEVEL, (void *) (&quality));
+ const struct vd_functions *vd = sh_video->vd_driver;
+ if (vd)
+ vd->control(sh_video, VDCTRL_SET_PP_LEVEL, (void *) (&quality));
}
int set_video_colors(sh_video_t *sh_video, const char *item, int value)
@@ -107,12 +107,12 @@ int set_video_colors(sh_video_t *sh_video, const char *item, int value)
return 1;
}
/* try software control */
- if (mpvdec)
- if (mpvdec->control
- (sh_video, VDCTRL_SET_EQUALIZER, item, (int *) value)
+ const struct vd_functions *vd = sh_video->vd_driver;
+ if (vd &&
+ vd->control(sh_video, VDCTRL_SET_EQUALIZER, item, (int *) value)
== CONTROL_OK)
- return 1;
- mp_msg(MSGT_DECVIDEO, MSGL_V, MSGTR_VideoAttributeNotSupportedByVO_VD,
+ return 1;
+ mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Video attribute '%s' is not supported by selected vo & vd.\n",
item);
return 0;
}
@@ -133,8 +133,9 @@ int get_video_colors(sh_video_t *sh_video, const char *item, int *value)
}
}
/* try software control */
- if (mpvdec)
- return mpvdec->control(sh_video, VDCTRL_GET_EQUALIZER, item, value);
+ const struct vd_functions *vd = sh_video->vd_driver;
+ if (vd)
+ return vd->control(sh_video, VDCTRL_GET_EQUALIZER, item, value);
return 0;
}
@@ -152,23 +153,29 @@ 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)
{
- sh_video->timer = 0;
- sh_video->next_frame_time = 0;
- sh_video->num_buffered_pts = 0;
- sh_video->last_pts = MP_NOPTS_VALUE;
- if (mpvdec)
- mpvdec->control(sh_video, VDCTRL_RESYNC_STREAM, NULL);
+ const struct vd_functions *vd = sh_video->vd_driver;
+ if (vd)
+ vd->control(sh_video, VDCTRL_RESYNC_STREAM, NULL);
+ sh_video->prev_codec_reordered_pts = MP_NOPTS_VALUE;
+ sh_video->prev_sorted_pts = MP_NOPTS_VALUE;
}
int get_current_video_decoder_lag(sh_video_t *sh_video)
{
- int ret;
-
- if (!mpvdec)
+ const struct vd_functions *vd = sh_video->vd_driver;
+ if (!vd)
return -1;
- ret = mpvdec->control(sh_video, VDCTRL_QUERY_UNSEEN_FRAMES, NULL);
+ int ret = vd->control(sh_video, VDCTRL_QUERY_UNSEEN_FRAMES, NULL);
if (ret >= 10)
return ret - 10;
return -1;
@@ -178,8 +185,8 @@ void uninit_video(sh_video_t *sh_video)
{
if (!sh_video->initialized)
return;
- mp_msg(MSGT_DECVIDEO, MSGL_V, MSGTR_UninitVideoStr, sh_video->codec->drv);
- mpvdec->uninit(sh_video);
+ mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Uninit video: %s\n", sh_video->codec->drv);
+ sh_video->vd_driver->uninit(sh_video);
#ifdef CONFIG_DYNAMIC_PLUGINS
if (sh_video->dec_handle)
dlclose(sh_video->dec_handle);
@@ -191,7 +198,7 @@ void uninit_video(sh_video_t *sh_video)
void vfm_help(void)
{
int i;
- mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_AvailableVideoFm);
+ mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Available (compiled-in) video codec families/drivers:\n");
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_DRIVERS\n");
mp_msg(MSGT_DECVIDEO, MSGL_INFO, " vfm: info: (comment)\n");
for (i = 0; mpcodecs_vd_drivers[i] != NULL; i++)
@@ -223,10 +230,9 @@ static int init_video(sh_video_t *sh_video, char *codecname, char *vfm,
if (!
(sh_video->codec =
find_video_codec(sh_video->format,
- sh_video->
- bih ? ((unsigned int *) &sh_video->bih->
- biCompression) : NULL, sh_video->codec,
- force)))
+ sh_video->bih ? ((unsigned int *) &sh_video->
+ bih->biCompression) : NULL,
+ sh_video->codec, force)))
break;
// ok we found one codec
if (stringset_test(selected, sh_video->codec->name))
@@ -240,14 +246,12 @@ static int init_video(sh_video_t *sh_video, char *codecname, char *vfm,
stringset_add(selected, sh_video->codec->name); // tagging it
// ok, it matches all rules, let's find the driver!
for (i = 0; mpcodecs_vd_drivers[i] != NULL; i++)
-// if(mpcodecs_vd_drivers[i]->info->id==sh_video->codec->driver) break;
- if (!strcmp
- (mpcodecs_vd_drivers[i]->info->short_name,
- sh_video->codec->drv))
+ if (!strcmp(mpcodecs_vd_drivers[i]->info->short_name,
+ sh_video->codec->drv))
break;
- mpvdec = mpcodecs_vd_drivers[i];
+ sh_video->vd_driver = mpcodecs_vd_drivers[i];
#ifdef CONFIG_DYNAMIC_PLUGINS
- if (!mpvdec) {
+ if (!sh_video->vd_driver) {
/* try to open shared decoder plugin */
int buf_len;
char *buf;
@@ -276,15 +280,15 @@ static int init_video(sh_video_t *sh_video, char *codecname, char *vfm,
if (strcmp(info_sym->short_name, sh_video->codec->drv))
break;
free(buf);
- mpvdec = funcs_sym;
+ sh_video->vd_driver = funcs_sym;
mp_msg(MSGT_DECVIDEO, MSGL_V,
"Using external decoder plugin (%s/mplayer/vd_%s.so)!\n",
MPLAYER_LIBDIR, sh_video->codec->drv);
}
#endif
- if (!mpvdec) { // driver not available (==compiled in)
- mp_msg(MSGT_DECVIDEO, MSGL_WARN,
- MSGTR_VideoCodecFamilyNotAvailableStr,
+ if (!sh_video->vd_driver) { // driver not available (==compiled in)
+ mp_tmsg(MSGT_DECVIDEO, MSGL_WARN,
+ _("Requested video codec family [%s] (vfm=%s) not available.\nEnable it at compilation.\n"),
sh_video->codec->name, sh_video->codec->drv);
continue;
}
@@ -302,14 +306,16 @@ static int init_video(sh_video_t *sh_video, char *codecname, char *vfm,
sh_video->bih->biWidth = sh_video->disp_w;
sh_video->bih->biHeight = sh_video->disp_h;
}
+
// init()
- mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_OpeningVideoDecoder,
- mpvdec->info->short_name, mpvdec->info->name);
+ const struct vd_functions *vd = sh_video->vd_driver;
+ mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Opening video decoder: [%s] %s\n",
+ vd->info->short_name, vd->info->name);
// clear vf init error, it is no longer relevant
if (sh_video->vf_initialized < 0)
sh_video->vf_initialized = 0;
- if (!mpvdec->init(sh_video)) {
- mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_VDecoderInitFailed);
+ if (!vd->init(sh_video)) {
+ mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "VDecoder init failed :(\n");
sh_video->disp_w = orig_w;
sh_video->disp_h = orig_h;
if (sh_video->bih) {
@@ -320,6 +326,8 @@ static int init_video(sh_video_t *sh_video, char *codecname, char *vfm,
}
// Yeah! We got it!
sh_video->initialized = 1;
+ sh_video->prev_codec_reordered_pts = MP_NOPTS_VALUE;
+ sh_video->prev_sorted_pts = MP_NOPTS_VALUE;
return 1;
}
return 0;
@@ -344,7 +352,7 @@ int init_best_video_codec(sh_video_t *sh_video, char **video_codec_list,
stringset_add(&selected, video_codec + 1);
} else {
// forced codec by name:
- mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_ForcedVideoCodec,
+ mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Forced video codec: %s\n",
video_codec);
init_video(sh_video, video_codec, NULL, -1, &selected);
}
@@ -356,7 +364,7 @@ int init_best_video_codec(sh_video_t *sh_video, char **video_codec_list,
// try first the preferred codec families:
while (!sh_video->initialized && *fmlist) {
char *video_fm = *(fmlist++);
- mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_TryForceVideoFmtStr,
+ mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Trying to force video codec driver family %s...\n",
video_fm);
for (status = CODECS_STATUS__MAX;
status >= CODECS_STATUS__MIN; --status)
@@ -375,12 +383,12 @@ int init_best_video_codec(sh_video_t *sh_video, char **video_codec_list,
stringset_free(&selected);
if (!sh_video->initialized) {
- mp_msg(MSGT_DECVIDEO, MSGL_ERR, MSGTR_CantFindVideoCodec,
+ mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Cannot find codec matching selected -vo and video format 0x%X.\n",
sh_video->format);
return 0; // failed
}
- mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_SelectedVideoCodec,
+ mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Selected video codec: [%s] vfm: %s (%s)\n",
sh_video->codec->name, sh_video->codec->drv, sh_video->codec->info);
return 1; // success
}
@@ -392,8 +400,23 @@ void *decode_video(sh_video_t *sh_video, unsigned char *start, int in_size,
unsigned int t = GetTimer();
unsigned int t2;
double tt;
+ struct MPOpts *opts = sh_video->opts;
- if (correct_pts && pts != MP_NOPTS_VALUE) {
+ if (opts->correct_pts && pts != MP_NOPTS_VALUE) {
+ 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");
@@ -409,7 +432,14 @@ void *decode_video(sh_video_t *sh_video, unsigned char *start, int in_size,
}
}
- mpi = mpvdec->decode(sh_video, start, in_size, drop_frame);
+ if (sh_video->vd_driver->decode2) {
+ mpi = sh_video->vd_driver->decode2(sh_video, start, in_size,
+ drop_frame, &pts);
+ } else {
+ mpi = sh_video->vd_driver->decode(sh_video, start, in_size,
+ drop_frame);
+ pts = MP_NOPTS_VALUE;
+ }
//------------------------ frame decoded. --------------------
@@ -417,9 +447,9 @@ void *decode_video(sh_video_t *sh_video, unsigned char *start, int in_size,
// some codecs are broken, and doesn't restore MMX state :(
// it happens usually with broken/damaged files.
if (gCpuCaps.has3DNow) {
- __asm__ volatile ("femms\n\t":::"memory");
+ __asm__ volatile("femms\n\t":::"memory");
} else if (gCpuCaps.hasMMX) {
- __asm__ volatile ("emms\n\t":::"memory");
+ __asm__ volatile("emms\n\t":::"memory");
}
#endif
@@ -436,33 +466,28 @@ void *decode_video(sh_video_t *sh_video, unsigned char *start, int in_size,
else if (field_dominance == 1)
mpi->fields &= ~MP_IMGFIELD_TOP_FIRST;
- if (correct_pts) {
- int delay = get_current_video_decoder_lag(sh_video);
+ double prevpts = sh_video->codec_reordered_pts;
+ sh_video->prev_codec_reordered_pts = prevpts;
+ sh_video->codec_reordered_pts = pts;
+ if (prevpts != MP_NOPTS_VALUE && pts <= prevpts
+ || pts == MP_NOPTS_VALUE)
+ sh_video->num_reordered_pts_problems++;
+ prevpts = sh_video->sorted_pts;
+ if (opts->correct_pts) {
if (sh_video->num_buffered_pts) {
sh_video->num_buffered_pts--;
- sh_video->pts = sh_video->buffered_pts[sh_video->num_buffered_pts];
+ sh_video->sorted_pts =
+ sh_video->buffered_pts[sh_video->num_buffered_pts];
} else {
mp_msg(MSGT_CPLAYER, MSGL_ERR,
"No pts value from demuxer to " "use for frame!\n");
- sh_video->pts = MP_NOPTS_VALUE;
- }
- if (delay >= 0) {
- // limit buffered pts only afterwards so we do not get confused
- // by packets that produce no output (e.g. a single field of a
- // H.264 frame).
- 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;
+ sh_video->sorted_pts = MP_NOPTS_VALUE;
}
}
+ pts = sh_video->sorted_pts;
+ if (prevpts != MP_NOPTS_VALUE && pts <= prevpts
+ || pts == MP_NOPTS_VALUE)
+ sh_video->num_sorted_pts_problems++;
return mpi;
}
@@ -473,15 +498,6 @@ int filter_video(sh_video_t *sh_video, void *frame, double pts)
vf_instance_t *vf = sh_video->vfilter;
// apply video filters and call the leaf vo/ve
int ret = vf->put_image(vf, mpi, pts);
- if (ret > 0) {
- // draw EOSD first so it ends up below the OSD.
- // Note that changing this is will not work right with vf_ass and the
- // vos currently always draw the EOSD first in paused mode.
-#ifdef CONFIG_ASS
- vf->control(vf, VFCTRL_DRAW_EOSD, NULL);
-#endif
- vf->control(vf, VFCTRL_DRAW_OSD, NULL);
- }
t2 = GetTimer() - t2;
vout_time_usage += t2 * 0.000001;