STDMETHODIMP CGfxTitanII::CreateSurfaces() { HRESULT hr; int i; DWORD height,width,buffers,hpad,wpad; if(m_dwWidth==0 || m_dwHeight==0 /*|| m_hwnd==0*/) return E_FAIL; if(m_pVr && m_dwWidth==m_dwOldWidth && m_dwHeight==m_dwOldHeight && m_hwnd==m_Oldhwnd) return S_OK; if(m_bBSMMode == TRUE) { m_BSM_Init(m_pVr); } m_dwOldWidth = m_dwWidth; m_dwOldHeight = m_dwHeight; m_Oldhwnd = m_hwnd; //VR_LAYER_OVERLAY:VR_LAYER_PRIMARY #if defined(SIRF_NOTEBOOK ) || defined(RTK_TITAN_II) hr = m_CVR_SetRenderLayer(m_pVr, VR_LAYER_PRIMARY,0.0f); #else hr = m_CVR_SetRenderLayer(m_pVr, VR_LAYER_OVERLAY,0.0f); #endif //[optional] it will change settings in renderer. //TITAN_BITMAP_ORDER: this is the set the bitmap data order //inputted. //pInBuf: the pointer of input data block //data_size: the size of input data block //pOutBuf: the pointer of output data block. //CVR_EscapeCtrl(m_pVr, TITAN_BITMAP_ORDER, pInBuf, data_size, pOutBuf); //[optional] it will set the display mode //mode: the display mode to be set hr = m_CVR_SetDisplayMode(m_pVr, m_dispmode); //if(m_dwHeight<480) // m_sy = 2; // double the height! //else m_sy = 1; //if(m_bUseDSP) //{ // DSP renderer // alignx = 16; // 16 is required (spec doesn't specify) // aligny = 4; // hr = CVR_EscapeCtrl(m_pVr,TITAN_DSP_RENDERER,0,0,0); // if(hr!=VR_OK) // { // // do something here. // } //} //else { // alignx = 2; /* actually 2, but we prefer this for our averaging ops */ // aligny = 2; } buffers = m_dwMaxBuffers+1; wpad = ~(m_dwWidth-1) & (ALIGNX-1); width = m_dwWidth+wpad; height = m_dwHeight*m_sy; hpad = ~(height-1) & (ALIGNY-1); height = height+hpad; //width = width + (width&0xf); //height = height + (height&0xf); //SetDisplayMode(1); m_iYPitch = width; m_iUVPitch = m_iYPitch>>1; //hr = CVR_SetVideoFormat(m_pVr, 0, width, height, 0, &m_iYPitch, &m_iUVPitch); //Set the Video parameters. //VR_FORMAT_I420: set the input data format as I420 //width: width of source frame //height: height of source frame //rect: the source rect //LumPitch: pitch of lum //ChromPitch: pitch of chrom width = ROOF(m_dwWidth, ALIGNX); if(m_bBSMMode == TRUE) height = ROOF(m_dwHeight, ALIGNY); else height = m_dwHeight; VR_SRCRECT rect; rect.left= 0; rect.right = m_dwWidth; rect.top = 0; rect.bottom= m_dwHeight; hr = m_CVR_SetVideoFormat(m_pVr, VR_FORMAT_I420, width, height, &rect, &m_iYPitch, &m_iUVPitch); SetDeinterlaceMode(m_deinterlace_mode); if(!m_bBSMMode) { m_pBackBuffer = new LPVR_FRAME_SURFACE[buffers]; ZeroMemory(m_pBackBuffer,sizeof(m_pBackBuffer[0])*buffers); for(i=0;i<(signed)buffers;i++) { hr = m_CVR_CreateSurface(m_pVr,&m_pBackBuffer[i],1); if(hr!=VR_OK) break; } if(i==0) { delete[] m_pBackBuffer; m_pBackBuffer = 0; //CVR_DeleteVideoRender(m_pVr); //m_pVr = 0; return E_FAIL; } if(i>1) { // make sure we have at least one surface available for background scratch, otherwise hang. m_CVR_DestroySurface(m_pVr,m_pBackBuffer[--i]); ZeroMemory(&m_pBackBuffer[i],sizeof(m_pBackBuffer[i])); } m_dwBackBuffers = i; // clear out buffers unsigned char *pb; LONG lstride; int xl,xr,yt,yb,ht; yt = hpad>>1&~1; yb = hpad - yt; xl = 0; // (wpad>>1)&~3; xr = wpad -xl; ht = m_dwHeight*m_sy; for(i=0;i<(signed)m_dwBackBuffers;i++) { if(SUCCEEDED(Lock(i, (LPVOID *)&pb, &lstride, 0))) { clearoutsiderect(pb,m_dwWidth,ht,lstride,0,xl,xr,yt,yb); clearoutsiderect(pb+height*width,m_dwWidth>>1,ht>>1,lstride>>1,128,xl>>1,xr>>1,yt>>1,yb>>1); clearoutsiderect(pb+height*width+(height*width>>2),m_dwWidth>>1,ht>>1,lstride>>1,128,xl>>1,xr>>1,yt>>1,yb>>1); Unlock(i); } }
static int Open(vlc_object_t *obj) { char ppsz_components[MAX_COMPONENTS_LIST_SIZE][OMX_MAX_STRINGNAME_SIZE]; OMX_U8 psz_role[OMX_MAX_STRINGNAME_SIZE]; filter_t *filter = (filter_t*) obj; OMX_PARAM_PORTDEFINITIONTYPE def; OMX_PORT_PARAM_TYPE param; filter_t *p_dec = filter; OMX_ERRORTYPE omx_error; filter_sys_t *sys; unsigned int i, j; int components; static OMX_CALLBACKTYPE callbacks = { OmxEventHandler, OmxEmptyBufferDone, OmxFillBufferDone }; if (InitOmxCore(obj) != VLC_SUCCESS) return VLC_EGENERIC; components = CreateComponentsList(obj, "image_fx", ppsz_components); if (components <= 0) { DeinitOmxCore(); msg_Err(filter, "Could not find image_fx component.\n"); return VLC_EGENERIC; } sys = calloc(1, sizeof(*sys)); if (unlikely(sys == NULL)) return VLC_ENOMEM; strcpy(sys->psz_component, ppsz_components[0]); filter->p_sys = sys; /* Initialize the OMX component */ omx_error = pf_get_handle(&sys->omx_handle, sys->psz_component, filter, &callbacks); CHECK_ERROR(omx_error, "OMX_GetHandle(%s) failed (%x: %s)", sys->psz_component, omx_error, ErrorToString(omx_error)); omx_error = OMX_ComponentRoleEnum(sys->omx_handle, psz_role, 0); if(omx_error == OMX_ErrorNone) msg_Dbg(filter, "loaded component %s of role %s", sys->psz_component, psz_role); else msg_Dbg(filter, "loaded component %s", sys->psz_component); PrintOmx(obj, sys->omx_handle, OMX_ALL); InitOmxEventQueue(&sys->event_queue); OMX_INIT_STRUCTURE(param); OMX_INIT_STRUCTURE(def); omx_error = OMX_GetParameter(sys->omx_handle, OMX_IndexParamImageInit, ¶m); CHECK_ERROR(omx_error, "OMX_GetParameter(OMX_IndexParamImageInit) failed (%x: %s)", omx_error, ErrorToString(omx_error)); sys->num_ports = param.nPorts; sys->ports = &sys->out; for (i = 0; i < param.nPorts; i++) { OmxPort *p_port; def.nPortIndex = param.nStartPortNumber + i; omx_error = OMX_GetParameter(sys->omx_handle, OMX_IndexParamPortDefinition, &def); if (omx_error != OMX_ErrorNone) { msg_Warn(obj, "Port Defintion could not be retrieved for port %d", (int)def.nPortIndex); continue; } if (def.eDir == OMX_DirInput) { msg_Dbg(obj, "Port %d is input.", (int)def.nPortIndex); p_port = &sys->in; } else { msg_Dbg(obj, "Port %d is output.", (int)def.nPortIndex); p_port = &sys->out; } def.nBufferCountActual = def.nBufferCountMin; omx_error = OMX_SetParameter(sys->omx_handle, OMX_IndexParamPortDefinition, &def); if (omx_error != OMX_ErrorNone) { msg_Warn(obj, "Port Defintion could not be updated for port %d", (int)def.nPortIndex); continue; } p_port->b_valid = true; p_port->i_port_index = def.nPortIndex; p_port->definition = def; p_port->omx_handle = sys->omx_handle; } if (!sys->in.b_valid || !sys->out.b_valid) { omx_error = OMX_ErrorInvalidComponent; CHECK_ERROR(omx_error, "couldn't find an input and/or output port."); } SetFormat(filter, &sys->in); SetFormat(filter, &sys->out); /* allocate array for port buffers */ for (i = 0; i < sys->num_ports; i++) { OmxPort *port = &sys->ports[i]; vlc_mutex_init(&port->fifo.lock); vlc_cond_init(&port->fifo.wait); port->fifo.pp_last = &port->fifo.p_first; port->b_flushed = true; if (port == &sys->in) { port->b_direct = true; port->p_fmt = &filter->fmt_in; port->fifo.offset = offsetof(OMX_BUFFERHEADERTYPE, pOutputPortPrivate) / sizeof(void*); } else { port->b_direct = true; port->p_fmt = &filter->fmt_out; port->fifo.offset = offsetof(OMX_BUFFERHEADERTYPE, pInputPortPrivate) / sizeof(void*); } msg_Dbg(obj, "Allocate headroom for %u buffers.", (unsigned)port->definition.nBufferCountActual); port->pp_buffers = malloc(port->definition.nBufferCountActual * sizeof(OMX_BUFFERHEADERTYPE*)); if (unlikely(port->pp_buffers == NULL)) { omx_error = OMX_ErrorInsufficientResources; CHECK_ERROR(omx_error, "memory allocation failed"); } port->i_buffers = port->definition.nBufferCountActual; /* enable port */ if (!port->definition.bEnabled) { omx_error = OMX_SendCommand(sys->omx_handle, OMX_CommandPortEnable, port->i_port_index, NULL); CHECK_ERROR(omx_error, "OMX_CommandPortEnable on %i failed (%x)", (int)port->i_port_index, omx_error); omx_error = WaitForSpecificOmxEvent(&sys->event_queue, OMX_EventCmdComplete, 0, 0, 0); CHECK_ERROR(omx_error, "Wait for PortEnable on %i failed (%x)", (int)port->i_port_index, omx_error); } } /* Put component into idle state */ omx_error = OMX_SendCommand(sys->omx_handle, OMX_CommandStateSet, OMX_StateIdle, 0); CHECK_ERROR(omx_error, "OMX_CommandStateSet Idle failed (%x: %s)", omx_error, ErrorToString(omx_error)); /* allocate buffers/bufferheaders for direct rendering */ for (i = 0; i < sys->num_ports; i++) { OmxPort *port = &sys->ports[i]; for (j = 0; j < port->i_buffers; j++) { if (port->b_direct) { omx_error = OMX_UseBuffer(sys->omx_handle, &port->pp_buffers[j], port->i_port_index, 0, port->definition.nBufferSize, (void*)1); CHECK_ERROR(omx_error, "OMX_UseBuffer failed (%x: %s)", omx_error, ErrorToString(omx_error)); msg_Dbg(obj, "Use direct rendering on port %u", (unsigned)port->i_port_index); msg_Dbg(obj, "Allocated direct rendering buffer header: %p", port->pp_buffers[j]); } else { omx_error = OMX_AllocateBuffer(sys->omx_handle, &port->pp_buffers[j], port->i_port_index, 0, port->definition.nBufferSize); msg_Dbg(obj, "Use indirect rendering on port %u", (unsigned)port->i_port_index); } if (omx_error != OMX_ErrorNone) { msg_Warn(obj, "Buffer allocate failed on buffer %d for port %d (%x: %s)", j, i, omx_error, ErrorToString(omx_error)); CHECK_ERROR(omx_error, "OMX_FillBuffer failed (%x: %s)", omx_error, ErrorToString(omx_error)); break; } OMX_FIFO_PUT(&port->fifo, port->pp_buffers[j]); } msg_Dbg(obj, "Allocated %u buffers for port %u", (unsigned)port->i_buffers, (unsigned)port->i_port_index); } omx_error = WaitForSpecificOmxEvent(&sys->event_queue, OMX_EventCmdComplete, 0, 0, 0); CHECK_ERROR(omx_error, "Wait for Idle failed (%x: %s)", omx_error, ErrorToString(omx_error)); msg_Dbg(obj, "Reached Idle state, transition to Executing."); SetDeinterlaceMode(filter); omx_error = OMX_SendCommand(sys->omx_handle, OMX_CommandStateSet, OMX_StateExecuting, 0); CHECK_ERROR(omx_error, "OMX_CommandStateSet Executing failed (%x)", omx_error); omx_error = WaitForSpecificOmxEvent(&sys->event_queue, OMX_EventCmdComplete, 0, 0, 0); CHECK_ERROR(omx_error, "Wait for Executing failed (%x)", omx_error ); filter->pf_video_filter = Deinterlace; filter->fmt_out.video.i_frame_rate *= 2; printf("OMXIL deinterlace filter initialized with %d->%d fps\n", filter->fmt_in.video.i_frame_rate, filter->fmt_out.video.i_frame_rate); return VLC_SUCCESS; error: Close(obj); return VLC_EGENERIC; }