/** \fn openGlBenchmark \brief constructor */ openGlBenchmark::openGlBenchmark( ADM_coreVideoFilter *in,CONFcouple *setup) : ADM_coreVideoFilterQtGl(in,setup) { UNUSED_ARG(setup); widget->makeCurrent(); fboY->bind(); printf("Compiling shader \n"); glProgramY = new QGLShaderProgram(context); ADM_assert(glProgramY); if ( !glProgramY->addShaderFromSourceCode(QGLShader::Fragment, myShaderY)) { ADM_error("[GL Render] Fragment log: %s\n", glProgramY->log().toUtf8().constData()); ADM_assert(0); } if ( !glProgramY->link()) { ADM_error("[GL Render] Link log: %s\n", glProgramY->log().toUtf8().constData()); ADM_assert(0); } if ( !glProgramY->bind()) { ADM_error("[GL Render] Binding FAILED\n"); ADM_assert(0); } fboY->release(); widget->doneCurrent(); }
/** \fn resetVdpau */ bool vdpauVideoFilterDeint::setupVdpau(void) { scaler=NULL; secondField=false; nextFrame=0; if(!admVdpau::isOperationnal()) { ADM_warning("Vdpau not operationnal\n"); return false; } if(VDP_STATUS_OK!=admVdpau::outputSurfaceCreate(VDP_RGBA_FORMAT_B8G8R8A8, info.width,info.height,&outputSurface)) { ADM_error("Cannot create outputSurface0\n"); return false; } for(int i=0;i<ADM_NB_SURFACES;i++) surfacePool[i]=VDP_INVALID_HANDLE; for(int i=0;i<ADM_NB_SURFACES;i++) { if(VDP_STATUS_OK!=admVdpau::surfaceCreate( previousFilter->getInfo()->width, previousFilter->getInfo()->height, &(surfacePool[i]))) { ADM_error("Cannot create input Surface %d\n",i); goto badInit; } aprintf("Created surface %d\n",(int)surfacePool[i]); } // allocate our (dummy) images for(int i=0;i<3;i++) xslots[i].image=new ADMImageDefault( previousFilter->getInfo()->width, previousFilter->getInfo()->height); if(VDP_STATUS_OK!=admVdpau::mixerCreate(previousFilter->getInfo()->width, previousFilter->getInfo()->height,&mixer,true)) { ADM_error("Cannot create mixer\n"); goto badInit; } tempBuffer=new uint8_t[info.width*info.height*4]; scaler=new ADMColorScalerSimple( info.width,info.height, ADM_COLOR_BGR32A,ADM_COLOR_YV12); freeSurface.clear(); for(int i=0;i<ADM_NB_SURFACES;i++) freeSurface.push_back(surfacePool[i]); ADM_info("VDPAU setup ok\n"); if(initGl()==false) { ADM_error("Cannot setup openGL\n"); goto badInit; } ADM_info("VDPAU setup ok\n"); return true; badInit: cleanupVdpau(); passThrough=true; return false; }
/** \fn samePicture \brief returns the last already decoded picture */ bool ADM_Composer::samePicture(ADMImage *image) { _SEGMENT *seg=_segments.getSegment(_currentSegment); _VIDEOS *ref=_segments.getRefVideo(seg->_reference); // Do Pts->ref PTs uint64_t refPts; uint64_t segTime; uint32_t segNo; if(false==_segments.convertLinearTimeToSeg(_currentPts,&segNo,&segTime)) { ADM_error("Cannot convert time in samePicture\n"); return false; } ADM_assert(_currentSegment==segNo); refPts=segTime+seg->_refStartTimeUs; ADMImage *last=ref->_videoCache->getByPts(refPts); if(last) { image->duplicate(last); updateImageTiming(seg,image); return true; } ADM_error("Cannot find same image in cache\n"); ADM_info("Looking for PTS=%"PRIu64" ms\n",refPts/1000); ref->_videoCache->dump(); return false; }
/** \fn ADM_copyFile */ uint8_t ADM_copyFile(const char *source, const char *target) { FILE *fin=ADM_fopen(source,"rb"); if(!fin) { ADM_error("Cannot open %s for reading\n",source); return false; } FILE *fout=ADM_fopen(target,"wb"); if(!fout) { fclose(fin); ADM_error("Cannot open %s for writting\n",target); return false; } uint8_t buffer[1024]; while(!feof(fin)) { int r=fread(buffer,1,1024,fin); fwrite(buffer,1,r,fout); if(r!=1024) break; } fclose(fin); fclose(fout); return true; }
/** \fn init */ bool vdpauRender::init( GUI_WindowInfo *window, uint32_t w, uint32_t h, float zoom) { if(!w || !h) { ADM_info("[VDPAU] Not trying to initialize with zero size dimensions\n"); return false; } ADM_info("[Vdpau]Init\n"); info=*window; if(admVdpau::isOperationnal()==false) { ADM_warning("[Vdpau] Not operationnal\n"); } baseInit(w,h,zoom); // Create couple of outputSurface surface[0]=surface[1]=VDP_INVALID_HANDLE; currentSurface=0; // int widthToUse=admVdpau::dimensionRoundUp(w); int heightToUse=admVdpau::dimensionRoundUp(h); ADM_info("[VDpau] Allocating surfaces %d x%d , %d x %d, %d x x%d\n",w,h,widthToUse,heightToUse,displayWidth,displayHeight); if(!reallocOutputSurface(displayWidth,displayHeight)) { goto badInit; } if(VDP_STATUS_OK!=admVdpau::surfaceCreate(widthToUse,heightToUse,&input)) { ADM_error("Cannot create input Surface\n"); goto badInit; } if(VDP_STATUS_OK!=admVdpau::presentationQueueCreate(&queue)) { ADM_error("Cannot create queue\n"); goto badInit; } if(VDP_STATUS_OK!=admVdpau::mixerCreate(widthToUse,heightToUse,&mixer)) { ADM_error("Cannot create mixer\n"); goto badInit; } return true; badInit: return false; }
void ADM_initBaseDir(int argc, char *argv[]) { char *home = NULL; // Get the base directory const char* homeEnv = getenv("HOME"); if (!homeEnv) { printf("Oops: can't determine $HOME."); return; } // Try to open the .avidemux directory strcpy(ADM_basedir, homeEnv); AddSeparator(ADM_basedir); const char *ADM_DIR_NAME = ".avidemux6"; strcat(ADM_basedir, ADM_DIR_NAME); strcat(ADM_basedir, ADM_SEPARATOR); if (ADM_mkdir(ADM_basedir)) { printf("Using %s as base directory for prefs, jobs, etc.\n", ADM_basedir); } else { ADM_error("Oops: cannot create the .avidemux directoryi (%s)\n", ADM_basedir); } }
bool ADM_Composer::setContainer(const char *cont, CONFcouple *c) { int idx = ADM_MuxerIndexFromName(cont); if (idx == -1) { ADM_error("Cannot find muxer for format=%s\n",cont); return false; } ADM_info("setting container as index %d\n",idx); UI_SetCurrentFormat(idx); idx = ADM_MuxerIndexFromName(cont); bool r = false; if(idx != -1) { r = ADM_mx_setExtraConf(idx, c); } if (c) delete c; return r; }
/** \fn TimeToFrame \brief return the frameno whose PTS==time */ static bool TimeToFrame(_VIDEOS *v,uint64_t time,uint32_t *frame,uint32_t *oflags) { vidHeader *demuxer=v->_aviheader; bool warn=false; int nb=demuxer->getMainHeader()->dwTotalFrames; for(int i=0;i<nb;i++) { uint64_t pts,dts; uint32_t flags; demuxer->getPtsDts(i,&pts,&dts); demuxer->getFlags(i,&flags); if(pts==time) { *frame=i; *oflags=flags; return true; } if(dts!=ADM_NO_PTS && warn==false) { if(dts>time) { ADM_error("We reached frame %d with a PTS of %"PRIu64" when looking for PTS %"PRIu64"\n", i,dts,time); warn=true; } } } return false; }
uint8_t asfHeader::open(const char *name) { _fd=ADM_fopen(name,"rb"); if(!_fd) { GUI_Error_HIG("File Error.","Cannot open file\n"); return 0; } myName=ADM_strdup(name); if(!getHeaders()) { return 0; } ADM_info("Stream Video: index=%d, sid=%d\n",(int)_videoIndex,(int)_videoStreamId); for(int i=0;i<_nbAudioTrack;i++) ADM_info("Stream Audio: index=%d, sid=%d\n", (int)_allAudioTracks[i].streamIndex,(int)_allAudioTracks[i].streamIndex); buildIndex(); fseeko(_fd,_dataStartOffset,SEEK_SET); _packet=new asfPacket(_fd,_nbPackets,_packetSize,&readQueue,&storageQueue,_dataStartOffset); curSeq=1; for(int i=0;i<_nbAudioTrack;i++) { _audioAccess[i]=new asfAudioAccess(this,i); _audioStreams[i]=ADM_audioCreateStream(&(_allAudioTracks[i].wavHeader), _audioAccess[i]); } if(!nbImage) { ADM_error("No image found \n"); return 0; } return 1; }
/** * \fn printError * @param s : banner * @param er : error code */ void AUDMEncoder_Lavcodec::printError(const char *s,int er) { char strer[256]={0}; av_strerror(er, strer, sizeof(strer)); ADM_error("[Lavcodec] %s,err : %d %s!\n",s,er,strer); }
/** \fn uploadImage \brief upload an image to a vdpau surface */ bool vdpauVideoFilterDeint::uploadImage(ADMImage *next,VdpVideoSurface surface) { if(!next) // empty image { ADM_warning("VdpauDeint:No image to upload\n"); return true; } if(surface==VDP_INVALID_HANDLE) { ADM_error("Surface provided is invalid\n"); return false; } // Blit our image to surface uint32_t pitches[3]; uint8_t *planes[3]; next->GetPitches(pitches); next->GetReadPlanes(planes); aprintf("Putting image in surface %d\n",(int)surface); // Put out stuff in input... #if VDP_DEBUG printf("Uploading image to surface %d\n",surfaceIndex%ADM_NB_SURFACES); #endif if(VDP_STATUS_OK!=admVdpau::surfacePutBits( surface, planes,pitches)) { ADM_warning("[Vdpau] video surface : Cannot putbits\n"); return false; } return true; }
/** \fn shiftAudioVideoBy \brief shift audio and video so that they start close to zero */ bool asfHeader::shiftAudioVideoBy(uint64_t s) { int n=_index.size(); ADM_info("Shifting by %s\n",ADM_us2plain(s)); for(int i=0;i<n;i++) { if(_index[i].pts!=ADM_NO_PTS) { if(_index[i].pts<s) { ADM_error("Shifting too big for frame %d PTS: %s\n",i,ADM_us2plain(_index[i].pts)); }else _index[i].pts-=s; } _index[i].dts=ADM_NO_PTS; /* if(_index[i].dts!=ADM_NO_PTS) { if(_index[i].dts<s) { ADM_error("Shifting too big for frame %d DTS: %s\n",i,ADM_us2plain(_index[i].dts)); _index[i].dts=ADM_NO_PTS; }else _index[i].dts-=s; } */ } _shiftUs=s; return true; }
ADM_AudiocodecAC3::ADM_AudiocodecAC3( uint32_t fourcc, WAVHeader *info,uint32_t extraLength,uint8_t *extraData) : ADM_Audiocodec(fourcc,*info) { int flags=0; ADM_assert(fourcc==WAV_AC3); ac3_handle=NULL; ac3_sample=NULL; #ifdef ADM_CPU_X86 #define CHK(x,y) if(CpuCaps::has##x()) flags|=MM_ACCEL_X86_##y; CHK(MMX,MMX); CHK(3DNOW,3DNOW); CHK(MMXEXT,MMXEXT); #endif ac3_handle=(void *)a52_init(flags); if(!ac3_handle) { ADM_error("Cannot init a52\n"); ADM_assert(0); } ac3_sample=(sample_t *)a52_samples(AC3_HANDLE); if(!ac3_sample) { ADM_warning("Cannot init a52 sample\n"); ADM_assert(0); } }
/** \fn stop \brief stop */ uint8_t audioDeviceThreaded::stop() { uint32_t maxWait=3*1000; // Should be enough to drain ADM_info("[audioDevice]Stopping device..."); if(stopRequest==AUDIO_DEVICE_STARTED) { CHANGE_STATE(AUDIO_DEVICE_STOP_REQ); while(stopRequest==AUDIO_DEVICE_STOP_REQ && maxWait) { ADM_usleep(1000); maxWait--; } } if(!maxWait) { ADM_error("Audio device did not stop cleanly\n"); } localStop(); if(audioBuffer) { delete [] audioBuffer; audioBuffer=NULL; } if(silence) delete [] silence; silence=NULL; CHANGE_STATE(AUDIO_DEVICE_STOPPED); return 1; }
muxerMp4v2::~muxerMp4v2() { ADM_info("[Mp4v2Muxer] Destroying\n"); close(); if(handle) ADM_error("MP4V2: File still opened\n"); currentMuxer=NULL; }
bool denoise3dhq_jdeserialize(const char *file, const ADM_paramList *tmpl,denoise3dhq *key){ admJsonToCouple json; CONFcouple *c=json.readFromFile(file); if(!c) {ADM_error("Cannot read json file");return false;} bool r= ADM_paramLoadPartial(c,tmpl,key); delete c; return r; };
/** \fn reallocOutputSurface */ bool vdpauRender::reallocOutputSurface(uint32_t tgtWidth, uint32_t tgtHeight) { if(surface[0]!=VDP_INVALID_HANDLE) admVdpau::outputSurfaceDestroy(surface[0]); if(surface[1]!=VDP_INVALID_HANDLE) admVdpau::outputSurfaceDestroy(surface[1]); surface[0]=surface[1]=VDP_INVALID_HANDLE; if(VDP_STATUS_OK!=admVdpau::outputSurfaceCreate(VDP_RGBA_FORMAT_B8G8R8A8,tgtWidth,tgtHeight,&surface[0])) { ADM_error("Cannot create outputSurface0\n"); return false; } if(VDP_STATUS_OK!=admVdpau::outputSurfaceCreate(VDP_RGBA_FORMAT_B8G8R8A8,tgtWidth,tgtHeight,&surface[1])) { ADM_error("Cannot create outputSurface1\n"); return false; } return true; }
/** * \fn tryLoadingVideoFilterPlugin * \brief try to load the plugin given as argument.. */ static uint8_t tryLoadingVideoFilterPlugin(const char *file) { ADM_vf_plugin *plugin = new ADM_vf_plugin(file); admVideoFilterInfo *info=NULL; if (!plugin->isAvailable()) { printf("[ADM_vf_plugin] Unable to load %s\n", ADM_GetFileName(file)); goto Err_ad; } // Check API version if (plugin->getApiVersion() != VF_API_VERSION) { printf("[ADM_vf_plugin] File %s has API version too old (%d vs %d)\n", ADM_GetFileName(file), plugin->getApiVersion(), VF_API_VERSION); goto Err_ad; } if(!(plugin->supportedUI() & UI_GetCurrentUI())) { // FIXME ADM_info("==> wrong UI\n"); goto Err_ad; } // Get infos uint32_t major, minor, patch; plugin->getFilterVersion(&major, &minor, &patch); plugin->nameOfLibrary = ADM_strdup(ADM_GetFileName(file)); info=&(plugin->info); info->internalName=plugin->getInternalName(); info->desc=plugin->getDesc(); info->displayName=plugin->getDisplayName(); info->category=plugin->getCategory(); printf("[ADM_vf_plugin] Plugin loaded version %d.%d.%d, name %s/%s\n", major, minor, patch, info->internalName, info->displayName); if(info->category>=VF_MAX) { ADM_error("This filter has an unknown caregory!\n"); goto Err_ad; }else { plugin->tag=ADM_videoFilterPluginsList[info->category].size()+info->category*100; ADM_videoFilterPluginsList[info->category].append(plugin); } return 1; Err_ad: delete plugin; return 0; }
/** \fn openGlResize \brief constructor */ openGlResize::openGlResize( ADM_coreVideoFilter *in,CONFcouple *setup) : ADM_coreVideoFilterQtGl(in,setup) { if (widget == NULL) { original = NULL; return; } UNUSED_ARG(setup); if(!setup || !ADM_paramLoad(setup,gl_resize_param,&configuration)) { // Default value configuration.width=info.width; configuration.height=info.height; } original=new ADMImageDefault(in->getInfo()->width,in->getInfo()->height); info.width=configuration.width; info.height=configuration.height; resizeFBO(info.width,info.height); widget->makeCurrent(); fboY->bind(); printf("Compiling shader \n"); glProgramY = new QGLShaderProgram(context); ADM_assert(glProgramY); if ( !glProgramY->addShaderFromSourceCode(QGLShader::Fragment, myShaderY)) { ADM_error("[GL Render] Fragment log: %s\n", glProgramY->log().toUtf8().constData()); ADM_assert(0); } if ( !glProgramY->link()) { ADM_error("[GL Render] Link log: %s\n", glProgramY->log().toUtf8().constData()); ADM_assert(0); } if ( !glProgramY->bind()) { ADM_error("[GL Render] Binding FAILED\n"); ADM_assert(0); } fboY->release(); widget->doneCurrent(); }
bool FileSystem::rename( string from, string to ) { if(!ADM_renameFile(from.c_str(),to.c_str())) { ADM_error("Cannot rename %s to %s\n",from.c_str(),to.c_str()); return true; } return false; }
/** \fn processError */ static bool processError(const char *e) { int x=glGetError(); if(x!=GL_NO_ERROR) { ADM_error("%s: Error : %d %s\n",e,x,gluErrorString(x)); return false; } return true; }
/** \fn rotateGl \brief constructor */ rotateGl::rotateGl( ADM_coreVideoFilter *in,CONFcouple *setup) : ADM_coreVideoFilterQtGl(in,setup) { if (widget == NULL) { original = NULL; return; } UNUSED_ARG(setup); original=new ADMImageDefault(in->getInfo()->width,in->getInfo()->height); if(!setup || !ADM_paramLoad(setup,gl_rotate_param,¶ms)) { // Default value params.angle=0; } widget->makeCurrent(); fboY->bind(); printf("Compiling shader \n"); glProgramY = new QGLShaderProgram(context); ADM_assert(glProgramY); if ( !glProgramY->addShaderFromSourceCode(QGLShader::Fragment, myShaderY)) { ADM_error("[GL Render] Fragment log: %s\n", glProgramY->log().toUtf8().constData()); ADM_assert(0); } if ( !glProgramY->link()) { ADM_error("[GL Render] Link log: %s\n", glProgramY->log().toUtf8().constData()); ADM_assert(0); } if ( !glProgramY->bind()) { ADM_error("[GL Render] Binding FAILED\n"); ADM_assert(0); } glList=glGenLists(1); genQuad(); fboY->release(); widget->doneCurrent(); }
/** \fn ctor */ glRGB::glRGB(ADM_coreVideoFilter *previous,CONFcouple *conf) : ADM_coreVideoFilterQtGl(previous,conf) { widget->makeCurrent(); fboY->bind(); ADM_info("Compiling shader \n"); glProgramY = new QGLShaderProgram(context); ADM_assert(glShaderRgb); if ( !glProgramY->addShaderFromSourceCode(QGLShader::Fragment, glShaderRgb)) { ADM_error("[GL Render] Fragment log: %s\n", glProgramY->log().toUtf8().constData()); ADM_assert(0); } if ( !glProgramY->link()) { ADM_error("[GL Render] Link log: %s\n", glProgramY->log().toUtf8().constData()); ADM_assert(0); } if ( !glProgramY->bind()) { ADM_error("[GL Render] Binding FAILED\n"); ADM_assert(0); } fboY->release(); widget->doneCurrent(); // memset(realMatrix,0,sizeof(realMatrix)); realMatrix[0]=0.299; realMatrix[1]=0.587; realMatrix[2]=0.114; realMatrix[4]=-0.14713; realMatrix[5]=-0.28886; realMatrix[6]=+0.436; realMatrix[8]=+0.615; realMatrix[9]=-0.51499; realMatrix[10]=-0.10001; }
/** \fn changeZoom */ bool vdpauRender::changeZoom(float newZoom) { ADM_info("[Vdpau]changing zoom.\n"); calcDisplayFromZoom(newZoom); currentZoom=newZoom; if(!reallocOutputSurface(displayWidth,displayHeight)) { ADM_error("[VdpauRender] Change zoome failed\n"); } return true; }
/** * \fn ADM_getIndexForIso639 * @param iso * @return */ int ADM_getIndexForIso639(const char *iso) { int n=ADM_getLanguageListSize(); for(int i=0;i<n;i++) { if(!strcmp(languages[i].iso639_2,iso)) return i; } ADM_error("Language %s not found in list\n",iso); return -1; }
/** * * @param p */ void call_slave(char *p) { uint32_t i; sscanf(p,"%" PRIu32,&i); ADM_info("Slave on port %" PRIu32"\n",i); if(!ADM_slaveConnect(i)) { ADM_error("Cannot connect to master\n"); exit(-1); } }
bool admJsonToCouple::scan( void *xnode,string name) { JSONNODE *node=(JSONNODE *)xnode; if (!node){ ADM_error("Invalid JSON Node\n"); return false; } JSONNODE_ITERATOR i = json_begin(node); while (i != json_end(node)){ if (*i == NULL){ ADM_error("Invalid JSON Node\n"); return false; } json_char *node_name = json_name(*i); //printf("Node :%s\n",node_name); // recursively call ourselves to dig deeper into the tree if (json_type(*i) == JSON_ARRAY || json_type(*i) == JSON_NODE) { if(name=="") scan(*i,string(node_name)); else scan(*i,name+string(".")+string(node_name)); } else { keyVal k; json_char *node_value = json_as_string(*i); if(name=="") k.key=string(node_name); else k.key=string(name)+string(".")+string(node_name); k.value=string(node_value); readItems.push_back(k); json_free(node_value); } json_free(node_name); ++i; } return true; }
/** \fn openGlVertex \brief constructor */ openGlVertex::openGlVertex( ADM_coreVideoFilter *in,CONFcouple *setup) : ADM_coreVideoFilterQtGl(in,setup) { UNUSED_ARG(setup); widget->makeCurrent(); fboY->bind(); printf("Compiling shader \n"); // vertex shader // frag shader glProgramY = new QGLShaderProgram(context); ADM_assert(glProgramY); #if 1 if ( !glProgramY->addShaderFromSourceCode(QGLShader::Vertex, myVertex)) { ADM_error("[GL Render] Vertex log: %s\n", glProgramY->log().toUtf8().constData()); ADM_assert(0); } #endif if ( !glProgramY->addShaderFromSourceCode(QGLShader::Fragment, myShaderY)) { ADM_error("[GL Render] Fragment log: %s\n", glProgramY->log().toUtf8().constData()); ADM_assert(0); } if ( !glProgramY->link()) { ADM_error("[GL Render] Link log: %s\n", glProgramY->log().toUtf8().constData()); ADM_assert(0); } if ( !glProgramY->bind()) { ADM_error("[GL Render] Binding FAILED\n"); ADM_assert(0); } glList=glGenLists(1); buildVertex(); fboY->release(); widget->doneCurrent(); }
/** \fn glYadif \brief constructor */ glYadif::glYadif( ADM_coreVideoFilter *in,CONFcouple *setup) : ADM_coreVideoFilterQtGl(in,setup) { UNUSED_ARG(setup); widget->makeCurrent(); fboY->bind(); printf("Compiling shader \n"); glProgramY = new QGLShaderProgram(context); ADM_assert(glProgramY); if ( !glProgramY->addShaderFromSourceCode(QGLShader::Fragment, myShaderY)) { ADM_error("[GL Render] Fragment log: %s\n", glProgramY->log().toUtf8().constData()); ADM_assert(0); } if ( !glProgramY->link()) { ADM_error("[GL Render] Link log: %s\n", glProgramY->log().toUtf8().constData()); ADM_assert(0); } if ( !glProgramY->bind()) { ADM_error("[GL Render] Binding FAILED\n"); ADM_assert(0); } fboY->release(); widget->doneCurrent(); original=new ADMImageDefault(in->getInfo()->width,in->getInfo()->height); if(!setup || !ADM_paramLoad(setup,yadif_param,&configuration)) { // Default value configuration.mode=0; configuration.order=1; } vidCache = new VideoCache (10, in); updateInfo(); myName="yadif"; }
/** \fn setIdentityCSC \brief set the RGB/YUV matrix to identity so that data are still YUV at the end Should not work, but it does. */ bool vdpauVideoFilterDeint::setIdentityCSC(void) { ADM_info("Setting custom CSC\n"); const VdpCSCMatrix matrix={{1.,0,0,0},{0,1.,0,0},{0,0,1.,0}}; VdpVideoMixerAttribute attributes_key[]={VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX}; const void * attribute_values[] = {&matrix}; VdpStatus st = admVdpau::mixerSetAttributesValue(mixer, 1,attributes_key, (void * const *)attribute_values); if(st!=VDP_STATUS_OK) ADM_error("Cannot set custom matrix (CSC)\n"); return true; }