Initial import of MPlayer SVN rev 28382 and FFmpeg SVN rev 16846.
[vaapi:mplayer.git] / libmpcodecs / vf_pp.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <inttypes.h>
5 #include <errno.h>
6
7 #include "config.h"
8 #include "mp_msg.h"
9 #include "cpudetect.h"
10
11 #ifdef HAVE_MALLOC_H
12 #include <malloc.h>
13 #endif
14
15 #include "img_format.h"
16 #include "mp_image.h"
17 #include "vf.h"
18 #include "libavutil/internal.h"
19 #include "libpostproc/postprocess.h"
20
21 #ifdef CONFIG_LIBPOSTPROC_A
22 #define EMU_OLD
23 #include "libpostproc/postprocess_internal.h"
24 #endif
25
26 #undef malloc
27
28 struct vf_priv_s {
29     int pp;
30     pp_mode_t *ppMode[PP_QUALITY_MAX+1];
31     void *context;
32     unsigned int outfmt;
33 };
34
35 //===========================================================================//
36
37 static int config(struct vf_instance_s* vf,
38         int width, int height, int d_width, int d_height,
39         unsigned int voflags, unsigned int outfmt){
40     int flags=
41           (gCpuCaps.hasMMX   ? PP_CPU_CAPS_MMX   : 0)
42         | (gCpuCaps.hasMMX2  ? PP_CPU_CAPS_MMX2  : 0)
43         | (gCpuCaps.has3DNow ? PP_CPU_CAPS_3DNOW : 0);
44
45     switch(outfmt){
46     case IMGFMT_444P: flags|= PP_FORMAT_444; break;
47     case IMGFMT_422P: flags|= PP_FORMAT_422; break;
48     case IMGFMT_411P: flags|= PP_FORMAT_411; break;
49     default:          flags|= PP_FORMAT_420; break;
50     }
51         
52     if(vf->priv->context) pp_free_context(vf->priv->context);
53     vf->priv->context= pp_get_context(width, height, flags);
54
55     return vf_next_config(vf,width,height,d_width,d_height,voflags,outfmt);
56 }
57
58 static void uninit(struct vf_instance_s* vf){
59     int i;
60     for(i=0; i<=PP_QUALITY_MAX; i++){
61         if(vf->priv->ppMode[i])
62             pp_free_mode(vf->priv->ppMode[i]);
63     }
64     if(vf->priv->context) pp_free_context(vf->priv->context);
65 }
66
67 static int query_format(struct vf_instance_s* vf, unsigned int fmt){
68     switch(fmt){
69     case IMGFMT_YV12:
70     case IMGFMT_I420:
71     case IMGFMT_IYUV:
72     case IMGFMT_444P:
73     case IMGFMT_422P:
74     case IMGFMT_411P:
75         return vf_next_query_format(vf,fmt);
76     }
77     return 0;
78 }
79
80 static int control(struct vf_instance_s* vf, int request, void* data){
81     switch(request){
82     case VFCTRL_QUERY_MAX_PP_LEVEL:
83         return PP_QUALITY_MAX;
84     case VFCTRL_SET_PP_LEVEL:
85         vf->priv->pp= *((unsigned int*)data);
86         return CONTROL_TRUE;
87     }
88     return vf_next_control(vf,request,data);
89 }
90
91 static void get_image(struct vf_instance_s* vf, mp_image_t *mpi){
92     if(vf->priv->pp&0xFFFF) return; // non-local filters enabled
93     if((mpi->type==MP_IMGTYPE_IPB || vf->priv->pp) && 
94         mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
95     if(!(mpi->flags&MP_IMGFLAG_ACCEPT_STRIDE) && mpi->imgfmt!=vf->priv->outfmt)
96         return; // colorspace differ
97     // ok, we can do pp in-place (or pp disabled):
98     vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
99         mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height);
100     mpi->planes[0]=vf->dmpi->planes[0];
101     mpi->stride[0]=vf->dmpi->stride[0];
102     mpi->width=vf->dmpi->width;
103     if(mpi->flags&MP_IMGFLAG_PLANAR){
104         mpi->planes[1]=vf->dmpi->planes[1];
105         mpi->planes[2]=vf->dmpi->planes[2];
106         mpi->stride[1]=vf->dmpi->stride[1];
107         mpi->stride[2]=vf->dmpi->stride[2];
108     }
109     mpi->flags|=MP_IMGFLAG_DIRECT;
110 }
111
112 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts){
113     if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
114         // no DR, so get a new image! hope we'll get DR buffer:
115         vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
116             MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE |
117             MP_IMGFLAG_PREFER_ALIGNED_STRIDE | MP_IMGFLAG_READABLE,
118 //          MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
119 //          mpi->w,mpi->h);
120             (mpi->width+7)&(~7),(mpi->height+7)&(~7));
121         vf->dmpi->w=mpi->w; vf->dmpi->h=mpi->h; // display w;h
122     }
123     
124     if(vf->priv->pp || !(mpi->flags&MP_IMGFLAG_DIRECT)){
125         // do the postprocessing! (or copy if no DR)
126         pp_postprocess(mpi->planes           ,mpi->stride,
127                     vf->dmpi->planes,vf->dmpi->stride,
128                     (mpi->w+7)&(~7),mpi->h,
129                     mpi->qscale, mpi->qstride,
130                     vf->priv->ppMode[ vf->priv->pp ], vf->priv->context,
131 #ifdef PP_PICT_TYPE_QP2
132                     mpi->pict_type | (mpi->qscale_type ? PP_PICT_TYPE_QP2 : 0));
133 #else
134                     mpi->pict_type);
135 #endif
136     }
137     return vf_next_put_image(vf,vf->dmpi, pts);
138 }
139
140 //===========================================================================//
141
142 extern int divx_quality;
143
144 static unsigned int fmt_list[]={
145     IMGFMT_YV12,
146     IMGFMT_I420,
147     IMGFMT_IYUV,
148     IMGFMT_444P,
149     IMGFMT_422P,
150     IMGFMT_411P,
151     0
152 };
153
154 static int open(vf_instance_t *vf, char* args){
155     char *endptr, *name;
156     int i;
157     int hex_mode=0;
158     
159     vf->query_format=query_format;
160     vf->control=control;
161     vf->config=config;
162     vf->get_image=get_image;
163     vf->put_image=put_image;
164     vf->uninit=uninit;
165     vf->default_caps=VFCAP_ACCEPT_STRIDE|VFCAP_POSTPROC;
166     vf->priv=malloc(sizeof(struct vf_priv_s));
167     vf->priv->context=NULL;
168
169     // check csp:
170     vf->priv->outfmt=vf_match_csp(&vf->next,fmt_list,IMGFMT_YV12);
171     if(!vf->priv->outfmt) return 0; // no csp match :(
172     
173     if(args){
174         hex_mode= strtol(args, &endptr, 0);
175         if(*endptr){
176             name= args;
177         }else
178             name= NULL;
179     }else{
180         name="de";
181     }
182
183 #ifdef EMU_OLD
184     if(name){
185 #endif
186         for(i=0; i<=PP_QUALITY_MAX; i++){
187             vf->priv->ppMode[i]= pp_get_mode_by_name_and_quality(name, i);
188             if(vf->priv->ppMode[i]==NULL) return -1;
189         }
190 #ifdef EMU_OLD
191     }else{
192         /* hex mode for compatibility */
193         for(i=0; i<=PP_QUALITY_MAX; i++){
194             PPMode *ppMode;
195             
196             ppMode= (PPMode*)memalign(8, sizeof(PPMode));
197             
198             ppMode->lumMode= hex_mode;
199             ppMode->chromMode= ((hex_mode&0xFF)>>4) | (hex_mode&0xFFFFFF00);
200             ppMode->maxTmpNoise[0]= 700;
201             ppMode->maxTmpNoise[1]= 1500;
202             ppMode->maxTmpNoise[2]= 3000;
203             ppMode->maxAllowedY= 234;
204             ppMode->minAllowedY= 16;
205             ppMode->baseDcDiff= 256/4;
206             ppMode->flatnessThreshold=40;
207     
208             vf->priv->ppMode[i]= ppMode;
209         }
210     }
211 #endif
212     
213     vf->priv->pp=PP_QUALITY_MAX;
214     return 1;
215 }
216
217 const vf_info_t vf_info_pp = {
218     "postprocessing",
219     "pp",
220     "A'rpi",
221     "",
222     open,
223     NULL
224 };
225
226 //===========================================================================//
227