2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include "osdep/timer.h"
30 #include "osdep/shmem.h"
32 #include "stream/stream.h"
33 #include "libmpdemux/demuxer.h"
34 #include "libmpdemux/parse_es.h"
36 #include "codec-cfg.h"
38 #include "libvo/video_out.h"
40 #include "libmpdemux/stheader.h"
44 #include "dec_video.h"
46 #ifdef CONFIG_DYNAMIC_PLUGINS
50 // ===================================================================
52 extern double video_time_usage
;
53 extern double vout_time_usage
;
55 #include "cpudetect.h"
57 int field_dominance
= -1;
61 int get_video_quality_max(sh_video_t
*sh_video
)
63 vf_instance_t
*vf
= sh_video
->vfilter
;
65 int ret
= vf
->control(vf
, VFCTRL_QUERY_MAX_PP_LEVEL
, NULL
);
67 mp_tmsg(MSGT_DECVIDEO
, MSGL_INFO
, "[PP] Using external postprocessing filter, max q = %d.\n", ret
);
71 const struct vd_functions
*vd
= sh_video
->vd_driver
;
73 int ret
= vd
->control(sh_video
, VDCTRL_QUERY_MAX_PP_LEVEL
, NULL
);
75 mp_tmsg(MSGT_DECVIDEO
, MSGL_INFO
, "[PP] Using codec's postprocessing, max q = %d.\n", ret
);
82 void set_video_quality(sh_video_t
*sh_video
, int quality
)
84 vf_instance_t
*vf
= sh_video
->vfilter
;
86 int ret
= vf
->control(vf
, VFCTRL_SET_PP_LEVEL
, (void *) (&quality
));
87 if (ret
== CONTROL_TRUE
)
90 const struct vd_functions
*vd
= sh_video
->vd_driver
;
92 vd
->control(sh_video
, VDCTRL_SET_PP_LEVEL
, (void *) (&quality
));
95 int set_video_colors(sh_video_t
*sh_video
, const char *item
, int value
)
97 vf_instance_t
*vf
= sh_video
->vfilter
;
103 mp_dbg(MSGT_DECVIDEO
, MSGL_V
, "set video colors %s=%d \n", item
, value
);
105 int ret
= vf
->control(vf
, VFCTRL_SET_EQUALIZER
, &data
);
106 if (ret
== CONTROL_TRUE
)
109 /* try software control */
110 const struct vd_functions
*vd
= sh_video
->vd_driver
;
112 vd
->control(sh_video
, VDCTRL_SET_EQUALIZER
, item
, (int *) value
)
115 mp_tmsg(MSGT_DECVIDEO
, MSGL_V
, "Video attribute '%s' is not supported by selected vo & vd.\n",
120 int get_video_colors(sh_video_t
*sh_video
, const char *item
, int *value
)
122 vf_instance_t
*vf
= sh_video
->vfilter
;
127 mp_dbg(MSGT_DECVIDEO
, MSGL_V
, "get video colors %s \n", item
);
129 int ret
= vf
->control(vf
, VFCTRL_GET_EQUALIZER
, &data
);
130 if (ret
== CONTROL_TRUE
) {
135 /* try software control */
136 const struct vd_functions
*vd
= sh_video
->vd_driver
;
138 return vd
->control(sh_video
, VDCTRL_GET_EQUALIZER
, item
, value
);
142 int set_rectangle(sh_video_t
*sh_video
, int param
, int value
)
144 vf_instance_t
*vf
= sh_video
->vfilter
;
145 int data
[] = { param
, value
};
147 mp_dbg(MSGT_DECVIDEO
, MSGL_V
, "set rectangle \n");
149 int ret
= vf
->control(vf
, VFCTRL_CHANGE_RECTANGLE
, data
);
156 int redraw_osd(struct sh_video
*sh_video
, struct osd_state
*osd
)
158 struct vf_instance
*vf
= sh_video
->vfilter
;
159 if (vf
->control(vf
, VFCTRL_REDRAW_OSD
, osd
) == true)
164 void resync_video_stream(sh_video_t
*sh_video
)
166 const struct vd_functions
*vd
= sh_video
->vd_driver
;
168 vd
->control(sh_video
, VDCTRL_RESYNC_STREAM
, NULL
);
169 sh_video
->prev_codec_reordered_pts
= MP_NOPTS_VALUE
;
170 sh_video
->prev_sorted_pts
= MP_NOPTS_VALUE
;
173 int get_current_video_decoder_lag(sh_video_t
*sh_video
)
175 const struct vd_functions
*vd
= sh_video
->vd_driver
;
178 int ret
= vd
->control(sh_video
, VDCTRL_QUERY_UNSEEN_FRAMES
, NULL
);
184 void uninit_video(sh_video_t
*sh_video
)
186 if (!sh_video
->initialized
)
188 mp_tmsg(MSGT_DECVIDEO
, MSGL_V
, "Uninit video: %s\n", sh_video
->codec
->drv
);
189 sh_video
->vd_driver
->uninit(sh_video
);
190 #ifdef CONFIG_DYNAMIC_PLUGINS
191 if (sh_video
->dec_handle
)
192 dlclose(sh_video
->dec_handle
);
194 vf_uninit_filter_chain(sh_video
->vfilter
);
195 sh_video
->initialized
= 0;
201 mp_tmsg(MSGT_DECVIDEO
, MSGL_INFO
, "Available (compiled-in) video codec families/drivers:\n");
202 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VIDEO_DRIVERS\n");
203 mp_msg(MSGT_DECVIDEO
, MSGL_INFO
, " vfm: info: (comment)\n");
204 for (i
= 0; mpcodecs_vd_drivers
[i
] != NULL
; i
++)
205 mp_msg(MSGT_DECVIDEO
, MSGL_INFO
, "%8s %s (%s)\n",
206 mpcodecs_vd_drivers
[i
]->info
->short_name
,
207 mpcodecs_vd_drivers
[i
]->info
->name
,
208 mpcodecs_vd_drivers
[i
]->info
->comment
);
211 static int init_video(sh_video_t
*sh_video
, char *codecname
, char *vfm
,
212 int status
, stringset_t
*selected
)
215 unsigned int orig_fourcc
=
216 sh_video
->bih
? sh_video
->bih
->biCompression
: 0;
217 sh_video
->codec
= NULL
;
218 sh_video
->vf_initialized
= 0;
219 if (codecname
&& codecname
[0] == '+') {
220 codecname
= &codecname
[1];
227 // restore original fourcc:
229 sh_video
->bih
->biCompression
= orig_fourcc
;
232 find_video_codec(sh_video
->format
,
233 sh_video
->bih
? ((unsigned int *) &sh_video
->
234 bih
->biCompression
) : NULL
,
235 sh_video
->codec
, force
)))
237 // ok we found one codec
238 if (stringset_test(selected
, sh_video
->codec
->name
))
239 continue; // already tried & failed
240 if (codecname
&& strcmp(sh_video
->codec
->name
, codecname
))
242 if (vfm
&& strcmp(sh_video
->codec
->drv
, vfm
))
243 continue; // vfm doesn't match
244 if (!force
&& sh_video
->codec
->status
< status
)
245 continue; // too unstable
246 stringset_add(selected
, sh_video
->codec
->name
); // tagging it
247 // ok, it matches all rules, let's find the driver!
248 for (i
= 0; mpcodecs_vd_drivers
[i
] != NULL
; i
++)
249 if (!strcmp(mpcodecs_vd_drivers
[i
]->info
->short_name
,
250 sh_video
->codec
->drv
))
252 sh_video
->vd_driver
= mpcodecs_vd_drivers
[i
];
253 #ifdef CONFIG_DYNAMIC_PLUGINS
254 if (!sh_video
->vd_driver
) {
255 /* try to open shared decoder plugin */
258 vd_functions_t
*funcs_sym
;
262 strlen(MPLAYER_LIBDIR
) + strlen(sh_video
->codec
->drv
) + 16;
263 buf
= malloc(buf_len
);
266 snprintf(buf
, buf_len
, "%s/mplayer/vd_%s.so", MPLAYER_LIBDIR
,
267 sh_video
->codec
->drv
);
268 mp_msg(MSGT_DECVIDEO
, MSGL_DBG2
,
269 "Trying to open external plugin: %s\n", buf
);
270 sh_video
->dec_handle
= dlopen(buf
, RTLD_LAZY
);
271 if (!sh_video
->dec_handle
)
273 snprintf(buf
, buf_len
, "mpcodecs_vd_%s", sh_video
->codec
->drv
);
274 funcs_sym
= dlsym(sh_video
->dec_handle
, buf
);
275 if (!funcs_sym
|| !funcs_sym
->info
|| !funcs_sym
->init
276 || !funcs_sym
->uninit
|| !funcs_sym
->control
277 || !funcs_sym
->decode
)
279 info_sym
= funcs_sym
->info
;
280 if (strcmp(info_sym
->short_name
, sh_video
->codec
->drv
))
283 sh_video
->vd_driver
= funcs_sym
;
284 mp_msg(MSGT_DECVIDEO
, MSGL_V
,
285 "Using external decoder plugin (%s/mplayer/vd_%s.so)!\n",
286 MPLAYER_LIBDIR
, sh_video
->codec
->drv
);
289 if (!sh_video
->vd_driver
) { // driver not available (==compiled in)
290 mp_tmsg(MSGT_DECVIDEO
, MSGL_WARN
,
291 _("Requested video codec family [%s] (vfm=%s) not available.\nEnable it at compilation.\n"),
292 sh_video
->codec
->name
, sh_video
->codec
->drv
);
295 orig_w
= sh_video
->bih
? sh_video
->bih
->biWidth
: sh_video
->disp_w
;
296 orig_h
= sh_video
->bih
? sh_video
->bih
->biHeight
: sh_video
->disp_h
;
297 sh_video
->disp_w
= orig_w
;
298 sh_video
->disp_h
= orig_h
;
299 // it's available, let's try to init!
300 if (sh_video
->codec
->flags
& CODECS_FLAG_ALIGN16
) {
301 // align width/height to n*16
302 sh_video
->disp_w
= (sh_video
->disp_w
+ 15) & (~15);
303 sh_video
->disp_h
= (sh_video
->disp_h
+ 15) & (~15);
306 sh_video
->bih
->biWidth
= sh_video
->disp_w
;
307 sh_video
->bih
->biHeight
= sh_video
->disp_h
;
311 const struct vd_functions
*vd
= sh_video
->vd_driver
;
312 mp_tmsg(MSGT_DECVIDEO
, MSGL_INFO
, "Opening video decoder: [%s] %s\n",
313 vd
->info
->short_name
, vd
->info
->name
);
314 // clear vf init error, it is no longer relevant
315 if (sh_video
->vf_initialized
< 0)
316 sh_video
->vf_initialized
= 0;
317 if (!vd
->init(sh_video
)) {
318 mp_tmsg(MSGT_DECVIDEO
, MSGL_INFO
, "VDecoder init failed :(\n");
319 sh_video
->disp_w
= orig_w
;
320 sh_video
->disp_h
= orig_h
;
322 sh_video
->bih
->biWidth
= sh_video
->disp_w
;
323 sh_video
->bih
->biHeight
= sh_video
->disp_h
;
325 continue; // try next...
328 sh_video
->initialized
= 1;
329 sh_video
->prev_codec_reordered_pts
= MP_NOPTS_VALUE
;
330 sh_video
->prev_sorted_pts
= MP_NOPTS_VALUE
;
336 int init_best_video_codec(sh_video_t
*sh_video
, char **video_codec_list
,
337 char **video_fm_list
)
339 char *vc_l_default
[2] = { "", (char *) NULL
};
340 stringset_t selected
;
342 if (!video_codec_list
)
343 video_codec_list
= vc_l_default
;
344 // Go through the codec.conf and find the best codec...
345 sh_video
->initialized
= 0;
346 stringset_init(&selected
);
347 while (!sh_video
->initialized
&& *video_codec_list
) {
348 char *video_codec
= *(video_codec_list
++);
349 if (video_codec
[0]) {
350 if (video_codec
[0] == '-') {
351 // disable this codec:
352 stringset_add(&selected
, video_codec
+ 1);
354 // forced codec by name:
355 mp_tmsg(MSGT_DECVIDEO
, MSGL_INFO
, "Forced video codec: %s\n",
357 init_video(sh_video
, video_codec
, NULL
, -1, &selected
);
361 // try in stability order: UNTESTED, WORKING, BUGGY. never try CRASHING.
363 char **fmlist
= video_fm_list
;
364 // try first the preferred codec families:
365 while (!sh_video
->initialized
&& *fmlist
) {
366 char *video_fm
= *(fmlist
++);
367 mp_tmsg(MSGT_DECVIDEO
, MSGL_INFO
, "Trying to force video codec driver family %s...\n",
369 for (status
= CODECS_STATUS__MAX
;
370 status
>= CODECS_STATUS__MIN
; --status
)
372 (sh_video
, NULL
, video_fm
, status
, &selected
))
376 if (!sh_video
->initialized
)
377 for (status
= CODECS_STATUS__MAX
; status
>= CODECS_STATUS__MIN
;
379 if (init_video(sh_video
, NULL
, NULL
, status
, &selected
))
383 stringset_free(&selected
);
385 if (!sh_video
->initialized
) {
386 mp_tmsg(MSGT_DECVIDEO
, MSGL_ERR
, "Cannot find codec matching selected -vo and video format 0x%X.\n",
391 mp_tmsg(MSGT_DECVIDEO
, MSGL_INFO
, "Selected video codec: [%s] vfm: %s (%s)\n",
392 sh_video
->codec
->name
, sh_video
->codec
->drv
, sh_video
->codec
->info
);
396 void *decode_video(sh_video_t
*sh_video
, unsigned char *start
, int in_size
,
397 int drop_frame
, double pts
)
399 mp_image_t
*mpi
= NULL
;
400 unsigned int t
= GetTimer();
403 struct MPOpts
*opts
= sh_video
->opts
;
405 if (opts
->correct_pts
&& pts
!= MP_NOPTS_VALUE
) {
406 int delay
= get_current_video_decoder_lag(sh_video
);
408 if (delay
> sh_video
->num_buffered_pts
)
410 // this is disabled because vd_ffmpeg reports the same lag
411 // after seek even when there are no buffered frames,
412 // leading to incorrect error messages
413 mp_msg(MSGT_DECVIDEO
, MSGL_ERR
, "Not enough buffered pts\n");
418 sh_video
->num_buffered_pts
= delay
;
420 if (sh_video
->num_buffered_pts
==
421 sizeof(sh_video
->buffered_pts
) / sizeof(double))
422 mp_msg(MSGT_DECVIDEO
, MSGL_ERR
, "Too many buffered pts\n");
425 for (i
= 0; i
< sh_video
->num_buffered_pts
; i
++)
426 if (sh_video
->buffered_pts
[i
] < pts
)
428 for (j
= sh_video
->num_buffered_pts
; j
> i
; j
--)
429 sh_video
->buffered_pts
[j
] = sh_video
->buffered_pts
[j
- 1];
430 sh_video
->buffered_pts
[i
] = pts
;
431 sh_video
->num_buffered_pts
++;
435 if (sh_video
->vd_driver
->decode2
) {
436 mpi
= sh_video
->vd_driver
->decode2(sh_video
, start
, in_size
,
439 mpi
= sh_video
->vd_driver
->decode(sh_video
, start
, in_size
,
441 pts
= MP_NOPTS_VALUE
;
444 //------------------------ frame decoded. --------------------
447 // some codecs are broken, and doesn't restore MMX state :(
448 // it happens usually with broken/damaged files.
449 if (gCpuCaps
.has3DNow
) {
450 __asm__
volatile("femms\n\t":::"memory");
451 } else if (gCpuCaps
.hasMMX
) {
452 __asm__
volatile("emms\n\t":::"memory");
459 video_time_usage
+= tt
;
461 if (!mpi
|| drop_frame
)
462 return NULL
; // error / skipped frame
464 if (field_dominance
== 0)
465 mpi
->fields
|= MP_IMGFIELD_TOP_FIRST
;
466 else if (field_dominance
== 1)
467 mpi
->fields
&= ~MP_IMGFIELD_TOP_FIRST
;
469 double prevpts
= sh_video
->codec_reordered_pts
;
470 sh_video
->prev_codec_reordered_pts
= prevpts
;
471 sh_video
->codec_reordered_pts
= pts
;
472 if (prevpts
!= MP_NOPTS_VALUE
&& pts
<= prevpts
473 || pts
== MP_NOPTS_VALUE
)
474 sh_video
->num_reordered_pts_problems
++;
475 prevpts
= sh_video
->sorted_pts
;
476 if (opts
->correct_pts
) {
477 if (sh_video
->num_buffered_pts
) {
478 sh_video
->num_buffered_pts
--;
479 sh_video
->sorted_pts
=
480 sh_video
->buffered_pts
[sh_video
->num_buffered_pts
];
482 mp_msg(MSGT_CPLAYER
, MSGL_ERR
,
483 "No pts value from demuxer to " "use for frame!\n");
484 sh_video
->sorted_pts
= MP_NOPTS_VALUE
;
487 pts
= sh_video
->sorted_pts
;
488 if (prevpts
!= MP_NOPTS_VALUE
&& pts
<= prevpts
489 || pts
== MP_NOPTS_VALUE
)
490 sh_video
->num_sorted_pts_problems
++;
494 int filter_video(sh_video_t
*sh_video
, void *frame
, double pts
)
496 mp_image_t
*mpi
= frame
;
497 unsigned int t2
= GetTimer();
498 vf_instance_t
*vf
= sh_video
->vfilter
;
499 // apply video filters and call the leaf vo/ve
500 int ret
= vf
->put_image(vf
, mpi
, pts
);
502 t2
= GetTimer() - t2
;
503 vout_time_usage
+= t2
* 0.000001;