Color::Color(PClip _child, double _gain_y, double _off_y, double _gamma_y, double _cont_y, double _gain_u, double _off_u, double _gamma_u, double _cont_u, double _gain_v, double _off_v, double _gamma_v, double _cont_v, const char *_levels, const char *_opt, const char *_matrix, bool _colorbars, bool _analyze, bool _autowhite, bool _autogain, bool _conditional, IScriptEnvironment* env) : GenericVideoFilter(_child), y_gain(_gain_y), y_bright(_off_y), y_gamma(_gamma_y),y_contrast(_cont_y), u_gain(_gain_u), u_bright(_off_u), u_gamma(_gamma_u),u_contrast(_cont_u), v_gain(_gain_v), v_bright(_off_v), v_gamma(_gamma_v),v_contrast(_cont_v), conditional(_conditional) { try { // HIDE DAMN SEH COMPILER BUG!!! if (!vi.IsYUV()) env->ThrowError("ColorYUV: requires YUV input"); if (!CheckParms(_levels, _matrix, _opt)) { if (levels < 0) env->ThrowError("ColorYUV: parameter error : levels"); if (matrix < 0) env->ThrowError("ColorYUV: parameter error : matrix"); if (opt < 0) env->ThrowError("ColorYUV: parameter error : opt"); } colorbars=_colorbars; analyze=_analyze; autowhite=_autowhite; autogain=_autogain; MakeGammaLUT(); if (colorbars) { vi.height=224*2; vi.width=224*2; vi.pixel_type=VideoInfo::CS_YV12; } } catch (...) { throw; } }
/** \fn ctor */ vidColorYuv::vidColorYuv( ADM_coreVideoFilter *in,CONFcouple *setup) : ADM_coreVideoFilter(in,setup) { if(!setup || !ADM_paramLoad(setup,colorYuv_param,¶m)) { // Default value #define MKP(x,y) param.x=y; MKP(y_contrast,0); MKP(y_bright,0); MKP(y_gamma,0); MKP(y_gain,0); MKP(u_contrast,0); MKP(u_bright,0); MKP(u_gamma,0); MKP(u_gain,0); MKP(v_contrast,0); MKP(v_bright,0); MKP(v_gamma,0); MKP(v_gain,0); MKP(matrix,0); MKP(levels,0); MKP(opt,0); MKP(colorbars,0); MKP(analyze,1); MKP(autowhite,1); MKP(autogain,0); } MakeGammaLUT(); }
/** \fn configure */ bool vidColorYuv::configure(void) { bool r=false; // --- Tab 1 ---- #define PX(x) (&(param.x)) diaElemToggle tAutoWhite(PX(autowhite),QT_TRANSLATE_NOOP("coloryuv","AutoWhite")); diaElemToggle tAutoGain(PX(autogain),QT_TRANSLATE_NOOP("coloryuv","AutoGain")); diaElemToggle tOpt(PX(opt),QT_TRANSLATE_NOOP("coloryuv","Clip to Tv Range (16-235)")); diaMenuEntry levelMenus[]={{0,QT_TRANSLATE_NOOP("coloryuv","None"),NULL}, {1,QT_TRANSLATE_NOOP("coloryuv","PC->TV"),NULL}, {2,QT_TRANSLATE_NOOP("coloryuv","TV->PC"),NULL}}; // levels case 1: // PC->TV Scale case 2: // TV->PC Scale case 0: //none diaElemMenu mLevel(PX(levels),QT_TRANSLATE_NOOP("coloryuv","Levels:"), sizeof(levelMenus)/sizeof(diaMenuEntry),levelMenus,""); diaElem *dia1[]={&tAutoWhite,&tAutoGain,&tOpt,&mLevel}; // diaElemFloat(ELEM_TYPE_FLOAT *intValue,const char *toggleTitle, ELEM_TYPE_FLOAT min, // ELEM_TYPE_FLOAT max,const char *tip=NULL, int decimals = 2); // --- Tab 2 ---- diaElemFloat yGain(PX(y_gain),QT_TRANSLATE_NOOP("coloryuv","Y gain"),0,256*3,NULL,3); diaElemFloat yBright(PX(y_bright),QT_TRANSLATE_NOOP("coloryuv","Y Brightness"),0,256*3,NULL,3); diaElemFloat yGamma(PX(y_gamma),QT_TRANSLATE_NOOP("coloryuv","Y Gamma"),0,256*2,NULL,3); diaElemFloat yContrast(PX(y_contrast),QT_TRANSLATE_NOOP("coloryuv","Y Contrast"),-256*3,256*3,NULL,3); diaElem *dia2[]={&yGain,&yBright,&yGamma,&yContrast}; // --- Tab 3 ---- diaElemFloat uGain(PX(u_gain),QT_TRANSLATE_NOOP("coloryuv","U gain"),0,256*3,NULL,3); diaElemFloat uBright(PX(u_bright),QT_TRANSLATE_NOOP("coloryuv","U Brightness"),0,256*3,NULL,3); //diaElemFloat uGamma(PX(u_gamma),QT_TRANSLATE_NOOP("coloryuv","U Gamma"),0,100,NULL,3); diaElemFloat uContrast(PX(u_contrast),QT_TRANSLATE_NOOP("coloryuv","U Contrast"),-256*3,256*3,NULL,3); diaElem *dia3[]={&uGain,&uBright,&uContrast}; // --- Tab 4 ---- diaElemFloat vGain(PX(v_gain),QT_TRANSLATE_NOOP("coloryuv","V gain"),0,256*3,NULL,3); diaElemFloat vBright(PX(v_bright),QT_TRANSLATE_NOOP("coloryuv","V Brightness"),0,256*3,NULL,3); //diaElemFloat vGamma(PX(u_gamma),QT_TRANSLATE_NOOP("coloryuv","V Gamma"),0,100,NULL,3); diaElemFloat vContrast(PX(v_contrast),QT_TRANSLATE_NOOP("coloryuv","V Contrast"),-256*3,256*3,NULL,3); diaElem *dia4[]={&vGain,&vBright,&vContrast}; // diaElemTabs tab1(QT_TRANSLATE_NOOP("coloryuv","Flags"),4,dia1); diaElemTabs tab2(QT_TRANSLATE_NOOP("coloryuv","Y"),4,dia2); diaElemTabs tab3(QT_TRANSLATE_NOOP("coloryuv","U"),3,dia3); diaElemTabs tab4(QT_TRANSLATE_NOOP("coloryuv","V"),3,dia4); diaElemTabs *tabs[]={&tab1,&tab2,&tab3,&tab4}; if( diaFactoryRunTabs(QT_TRANSLATE_NOOP("coloryuv","colorYuv"),4,tabs)) { r=true; } MakeGammaLUT(); return r; }
/** \fn getNextFrame */ bool vidColorYuv::getNextFrame(uint32_t *fn,ADMImage *image) { //x PVideoFrame src; //x unsigned long *srcp; uint8_t *srcp; int pitch, w, h; int i,j,wby4; int modulo; #if 0 //ifdef _DEBUG COUNT y0,u0,v0; COUNT y,u,v; COUNT r,g,b; COUNT r0,g0,b0; PIXELDATA pixel0; int total,totalby2; #endif #if 0 if (colorbars) { PVideoFrame dst= env->NewVideoFrame(vi); int* pdst=(int*)dst->GetWritePtr(PLANAR_Y); int Y=16+abs(219-((frame+219)%438)); Y|=(Y<<8)|(Y<<16)|(Y<<24); for (int i = 0;i<224*224;i++) pdst[i] = Y; unsigned char* pdstb = dst->GetWritePtr(PLANAR_U); for (unsigned int y=0;y<224;y++) { for (unsigned int x=0;x<224;x++) { pdstb[x] = 16+x; } pdstb += dst->GetPitch(PLANAR_U); } pdstb = dst->GetWritePtr(PLANAR_V); for (y=0;y<224;y++) { for (unsigned int x=0;x<224;x++) { pdstb[x] = 16+y; } pdstb += dst->GetPitch(PLANAR_U); } return dst; } #endif if(false==previousFilter->getNextFrame(fn,image)) { return false; } ADMImage *src=image; //x src = child->GetFrame(frame, env); //x env->MakeWritable(&src); //x srcp = (unsigned long *) src->GetWritePtr(); //x pitch = src->GetPitch(); srcp=src->GetWritePtr(PLANAR_Y); pitch=src->GetPitch(PLANAR_Y); w = info.width; //x src->GetRowSize(); h = info.height; //x src->GetHeight(); wby4 = w / 4; modulo = pitch - w; // dst = env->NewVideoFrame(vi); // dstp = (unsigned long *) dst->GetWritePtr(); // dpitch = dst->GetPitch(); // dmodulo = dpitch - dst->GetRowSize(); if (param.analyze||param.autowhite||param.autogain) { unsigned int accum_Y[256],accum_U[256],accum_V[256]; for (int i=0;i<256;i++) { accum_Y[i]=0; accum_U[i]=0; accum_V[i]=0; } int uvdiv=1; //UV divider (ratio between Y and UV pixels) if (1) { //x vi.IsPlanar()) { uvdiv=4; BYTE* srcp2 = (BYTE*) src->GetReadPtr(PLANAR_Y); for (int y=0;y<h;y++) { for (int x=0;x<w;x++) { accum_Y[srcp2[x]]++; } srcp2+=pitch; } pitch = src->GetPitch(PLANAR_U); srcp2 = (BYTE*) src->GetReadPtr(PLANAR_U); for (int y=0;y<h/2;y++) { for (int x=0;x<w/2;x++) { accum_U[srcp2[x]]++; } srcp2+=pitch; } srcp2 = (BYTE*) src->GetReadPtr(PLANAR_V); for (int y=0;y<h/2;y++) { for (int x=0;x<w/2;x++) { accum_V[srcp2[x]]++; } srcp2+=pitch; } pitch = src->GetPitch(PLANAR_Y); } #if 0 else { // YUY2 uvdiv=2; for (int y=0;y<h;y++) { for (int x=0;x<wby4;x++) { unsigned long p=srcp[x]; accum_Y[p&0xff]++; accum_Y[(p>>16)&0xff]++; accum_U[(p>>8)&0xff]++; accum_V[(p>>24)&0xff]++; } srcp+=pitch/4; } srcp=(unsigned long *)src->GetReadPtr(); } #endif int pixels = info.width*info.height; float avg_u=0, avg_v=0, avg_y=0; int x_min_u=0, x_min_v=0, x_min_y=0; int x_max_u=0, x_max_v=0, x_max_y=0; bool hit_y=false,hit_u=false,hit_v=false; int Ax_min_u=0, Ax_min_v=0, Ax_min_y=0; int Ax_max_u=0, Ax_max_v=0, Ax_max_y=0; bool Ahit_x_miny=false,Ahit_x_minu=false,Ahit_x_minv=false; bool Ahit_x_maxy=false,Ahit_x_maxu=false,Ahit_x_maxv=false; int At_y2=(pixels/256); // When 1/256th of all pixels have been reached, trigger "Loose x_min/x_max" int At_uv2=(pixels/1024); for (int i=0;i<256;i++) { avg_y+=(float)accum_Y[i]*(float)i; avg_u+=(float)accum_U[i]*(float)i; avg_v+=(float)accum_V[i]*(float)i; if (accum_Y[i]!=0) {x_max_y=i;hit_y=true;} else {if (!hit_y) x_min_y=i+1;} if (accum_U[i]!=0) {x_max_u=i;hit_u=true;} else {if (!hit_u) x_min_u=i+1;} if (accum_V[i]!=0) {x_max_v=i;hit_v=true;} else {if (!hit_v) x_min_v=i+1;} if (!Ahit_x_miny) {Ax_min_y+=accum_Y[i]; if (Ax_min_y>At_y2){Ahit_x_miny=true; Ax_min_y=i;} } if (!Ahit_x_minu) {Ax_min_u+=accum_U[i]; if (Ax_min_u>At_uv2){Ahit_x_minu=true; Ax_min_u=i;} } if (!Ahit_x_minv) {Ax_min_v+=accum_V[i]; if (Ax_min_v>At_uv2){Ahit_x_minv=true; Ax_min_v=i;} } if (!Ahit_x_maxy) {Ax_max_y+=accum_Y[255-i]; if (Ax_max_y>At_y2){Ahit_x_maxy=true; Ax_max_y=255-i;} } if (!Ahit_x_maxu) {Ax_max_u+=accum_U[255-i]; if (Ax_max_u>At_uv2){Ahit_x_maxu=true; Ax_max_u=255-i;} } if (!Ahit_x_maxv) {Ax_max_v+=accum_V[255-i]; if (Ax_max_v>At_uv2){Ahit_x_maxv=true; Ax_max_v=255-i;} } } float Favg_y=avg_y/(float)pixels; float Favg_u=(avg_u*(float)uvdiv)/(float)pixels; float Favg_v=(avg_v*(float)uvdiv)/(float)pixels; if (param.analyze) { #if 0 char text[400]; sprintf(text, " Frame: %-8u ( Luma Y / ChromaU / ChromaV )\n" " Average: ( %7.2f / %7.2f / %7.2f )\n" " x_minimum: ( %3d / %3d / %3d )\n" " x_maximum: ( %3d / %3d / %3d )\n" "Loose x_minimum: ( %3d / %3d / %3d )\n" "Loose x_maximum: ( %3d / %3d / %3d )\n" , frame, Favg_y,Favg_u,Favg_v, x_min_y,x_min_u,x_min_v, x_max_y,x_max_u,x_max_v, Ax_min_y,Ax_min_u,Ax_min_v, Ax_max_y,Ax_max_u,Ax_max_v ); ApplyMessage(&src, vi, text, vi.width/4, 0xa0a0a0,0,0 , env ); if (!(param.autowhite||param.autogain)) { return true; //x src; } #endif } if (param.autowhite) { param.u_bright=127-(int)Favg_u; param.v_bright=127-(int)Favg_v; } if (param.autogain) { Ax_max_y=x_min(Ax_max_y,236); Ax_min_y=x_max(Ax_min_y,16); // Never scale above luma range! if (Ax_min_y!=Ax_max_y) { int y_range = Ax_max_y-Ax_min_y; double scale = (220.0 / y_range); param.y_gain = (int) (256.0 * scale)-256; param.y_bright = -(int)(scale * (double)(Ax_min_y)-16); } } MakeGammaLUT(); }