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_INFO
,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_DECVIDEO
,MSGL_INFO
," vfm: info: (comment)\n");
156 for (i
=0; mpcodecs_vd_drivers
[i
] != NULL
; i
++)
157 mp_msg(MSGT_DECVIDEO
,MSGL_INFO
,"%8s %s (%s)\n",
158 mpcodecs_vd_drivers
[i
]->info
->short_name
,
159 mpcodecs_vd_drivers
[i
]->info
->name
,
160 mpcodecs_vd_drivers
[i
]->info
->comment
);
163 int init_video(sh_video_t
*sh_video
,char* codecname
,char* vfm
,int status
){
164 unsigned int orig_fourcc
=sh_video
->bih
?sh_video
->bih
->biCompression
:0;
165 sh_video
->codec
=NULL
;
166 sh_video
->vf_inited
=0;
170 // restore original fourcc:
171 if(sh_video
->bih
) sh_video
->bih
->biCompression
=orig_fourcc
;
172 if(!(sh_video
->codec
=find_codec(sh_video
->format
,
173 sh_video
->bih
?((unsigned int*) &sh_video
->bih
->biCompression
):NULL
,
174 sh_video
->codec
,0) )) break;
175 // ok we found one codec
176 if(sh_video
->codec
->flags
&CODECS_FLAG_SELECTED
) continue; // already tried & failed
177 if(codecname
&& strcmp(sh_video
->codec
->name
,codecname
)) continue; // -vc
178 if(vfm
&& strcmp(sh_video
->codec
->drv
,vfm
)) continue; // vfm doesn't match
179 if(sh_video
->codec
->status
<status
) continue; // too unstable
180 sh_video
->codec
->flags
|=CODECS_FLAG_SELECTED
; // tagging it
181 // ok, it matches all rules, let's find the driver!
182 for (i
=0; mpcodecs_vd_drivers
[i
] != NULL
; i
++)
183 // if(mpcodecs_vd_drivers[i]->info->id==sh_video->codec->driver) break;
184 if(!strcmp(mpcodecs_vd_drivers
[i
]->info
->short_name
,sh_video
->codec
->drv
)) break;
185 mpvdec
=mpcodecs_vd_drivers
[i
];
186 #ifdef DYNAMIC_PLUGINS
189 /* try to open shared decoder plugin */
192 vd_functions_t
*funcs_sym
;
195 buf_len
= strlen(MPLAYER_LIBDIR
)+strlen(sh_video
->codec
->drv
)+16;
196 buf
= malloc(buf_len
);
199 snprintf(buf
, buf_len
, "%s/mplayer/vd_%s.so", MPLAYER_LIBDIR
, sh_video
->codec
->drv
);
200 mp_msg(MSGT_DECVIDEO
, MSGL_DBG2
, "Trying to open external plugin: %s\n", buf
);
201 sh_video
->dec_handle
= dlopen(buf
, RTLD_LAZY
);
202 if (!sh_video
->dec_handle
)
204 snprintf(buf
, buf_len
, "mpcodecs_vd_%s", sh_video
->codec
->drv
);
205 funcs_sym
= dlsym(sh_video
->dec_handle
, buf
);
206 if (!funcs_sym
|| !funcs_sym
->info
|| !funcs_sym
->init
||
207 !funcs_sym
->uninit
|| !funcs_sym
->control
|| !funcs_sym
->decode
)
209 info_sym
= funcs_sym
->info
;
210 if (strcmp(info_sym
->short_name
, sh_video
->codec
->drv
))
214 mp_msg(MSGT_DECVIDEO
, MSGL_V
, "Using external decoder plugin (%s/mplayer/vd_%s.so)!\n",
215 MPLAYER_LIBDIR
, sh_video
->codec
->drv
);
218 if(!mpvdec
){ // driver not available (==compiled in)
219 mp_msg(MSGT_DECVIDEO
,MSGL_WARN
,MSGTR_VideoCodecFamilyNotAvailableStr
,
220 sh_video
->codec
->name
, sh_video
->codec
->drv
);
223 // it's available, let's try to init!
224 if(sh_video
->codec
->flags
& CODECS_FLAG_ALIGN16
){
225 // align width/height to n*16
226 // FIXME: save orig w/h, and restore if codec init failed!
228 sh_video
->disp_w
=sh_video
->bih
->biWidth
=(sh_video
->bih
->biWidth
+15)&(~15);
229 sh_video
->disp_h
=sh_video
->bih
->biHeight
=(sh_video
->bih
->biHeight
+15)&(~15);
231 sh_video
->disp_w
=(sh_video
->disp_w
+15)&(~15);
232 sh_video
->disp_h
=(sh_video
->disp_h
+15)&(~15);
236 mp_msg(MSGT_DECVIDEO
,MSGL_INFO
,MSGTR_OpeningVideoDecoder
,mpvdec
->info
->short_name
,mpvdec
->info
->name
);
237 if(!mpvdec
->init(sh_video
)){
238 mp_msg(MSGT_DECVIDEO
,MSGL_INFO
,MSGTR_VDecoderInitFailed
);
239 continue; // try next...
248 extern char *get_path(char *filename
);
250 int init_best_video_codec(sh_video_t
*sh_video
,char** video_codec_list
,char** video_fm_list
){
251 char* vc_l_default
[2]={"",(char*)NULL
};
253 if(!video_codec_list
) video_codec_list
=vc_l_default
;
254 // Go through the codec.conf and find the best codec...
256 codecs_reset_selection(0);
257 while(!sh_video
->inited
&& *video_codec_list
){
258 char* video_codec
=*(video_codec_list
++);
260 if(video_codec
[0]=='-'){
261 // disable this codec:
262 select_codec(video_codec
+1,0);
264 // forced codec by name:
265 mp_msg(MSGT_DECVIDEO
,MSGL_INFO
,MSGTR_ForcedVideoCodec
,video_codec
);
266 init_video(sh_video
,video_codec
,NULL
,-1);
270 // try in stability order: UNTESTED, WORKING, BUGGY. never try CRASHING.
272 char** fmlist
=video_fm_list
;
273 // try first the preferred codec families:
274 while(!sh_video
->inited
&& *fmlist
){
275 char* video_fm
=*(fmlist
++);
276 mp_msg(MSGT_DECVIDEO
,MSGL_INFO
,MSGTR_TryForceVideoFmtStr
,video_fm
);
277 for(status
=CODECS_STATUS__MAX
;status
>=CODECS_STATUS__MIN
;--status
)
278 if(init_video(sh_video
,NULL
,video_fm
,status
)) break;
281 if(!sh_video
->inited
)
282 for(status
=CODECS_STATUS__MAX
;status
>=CODECS_STATUS__MIN
;--status
)
283 if(init_video(sh_video
,NULL
,NULL
,status
)) break;
287 if(!sh_video
->inited
){
288 mp_msg(MSGT_DECVIDEO
,MSGL_ERR
,MSGTR_CantFindVideoCodec
,sh_video
->format
);
289 mp_msg(MSGT_DECAUDIO
,MSGL_HINT
, MSGTR_RTFMCodecs
);
293 mp_msg(MSGT_DECVIDEO
,MSGL_INFO
,"Selected video codec: [%s] vfm:%s (%s)\n",
294 sh_video
->codec
->name
,sh_video
->codec
->drv
,sh_video
->codec
->info
);
298 extern int vo_directrendering
;
300 int decode_video(sh_video_t
*sh_video
,unsigned char *start
,int in_size
,int drop_frame
){
302 mp_image_t
*mpi
=NULL
;
303 unsigned int t
=GetTimer();
308 //if(!(sh_video->ds->flags&1) || sh_video->ds->pack_no<5)
309 mpi
=mpvdec
->decode(sh_video
, start
, in_size
, drop_frame
);
311 //------------------------ frame decoded. --------------------
314 // some codecs are broken, and doesn't restore MMX state :(
315 // it happens usually with broken/damaged files.
316 if(gCpuCaps
.has3DNow
){
317 __asm
__volatile ("femms\n\t":::"memory");
319 else if(gCpuCaps
.hasMMX
){
320 __asm
__volatile ("emms\n\t":::"memory");
324 t2
=GetTimer();t
=t2
-t
;
326 video_time_usage
+=tt
;
328 if(!mpi
|| drop_frame
) return 0; // error / skipped frame
330 //vo_draw_image(video_out,mpi);
331 vf
=sh_video
->vfilter
;
332 ret
= vf
->put_image(vf
,mpi
); // apply video filters and call the leaf vo/ve
333 if(ret
>0) vf
->control(vf
,VFCTRL_DRAW_OSD
,NULL
);