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"
39 #include "libvo/csputils.h"
41 #include "libmpdemux/stheader.h"
45 #include "dec_video.h"
47 // ===================================================================
49 extern double video_time_usage
;
50 extern double vout_time_usage
;
52 #include "cpudetect.h"
54 int field_dominance
= -1;
58 int get_video_quality_max(sh_video_t
*sh_video
)
60 vf_instance_t
*vf
= sh_video
->vfilter
;
62 int ret
= vf
->control(vf
, VFCTRL_QUERY_MAX_PP_LEVEL
, NULL
);
64 mp_tmsg(MSGT_DECVIDEO
, MSGL_INFO
, "[PP] Using external postprocessing filter, max q = %d.\n", ret
);
68 const struct vd_functions
*vd
= sh_video
->vd_driver
;
70 int ret
= vd
->control(sh_video
, VDCTRL_QUERY_MAX_PP_LEVEL
, NULL
);
72 mp_tmsg(MSGT_DECVIDEO
, MSGL_INFO
, "[PP] Using codec's postprocessing, max q = %d.\n", ret
);
79 void set_video_quality(sh_video_t
*sh_video
, int quality
)
81 vf_instance_t
*vf
= sh_video
->vfilter
;
83 int ret
= vf
->control(vf
, VFCTRL_SET_PP_LEVEL
, (void *) (&quality
));
84 if (ret
== CONTROL_TRUE
)
87 const struct vd_functions
*vd
= sh_video
->vd_driver
;
89 vd
->control(sh_video
, VDCTRL_SET_PP_LEVEL
, (void *) (&quality
));
92 int set_video_colors(sh_video_t
*sh_video
, const char *item
, int value
)
94 vf_instance_t
*vf
= sh_video
->vfilter
;
100 mp_dbg(MSGT_DECVIDEO
, MSGL_V
, "set video colors %s=%d \n", item
, value
);
102 int ret
= vf
->control(vf
, VFCTRL_SET_EQUALIZER
, &data
);
103 if (ret
== CONTROL_TRUE
)
106 /* try software control */
107 const struct vd_functions
*vd
= sh_video
->vd_driver
;
109 vd
->control(sh_video
, VDCTRL_SET_EQUALIZER
, (void *)item
, value
)
112 mp_tmsg(MSGT_DECVIDEO
, MSGL_V
, "Video attribute '%s' is not supported by selected vo & vd.\n",
117 int get_video_colors(sh_video_t
*sh_video
, const char *item
, int *value
)
119 vf_instance_t
*vf
= sh_video
->vfilter
;
124 mp_dbg(MSGT_DECVIDEO
, MSGL_V
, "get video colors %s \n", item
);
126 int ret
= vf
->control(vf
, VFCTRL_GET_EQUALIZER
, &data
);
127 if (ret
== CONTROL_TRUE
) {
132 /* try software control */
133 const struct vd_functions
*vd
= sh_video
->vd_driver
;
135 return vd
->control(sh_video
, VDCTRL_GET_EQUALIZER
, (void *)item
, value
);
139 void get_detected_video_colorspace(struct sh_video
*sh
, struct mp_csp_details
*csp
)
141 struct MPOpts
*opts
= sh
->opts
;
142 struct vf_instance
*vf
= sh
->vfilter
;
144 csp
->format
= opts
->requested_colorspace
;
145 csp
->levels_in
= opts
->requested_input_range
;
146 csp
->levels_out
= opts
->requested_output_range
;
148 if (csp
->format
== MP_CSP_AUTO
)
149 csp
->format
= sh
->colorspace
;
150 if (csp
->format
== MP_CSP_AUTO
)
151 csp
->format
= mp_csp_guess_colorspace(vf
->w
, vf
->h
);
153 if (csp
->levels_in
== MP_CSP_LEVELS_AUTO
)
154 csp
->levels_in
= sh
->color_range
;
155 if (csp
->levels_in
== MP_CSP_LEVELS_AUTO
)
156 csp
->levels_in
= MP_CSP_LEVELS_TV
;
158 if (csp
->levels_out
== MP_CSP_LEVELS_AUTO
)
159 csp
->levels_out
= MP_CSP_LEVELS_PC
;
162 void set_video_colorspace(struct sh_video
*sh
)
164 struct vf_instance
*vf
= sh
->vfilter
;
166 struct mp_csp_details requested
;
167 get_detected_video_colorspace(sh
, &requested
);
168 vf
->control(vf
, VFCTRL_SET_YUV_COLORSPACE
, &requested
);
170 struct mp_csp_details actual
= MP_CSP_DETAILS_DEFAULTS
;
171 vf
->control(vf
, VFCTRL_GET_YUV_COLORSPACE
, &actual
);
173 int success
= actual
.format
== requested
.format
174 && actual
.levels_in
== requested
.levels_in
175 && actual
.levels_out
== requested
.levels_out
;
178 mp_tmsg(MSGT_DECVIDEO
, MSGL_WARN
,
179 "Colorspace details not fully supported by selected vo.\n");
181 if (actual
.format
!= requested
.format
182 && requested
.format
== MP_CSP_SMPTE_240M
) {
183 // BT.709 is pretty close, much better than BT.601
184 requested
.format
= MP_CSP_BT_709
;
185 vf
->control(vf
, VFCTRL_SET_YUV_COLORSPACE
, &requested
);
190 int set_rectangle(sh_video_t
*sh_video
, int param
, int value
)
192 vf_instance_t
*vf
= sh_video
->vfilter
;
193 int data
[] = { param
, value
};
195 mp_dbg(MSGT_DECVIDEO
, MSGL_V
, "set rectangle \n");
197 int ret
= vf
->control(vf
, VFCTRL_CHANGE_RECTANGLE
, data
);
204 void resync_video_stream(sh_video_t
*sh_video
)
206 const struct vd_functions
*vd
= sh_video
->vd_driver
;
208 vd
->control(sh_video
, VDCTRL_RESYNC_STREAM
, NULL
);
209 sh_video
->prev_codec_reordered_pts
= MP_NOPTS_VALUE
;
210 sh_video
->prev_sorted_pts
= MP_NOPTS_VALUE
;
213 void video_reset_aspect(struct sh_video
*sh_video
)
215 int r
= sh_video
->vd_driver
->control(sh_video
, VDCTRL_RESET_ASPECT
, NULL
);
217 mpcodecs_config_vo(sh_video
, sh_video
->disp_w
, sh_video
->disp_h
, 0);
220 int get_current_video_decoder_lag(sh_video_t
*sh_video
)
222 const struct vd_functions
*vd
= sh_video
->vd_driver
;
225 int ret
= vd
->control(sh_video
, VDCTRL_QUERY_UNSEEN_FRAMES
, NULL
);
231 void uninit_video(sh_video_t
*sh_video
)
233 if (!sh_video
->initialized
)
235 mp_tmsg(MSGT_DECVIDEO
, MSGL_V
, "Uninit video: %s\n", sh_video
->codec
->drv
);
236 sh_video
->vd_driver
->uninit(sh_video
);
237 vf_uninit_filter_chain(sh_video
->vfilter
);
238 sh_video
->initialized
= 0;
244 mp_tmsg(MSGT_DECVIDEO
, MSGL_INFO
, "Available (compiled-in) video codec families/drivers:\n");
245 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VIDEO_DRIVERS\n");
246 mp_msg(MSGT_DECVIDEO
, MSGL_INFO
, " vfm: info: (comment)\n");
247 for (i
= 0; mpcodecs_vd_drivers
[i
] != NULL
; i
++)
248 mp_msg(MSGT_DECVIDEO
, MSGL_INFO
, "%8s %s (%s)\n",
249 mpcodecs_vd_drivers
[i
]->info
->short_name
,
250 mpcodecs_vd_drivers
[i
]->info
->name
,
251 mpcodecs_vd_drivers
[i
]->info
->comment
);
254 static int init_video(sh_video_t
*sh_video
, char *codecname
, char *vfm
,
255 int status
, stringset_t
*selected
)
258 unsigned int orig_fourcc
=
259 sh_video
->bih
? sh_video
->bih
->biCompression
: 0;
260 sh_video
->codec
= NULL
;
261 sh_video
->vf_initialized
= 0;
262 if (codecname
&& codecname
[0] == '+') {
263 codecname
= &codecname
[1];
270 // restore original fourcc:
272 sh_video
->bih
->biCompression
= orig_fourcc
;
275 find_video_codec(sh_video
->format
,
276 sh_video
->bih
? ((unsigned int *) &sh_video
->
277 bih
->biCompression
) : NULL
,
278 sh_video
->codec
, force
)))
280 // ok we found one codec
281 if (stringset_test(selected
, sh_video
->codec
->name
))
282 continue; // already tried & failed
283 if (codecname
&& strcmp(sh_video
->codec
->name
, codecname
))
285 if (vfm
&& strcmp(sh_video
->codec
->drv
, vfm
))
286 continue; // vfm doesn't match
287 if (!force
&& sh_video
->codec
->status
< status
)
288 continue; // too unstable
289 stringset_add(selected
, sh_video
->codec
->name
); // tagging it
290 // ok, it matches all rules, let's find the driver!
291 for (i
= 0; mpcodecs_vd_drivers
[i
] != NULL
; i
++)
292 if (!strcmp(mpcodecs_vd_drivers
[i
]->info
->short_name
,
293 sh_video
->codec
->drv
))
295 sh_video
->vd_driver
= mpcodecs_vd_drivers
[i
];
296 if (!sh_video
->vd_driver
) { // driver not available (==compiled in)
297 mp_tmsg(MSGT_DECVIDEO
, MSGL_WARN
,
298 _("Requested video codec family [%s] (vfm=%s) not available.\nEnable it at compilation.\n"),
299 sh_video
->codec
->name
, sh_video
->codec
->drv
);
302 orig_w
= sh_video
->bih
? sh_video
->bih
->biWidth
: sh_video
->disp_w
;
303 orig_h
= sh_video
->bih
? sh_video
->bih
->biHeight
: sh_video
->disp_h
;
304 sh_video
->disp_w
= orig_w
;
305 sh_video
->disp_h
= orig_h
;
306 // it's available, let's try to init!
307 if (sh_video
->codec
->flags
& CODECS_FLAG_ALIGN16
) {
308 // align width/height to n*16
309 sh_video
->disp_w
= (sh_video
->disp_w
+ 15) & (~15);
310 sh_video
->disp_h
= (sh_video
->disp_h
+ 15) & (~15);
313 sh_video
->bih
->biWidth
= sh_video
->disp_w
;
314 sh_video
->bih
->biHeight
= sh_video
->disp_h
;
318 const struct vd_functions
*vd
= sh_video
->vd_driver
;
319 mp_tmsg(MSGT_DECVIDEO
, MSGL_V
, "Opening video decoder: [%s] %s\n",
320 vd
->info
->short_name
, vd
->info
->name
);
321 // clear vf init error, it is no longer relevant
322 if (sh_video
->vf_initialized
< 0)
323 sh_video
->vf_initialized
= 0;
324 if (!vd
->init(sh_video
)) {
325 mp_tmsg(MSGT_DECVIDEO
, MSGL_INFO
, "Video decoder init failed for "
326 "codecs.conf entry \"%s\".\n", sh_video
->codec
->name
);
327 sh_video
->disp_w
= orig_w
;
328 sh_video
->disp_h
= orig_h
;
330 sh_video
->bih
->biWidth
= sh_video
->disp_w
;
331 sh_video
->bih
->biHeight
= sh_video
->disp_h
;
333 continue; // try next...
336 sh_video
->initialized
= 1;
337 sh_video
->prev_codec_reordered_pts
= MP_NOPTS_VALUE
;
338 sh_video
->prev_sorted_pts
= MP_NOPTS_VALUE
;
344 int init_best_video_codec(sh_video_t
*sh_video
, char **video_codec_list
,
345 char **video_fm_list
)
347 char *vc_l_default
[2] = { "", (char *) NULL
};
348 stringset_t selected
;
350 if (!video_codec_list
)
351 video_codec_list
= vc_l_default
;
352 // Go through the codec.conf and find the best codec...
353 sh_video
->initialized
= 0;
354 stringset_init(&selected
);
355 while (!sh_video
->initialized
&& *video_codec_list
) {
356 char *video_codec
= *(video_codec_list
++);
357 if (video_codec
[0]) {
358 if (video_codec
[0] == '-') {
359 // disable this codec:
360 stringset_add(&selected
, video_codec
+ 1);
362 // forced codec by name:
363 mp_tmsg(MSGT_DECVIDEO
, MSGL_INFO
, "Forced video codec: %s\n",
365 init_video(sh_video
, video_codec
, NULL
, -1, &selected
);
369 // try in stability order: UNTESTED, WORKING, BUGGY. never try CRASHING.
371 char **fmlist
= video_fm_list
;
372 // try first the preferred codec families:
373 while (!sh_video
->initialized
&& *fmlist
) {
374 char *video_fm
= *(fmlist
++);
375 mp_tmsg(MSGT_DECVIDEO
, MSGL_INFO
, "Trying to force video codec driver family %s...\n",
377 for (status
= CODECS_STATUS__MAX
;
378 status
>= CODECS_STATUS__MIN
; --status
)
380 (sh_video
, NULL
, video_fm
, status
, &selected
))
384 if (!sh_video
->initialized
)
385 for (status
= CODECS_STATUS__MAX
; status
>= CODECS_STATUS__MIN
;
387 if (init_video(sh_video
, NULL
, NULL
, status
, &selected
))
391 stringset_free(&selected
);
393 if (!sh_video
->initialized
) {
394 mp_tmsg(MSGT_DECVIDEO
, MSGL_ERR
, "Cannot find codec matching selected -vo and video format 0x%X.\n",
399 mp_tmsg(MSGT_DECVIDEO
, MSGL_INFO
, "Selected video codec: %s [%s]\n",
400 sh_video
->codecname
? sh_video
->codecname
: sh_video
->codec
->info
,
401 sh_video
->vd_driver
->info
->print_name
?
402 sh_video
->vd_driver
->info
->print_name
:
403 sh_video
->vd_driver
->info
->short_name
);
404 mp_tmsg(MSGT_DECVIDEO
, MSGL_V
,
405 "Video codecs.conf entry: %s (%s) vfm: %s\n",
406 sh_video
->codec
->name
, sh_video
->codec
->info
, sh_video
->codec
->drv
);
410 void *decode_video(sh_video_t
*sh_video
, struct demux_packet
*packet
,
411 unsigned char *start
, int in_size
,
412 int drop_frame
, double pts
)
414 mp_image_t
*mpi
= NULL
;
415 unsigned int t
= GetTimer();
418 struct MPOpts
*opts
= sh_video
->opts
;
420 if (opts
->correct_pts
&& pts
!= MP_NOPTS_VALUE
) {
421 int delay
= get_current_video_decoder_lag(sh_video
);
423 if (delay
> sh_video
->num_buffered_pts
)
425 // this is disabled because vd_ffmpeg reports the same lag
426 // after seek even when there are no buffered frames,
427 // leading to incorrect error messages
428 mp_msg(MSGT_DECVIDEO
, MSGL_ERR
, "Not enough buffered pts\n");
433 sh_video
->num_buffered_pts
= delay
;
435 if (sh_video
->num_buffered_pts
==
436 sizeof(sh_video
->buffered_pts
) / sizeof(double))
437 mp_msg(MSGT_DECVIDEO
, MSGL_ERR
, "Too many buffered pts\n");
440 for (i
= 0; i
< sh_video
->num_buffered_pts
; i
++)
441 if (sh_video
->buffered_pts
[i
] < pts
)
443 for (j
= sh_video
->num_buffered_pts
; j
> i
; j
--)
444 sh_video
->buffered_pts
[j
] = sh_video
->buffered_pts
[j
- 1];
445 sh_video
->buffered_pts
[i
] = pts
;
446 sh_video
->num_buffered_pts
++;
450 if (sh_video
->vd_driver
->decode2
) {
451 mpi
= sh_video
->vd_driver
->decode2(sh_video
, packet
, start
, in_size
,
454 mpi
= sh_video
->vd_driver
->decode(sh_video
, start
, in_size
,
456 pts
= MP_NOPTS_VALUE
;
459 //------------------------ frame decoded. --------------------
462 // some codecs are broken, and doesn't restore MMX state :(
463 // it happens usually with broken/damaged files.
464 if (gCpuCaps
.has3DNow
) {
465 __asm__
volatile("femms\n\t":::"memory");
466 } else if (gCpuCaps
.hasMMX
) {
467 __asm__
volatile("emms\n\t":::"memory");
474 video_time_usage
+= tt
;
476 if (!mpi
|| drop_frame
)
477 return NULL
; // error / skipped frame
479 if (field_dominance
== 0)
480 mpi
->fields
|= MP_IMGFIELD_TOP_FIRST
;
481 else if (field_dominance
== 1)
482 mpi
->fields
&= ~MP_IMGFIELD_TOP_FIRST
;
484 double prevpts
= sh_video
->codec_reordered_pts
;
485 sh_video
->prev_codec_reordered_pts
= prevpts
;
486 sh_video
->codec_reordered_pts
= pts
;
487 if (prevpts
!= MP_NOPTS_VALUE
&& pts
<= prevpts
488 || pts
== MP_NOPTS_VALUE
)
489 sh_video
->num_reordered_pts_problems
++;
490 prevpts
= sh_video
->sorted_pts
;
491 if (opts
->correct_pts
) {
492 if (sh_video
->num_buffered_pts
) {
493 sh_video
->num_buffered_pts
--;
494 sh_video
->sorted_pts
=
495 sh_video
->buffered_pts
[sh_video
->num_buffered_pts
];
497 mp_msg(MSGT_CPLAYER
, MSGL_ERR
,
498 "No pts value from demuxer to use for frame!\n");
499 sh_video
->sorted_pts
= MP_NOPTS_VALUE
;
502 pts
= sh_video
->sorted_pts
;
503 if (prevpts
!= MP_NOPTS_VALUE
&& pts
<= prevpts
504 || pts
== MP_NOPTS_VALUE
)
505 sh_video
->num_sorted_pts_problems
++;
509 int filter_video(sh_video_t
*sh_video
, void *frame
, double pts
)
511 mp_image_t
*mpi
= frame
;
512 unsigned int t2
= GetTimer();
513 vf_instance_t
*vf
= sh_video
->vfilter
;
514 // apply video filters and call the leaf vo/ve
515 int ret
= vf
->put_image(vf
, mpi
, pts
);
517 t2
= GetTimer() - t2
;
518 vout_time_usage
+= t2
* 0.000001;