14 #include "osdep/timer.h"
15 #include "osdep/shmem.h"
21 #include "codec-cfg.h"
23 #include "libvo/video_out.h"
29 #include "dec_video.h"
31 #ifdef DYNAMIC_PLUGINS
35 // ===================================================================
37 extern double video_time_usage
;
38 extern double vout_time_usage
;
40 #include "cpudetect.h"
44 vd_functions_t
* mpvdec
=NULL
;
46 int get_video_quality_max(sh_video_t
*sh_video
){
47 vf_instance_t
* vf
=sh_video
->vfilter
;
49 int ret
=vf
->control(vf
,VFCTRL_QUERY_MAX_PP_LEVEL
,NULL
);
51 mp_msg(MSGT_DECVIDEO
,MSGL_INFO
,MSGTR_UsingExternalPP
,ret
);
56 int ret
=mpvdec
->control(sh_video
,VDCTRL_QUERY_MAX_PP_LEVEL
,NULL
);
58 mp_msg(MSGT_DECVIDEO
,MSGL_INFO
,MSGTR_UsingCodecPP
,ret
);
62 // mp_msg(MSGT_DECVIDEO,MSGL_INFO,"[PP] Sorry, postprocessing is not available\n");
66 void set_video_quality(sh_video_t
*sh_video
,int quality
){
67 vf_instance_t
* vf
=sh_video
->vfilter
;
69 int ret
=vf
->control(vf
,VFCTRL_SET_PP_LEVEL
, (void*)(&quality
));
70 if(ret
==CONTROL_TRUE
) return; // success
73 mpvdec
->control(sh_video
,VDCTRL_SET_PP_LEVEL
, (void*)(&quality
));
76 int set_video_colors(sh_video_t
*sh_video
,char *item
,int value
)
78 vf_instance_t
* vf
=sh_video
->vfilter
;
84 mp_dbg(MSGT_DECVIDEO
,MSGL_V
,"set video colors %s=%d \n", item
, value
);
87 int ret
= vf
->control(vf
, VFCTRL_SET_EQUALIZER
, &data
);
88 if (ret
== CONTROL_TRUE
)
91 /* try software control */
93 if( mpvdec
->control(sh_video
,VDCTRL_SET_EQUALIZER
, item
, (int *)value
)
94 == CONTROL_OK
) return 1;
95 mp_msg(MSGT_DECVIDEO
,MSGL_V
,MSGTR_VideoAttributeNotSupportedByVO_VD
,item
);
99 int get_video_colors(sh_video_t
*sh_video
,char *item
,int *value
)
101 vf_instance_t
* vf
=sh_video
->vfilter
;
106 mp_dbg(MSGT_DECVIDEO
,MSGL_V
,"get video colors %s \n", item
);
109 int ret
= vf
->control(vf
, VFCTRL_GET_EQUALIZER
, &data
);
110 if (ret
== CONTROL_TRUE
){
115 /* try software control */
116 if(mpvdec
) return mpvdec
->control(sh_video
,VDCTRL_GET_EQUALIZER
, item
, value
);
120 int set_rectangle(sh_video_t
*sh_video
,int param
,int value
)
122 vf_instance_t
* vf
=sh_video
->vfilter
;
123 int data
[] = {param
, value
};
125 mp_dbg(MSGT_DECVIDEO
,MSGL_V
,"set rectangle \n");
128 int ret
= vf
->control(vf
, VFCTRL_CHANGE_RECTANGLE
, data
);
135 void resync_video_stream(sh_video_t
*sh_video
)
137 if(mpvdec
) mpvdec
->control(sh_video
, VDCTRL_RESYNC_STREAM
, NULL
);
140 void uninit_video(sh_video_t
*sh_video
){
141 if(!sh_video
->inited
) return;
142 mp_msg(MSGT_DECVIDEO
,MSGL_V
,MSGTR_UninitVideoStr
,sh_video
->codec
->drv
);
143 mpvdec
->uninit(sh_video
);
144 #ifdef DYNAMIC_PLUGINS
145 if (sh_video
->dec_handle
)
146 dlclose(sh_video
->dec_handle
);
148 vf_uninit_filter_chain(sh_video
->vfilter
);
154 mp_msg(MSGT_DECVIDEO
,MSGL_INFO
,MSGTR_AvailableVideoFm
);
155 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VIDEO_DRIVERS\n");
156 mp_msg(MSGT_DECVIDEO
,MSGL_INFO
," vfm: info: (comment)\n");
157 for (i
=0; mpcodecs_vd_drivers
[i
] != NULL
; i
++)
158 mp_msg(MSGT_DECVIDEO
,MSGL_INFO
,"%8s %s (%s)\n",
159 mpcodecs_vd_drivers
[i
]->info
->short_name
,
160 mpcodecs_vd_drivers
[i
]->info
->name
,
161 mpcodecs_vd_drivers
[i
]->info
->comment
);
164 int init_video(sh_video_t
*sh_video
,char* codecname
,char* vfm
,int status
){
166 unsigned int orig_fourcc
=sh_video
->bih
?sh_video
->bih
->biCompression
:0;
167 sh_video
->codec
=NULL
;
168 sh_video
->vf_inited
=0;
169 if (codecname
&& codecname
[0] == '+') {
170 codecname
= &codecname
[1];
176 // restore original fourcc:
177 if(sh_video
->bih
) sh_video
->bih
->biCompression
=orig_fourcc
;
178 if(!(sh_video
->codec
=find_video_codec(sh_video
->format
,
179 sh_video
->bih
?((unsigned int*) &sh_video
->bih
->biCompression
):NULL
,
180 sh_video
->codec
,force
) )) break;
181 // ok we found one codec
182 if(sh_video
->codec
->flags
&CODECS_FLAG_SELECTED
) continue; // already tried & failed
183 if(codecname
&& strcmp(sh_video
->codec
->name
,codecname
)) continue; // -vc
184 if(vfm
&& strcmp(sh_video
->codec
->drv
,vfm
)) continue; // vfm doesn't match
185 if(!force
&& sh_video
->codec
->status
<status
) continue; // too unstable
186 sh_video
->codec
->flags
|=CODECS_FLAG_SELECTED
; // tagging it
187 // ok, it matches all rules, let's find the driver!
188 for (i
=0; mpcodecs_vd_drivers
[i
] != NULL
; i
++)
189 // if(mpcodecs_vd_drivers[i]->info->id==sh_video->codec->driver) break;
190 if(!strcmp(mpcodecs_vd_drivers
[i
]->info
->short_name
,sh_video
->codec
->drv
)) break;
191 mpvdec
=mpcodecs_vd_drivers
[i
];
192 #ifdef DYNAMIC_PLUGINS
195 /* try to open shared decoder plugin */
198 vd_functions_t
*funcs_sym
;
201 buf_len
= strlen(MPLAYER_LIBDIR
)+strlen(sh_video
->codec
->drv
)+16;
202 buf
= malloc(buf_len
);
205 snprintf(buf
, buf_len
, "%s/mplayer/vd_%s.so", MPLAYER_LIBDIR
, sh_video
->codec
->drv
);
206 mp_msg(MSGT_DECVIDEO
, MSGL_DBG2
, "Trying to open external plugin: %s\n", buf
);
207 sh_video
->dec_handle
= dlopen(buf
, RTLD_LAZY
);
208 if (!sh_video
->dec_handle
)
210 snprintf(buf
, buf_len
, "mpcodecs_vd_%s", sh_video
->codec
->drv
);
211 funcs_sym
= dlsym(sh_video
->dec_handle
, buf
);
212 if (!funcs_sym
|| !funcs_sym
->info
|| !funcs_sym
->init
||
213 !funcs_sym
->uninit
|| !funcs_sym
->control
|| !funcs_sym
->decode
)
215 info_sym
= funcs_sym
->info
;
216 if (strcmp(info_sym
->short_name
, sh_video
->codec
->drv
))
220 mp_msg(MSGT_DECVIDEO
, MSGL_V
, "Using external decoder plugin (%s/mplayer/vd_%s.so)!\n",
221 MPLAYER_LIBDIR
, sh_video
->codec
->drv
);
224 if(!mpvdec
){ // driver not available (==compiled in)
225 mp_msg(MSGT_DECVIDEO
,MSGL_WARN
,MSGTR_VideoCodecFamilyNotAvailableStr
,
226 sh_video
->codec
->name
, sh_video
->codec
->drv
);
229 // it's available, let's try to init!
230 if(sh_video
->codec
->flags
& CODECS_FLAG_ALIGN16
){
231 // align width/height to n*16
232 // FIXME: save orig w/h, and restore if codec init failed!
234 sh_video
->disp_w
=sh_video
->bih
->biWidth
=(sh_video
->bih
->biWidth
+15)&(~15);
235 sh_video
->disp_h
=sh_video
->bih
->biHeight
=(sh_video
->bih
->biHeight
+15)&(~15);
237 sh_video
->disp_w
=(sh_video
->disp_w
+15)&(~15);
238 sh_video
->disp_h
=(sh_video
->disp_h
+15)&(~15);
242 mp_msg(MSGT_DECVIDEO
,MSGL_INFO
,MSGTR_OpeningVideoDecoder
,mpvdec
->info
->short_name
,mpvdec
->info
->name
);
243 if(!mpvdec
->init(sh_video
)){
244 mp_msg(MSGT_DECVIDEO
,MSGL_INFO
,MSGTR_VDecoderInitFailed
);
245 continue; // try next...
254 extern char *get_path(char *filename
);
256 int init_best_video_codec(sh_video_t
*sh_video
,char** video_codec_list
,char** video_fm_list
){
257 char* vc_l_default
[2]={"",(char*)NULL
};
259 if(!video_codec_list
) video_codec_list
=vc_l_default
;
260 // Go through the codec.conf and find the best codec...
262 codecs_reset_selection(0);
263 while(!sh_video
->inited
&& *video_codec_list
){
264 char* video_codec
=*(video_codec_list
++);
266 if(video_codec
[0]=='-'){
267 // disable this codec:
268 select_codec(video_codec
+1,0);
270 // forced codec by name:
271 mp_msg(MSGT_DECVIDEO
,MSGL_INFO
,MSGTR_ForcedVideoCodec
,video_codec
);
272 init_video(sh_video
,video_codec
,NULL
,-1);
276 // try in stability order: UNTESTED, WORKING, BUGGY. never try CRASHING.
278 char** fmlist
=video_fm_list
;
279 // try first the preferred codec families:
280 while(!sh_video
->inited
&& *fmlist
){
281 char* video_fm
=*(fmlist
++);
282 mp_msg(MSGT_DECVIDEO
,MSGL_INFO
,MSGTR_TryForceVideoFmtStr
,video_fm
);
283 for(status
=CODECS_STATUS__MAX
;status
>=CODECS_STATUS__MIN
;--status
)
284 if(init_video(sh_video
,NULL
,video_fm
,status
)) break;
287 if(!sh_video
->inited
)
288 for(status
=CODECS_STATUS__MAX
;status
>=CODECS_STATUS__MIN
;--status
)
289 if(init_video(sh_video
,NULL
,NULL
,status
)) break;
293 if(!sh_video
->inited
){
294 mp_msg(MSGT_DECVIDEO
,MSGL_ERR
,MSGTR_CantFindVideoCodec
,sh_video
->format
);
295 mp_msg(MSGT_DECAUDIO
,MSGL_HINT
, MSGTR_RTFMCodecs
);
299 mp_msg(MSGT_DECVIDEO
,MSGL_INFO
,MSGTR_SelectedVideoCodec
,
300 sh_video
->codec
->name
,sh_video
->codec
->drv
,sh_video
->codec
->info
);
304 extern int vo_directrendering
;
306 int decode_video(sh_video_t
*sh_video
,unsigned char *start
,int in_size
,int drop_frame
, double pts
){
308 mp_image_t
*mpi
=NULL
;
309 unsigned int t
=GetTimer();
314 //if(!(sh_video->ds->flags&1) || sh_video->ds->pack_no<5)
315 mpi
=mpvdec
->decode(sh_video
, start
, in_size
, drop_frame
);
317 //------------------------ frame decoded. --------------------
320 // some codecs are broken, and doesn't restore MMX state :(
321 // it happens usually with broken/damaged files.
322 if(gCpuCaps
.has3DNow
){
323 __asm
__volatile ("femms\n\t":::"memory");
325 else if(gCpuCaps
.hasMMX
){
326 __asm
__volatile ("emms\n\t":::"memory");
330 t2
=GetTimer();t
=t2
-t
;
332 video_time_usage
+=tt
;
334 if(!mpi
|| drop_frame
) return 0; // error / skipped frame
336 //vo_draw_image(video_out,mpi);
337 vf
=sh_video
->vfilter
;
338 ret
= vf
->put_image(vf
,mpi
, pts
); // apply video filters and call the leaf vo/ve
339 if(ret
>0) vf
->control(vf
,VFCTRL_DRAW_OSD
,NULL
);