diff options
Diffstat (limited to 'libmpcodecs/dec_video.c')
-rw-r--r-- | libmpcodecs/dec_video.c | 155 |
1 files changed, 87 insertions, 68 deletions
diff --git a/libmpcodecs/dec_video.c b/libmpcodecs/dec_video.c index 51da1adf7b..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,9 @@ 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) @@ -423,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. -------------------- @@ -431,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 @@ -450,16 +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) { + 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; + 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; } @@ -470,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; |