int ServiceLayer::run() { m_display->setCommunicator( &getParent().getPortComm() ); if(!m_strConfigFile.empty()) { std::cout << "balzac was told to use [" << m_strConfigFile << "] as displayfile." << std::endl; flowvr::xml::TiXmlDocument config( m_strConfigFile.c_str() ); if( config.LoadFile() ) { flowvr::xml::TiXmlHandle docHandle( &config ); flowvr::xml::TiXmlHandle config = docHandle.FirstChild("config"); flowvr::xml::TiXmlHandle display = config.FirstChild("display"); configureDisplay( display ); } else { std::cerr << "error during parsing of displayfile [" << m_strConfigFile << "]" << std::endl << config.ErrorDesc() << std::endl; } } glutMainLoop(); return 0; }
void COMXVideo::setDisplayRect(ofRectangle& rectangle) { bool hasChanged = (displayRect != rectangle); //ofLogVerbose(__func__) << "hasChanged: " << hasChanged << " displayRect: " << displayRect << " rectangle: " << rectangle; if (hasChanged) { displayRect = rectangle; } if(!m_is_open) { return; } if (hasChanged) { configureDisplay(); } }
int main(int argc, const char *argv[]) { // http://developer.apple.com/library/IOs/#documentation/CoreFoundation/Conceptual/CFStrings/Articles/MutableStrings.html int i; CFMutableStringRef args = CFStringCreateMutable(NULL, 0); CFStringEncoding encoding = CFStringGetSystemEncoding(); CFStringAppend(args, CFSTR("starting screenresolution argv=")); for (i = 0 ; i < argc ; i++) { CFStringAppendCString(args, argv[i], encoding); // If I were so motivated, I'd probably use CFStringAppendFormat CFStringAppend(args, CFSTR(" ")); } // This has security implications. Will look at that later NSLog(CFSTR("%@"), args); unsigned int exitcode = 0; if (argc > 1) { int d; int keepgoing = 1; CGError rc; uint32_t displayCount = 0; uint32_t activeDisplayCount = 0; CGDirectDisplayID *activeDisplays = NULL; rc = CGGetActiveDisplayList(0, NULL, &activeDisplayCount); if (rc != kCGErrorSuccess) { NSLog(CFSTR("%s"), "Error: failed to get list of active displays"); return 1; } // Allocate storage for the next CGGetActiveDisplayList call activeDisplays = (CGDirectDisplayID *) malloc(activeDisplayCount * sizeof(CGDirectDisplayID)); if (activeDisplays == NULL) { NSLog(CFSTR("s"), "Error: could not allocate memory for display list"); return 1; } rc = CGGetActiveDisplayList(activeDisplayCount, activeDisplays, &displayCount); if (rc != kCGErrorSuccess) { NSLog(CFSTR("%s"), "Error: failed to get list of active displays"); return 1; } // This loop should probably be in another function. for (d = 0; d < displayCount && keepgoing; d++) { if (strcmp(argv[1], "get") == 0) { if (!listCurrentMode(activeDisplays[d], d)) { exitcode++; } } else if (strcmp(argv[1], "list") == 0) { if (!listAvailableModes(activeDisplays[d], d)) { exitcode++; } } else if (strcmp(argv[1], "set") == 0) { if (d < (argc - 2)) { if (strcmp(argv[d+2], "skip") == 0 && d < (argc - 2)) { printf("Skipping display %d\n", d); } else { struct config newConfig; if (parseStringConfig(argv[d + 2], &newConfig)) { if (!configureDisplay(activeDisplays[d], &newConfig, d)) { exitcode++; } } else { exitcode++; } } } } else if (strcmp(argv[1], "-version") == 0) { printf("screenresolution version %s\nLicensed under GPLv2\n", VERSION); keepgoing = 0; } else { NSLog(CFSTR("I'm sorry %s. I'm afraid I can't do that"), getlogin()); exitcode++; keepgoing = 0; } } free(activeDisplays); activeDisplays = NULL; } else { NSLog(CFSTR("%s"), "Incorrect command line"); exitcode++; } return exitcode > 0; }
bool COMXVideo::Open(COMXStreamInfo& hints, OMXClock *clock, float display_aspect, bool deinterlace, bool hdmi_clock_sync) { OMX_ERRORTYPE error = OMX_ErrorNone; m_video_codec_name = ""; m_codingType = OMX_VIDEO_CodingUnused; m_decoded_width = hints.width; m_decoded_height = hints.height; m_hdmi_clock_sync = hdmi_clock_sync; if(!m_decoded_width || !m_decoded_height) { return false; } if(hints.extrasize > 0 && hints.extradata != NULL) { m_extrasize = hints.extrasize; m_extradata = (uint8_t *)malloc(m_extrasize); memcpy(m_extradata, hints.extradata, hints.extrasize); } ProcessCodec(hints); if(deinterlace) { ofLog(OF_LOG_VERBOSE, "enable deinterlace\n"); m_deinterlace = true; } else { m_deinterlace = false; } std::string componentName = decoder_name; if(!m_omx_decoder.Initialize(componentName, OMX_IndexParamVideoInit)) { return false; } componentName = "OMX.broadcom.video_render"; if(!m_omx_render.Initialize(componentName, OMX_IndexParamVideoInit)) { return false; } componentName = "OMX.broadcom.video_scheduler"; if(!m_omx_sched.Initialize(componentName, OMX_IndexParamVideoInit)) { return false; } if(m_deinterlace) { componentName = "OMX.broadcom.image_fx"; if(!m_omx_image_fx.Initialize(componentName, OMX_IndexParamImageInit)) { return false; } } if(clock == NULL) { return false; } m_av_clock = clock; m_omx_clock = m_av_clock->GetOMXClock(); if(m_omx_clock->GetComponent() == NULL) { m_av_clock = NULL; m_omx_clock = NULL; return false; } if(m_deinterlace) { m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_image_fx, m_omx_image_fx.GetInputPort()); m_omx_tunnel_image_fx.Initialize(&m_omx_image_fx, m_omx_image_fx.GetOutputPort(), &m_omx_sched, m_omx_sched.GetInputPort()); } else { m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_sched, m_omx_sched.GetInputPort()); } m_omx_tunnel_sched.Initialize(&m_omx_sched, m_omx_sched.GetOutputPort(), &m_omx_render, m_omx_render.GetInputPort()); m_omx_tunnel_clock.Initialize(m_omx_clock, m_omx_clock->GetInputPort() + 1, &m_omx_sched, m_omx_sched.GetOutputPort() + 1); error = m_omx_tunnel_clock.Establish(false); if(error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_tunnel_clock Establish FAIL: " << COMXCore::getOMXError(error); return false; } error = m_omx_decoder.SetStateForComponent(OMX_StateIdle); if (error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_decoder OMX_StateIdle FAIL: " << COMXCore::getOMXError(error); return false; } OMX_VIDEO_PARAM_PORTFORMATTYPE formatType; OMX_INIT_STRUCTURE(formatType); formatType.nPortIndex = m_omx_decoder.GetInputPort(); formatType.eCompressionFormat = m_codingType; if (hints.fpsscale > 0 && hints.fpsrate > 0) { formatType.xFramerate = (long long)(1<<16)*hints.fpsrate / hints.fpsscale; } else { formatType.xFramerate = 25 * (1<<16); } error = m_omx_decoder.SetParameter(OMX_IndexParamVideoPortFormat, &formatType); if(error != OMX_ErrorNone) { return false; } OMX_PARAM_PORTDEFINITIONTYPE portParam; OMX_INIT_STRUCTURE(portParam); portParam.nPortIndex = m_omx_decoder.GetInputPort(); error = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &portParam); if(error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_decoder Get OMX_IndexParamPortDefinition FAIL: " << COMXCore::getOMXError(error); return false; } portParam.nPortIndex = m_omx_decoder.GetInputPort(); int videoBuffers = 60; portParam.nBufferCountActual = videoBuffers; portParam.format.video.nFrameWidth = m_decoded_width; portParam.format.video.nFrameHeight = m_decoded_height; error = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &portParam); if(error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_decoder Set OMX_IndexParamPortDefinition FAIL: " << COMXCore::getOMXError(error); return false; } OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE concanParam; OMX_INIT_STRUCTURE(concanParam); concanParam.bStartWithValidFrame = OMX_FALSE; error = m_omx_decoder.SetParameter(OMX_IndexParamBrcmVideoDecodeErrorConcealment, &concanParam); if(error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_decoder OMX_IndexParamBrcmVideoDecodeErrorConcealment FAIL: " << COMXCore::getOMXError(error); return false; } if (m_deinterlace) { // the deinterlace component requires 3 additional video buffers in addition to the DPB (this is normally 2). OMX_PARAM_U32TYPE extra_buffers; OMX_INIT_STRUCTURE(extra_buffers); extra_buffers.nU32 = 3; error = m_omx_decoder.SetParameter(OMX_IndexParamBrcmExtraBuffers, &extra_buffers); if(error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_decoder OMX_IndexParamBrcmExtraBuffers FAIL: " << COMXCore::getOMXError(error); return false; } } // broadcom omx entension: // When enabled, the timestamp fifo mode will change the way incoming timestamps are associated with output images. // In this mode the incoming timestamps get used without re-ordering on output images. // recent firmware will actually automatically choose the timestamp stream with the least variance, so always enable OMX_CONFIG_BOOLEANTYPE timeStampMode; OMX_INIT_STRUCTURE(timeStampMode); timeStampMode.bEnabled = OMX_TRUE; error = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamBrcmVideoTimestampFifo, &timeStampMode); if (error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_decoder OMX_IndexParamBrcmVideoTimestampFifo FAIL: " << COMXCore::getOMXError(error); return false; } if(NaluFormatStartCodes(hints.codec, m_extradata, m_extrasize)) { OMX_NALSTREAMFORMATTYPE nalStreamFormat; OMX_INIT_STRUCTURE(nalStreamFormat); nalStreamFormat.nPortIndex = m_omx_decoder.GetInputPort(); nalStreamFormat.eNaluFormat = OMX_NaluFormatStartCodes; error = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSelect, &nalStreamFormat); if (error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_decoder OMX_IndexParamNalStreamFormatSelect FAIL: " << COMXCore::getOMXError(error); return false; } } if(m_hdmi_clock_sync) { OMX_CONFIG_LATENCYTARGETTYPE latencyTarget; OMX_INIT_STRUCTURE(latencyTarget); latencyTarget.nPortIndex = m_omx_render.GetInputPort(); latencyTarget.bEnabled = OMX_TRUE; latencyTarget.nFilter = 2; latencyTarget.nTarget = 4000; latencyTarget.nShift = 3; latencyTarget.nSpeedFactor = -135; latencyTarget.nInterFactor = 500; latencyTarget.nAdjCap = 20; error = m_omx_render.SetConfig(OMX_IndexConfigLatencyTarget, &latencyTarget); if (error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_render OMX_IndexConfigLatencyTarget FAIL: " << COMXCore::getOMXError(error); return false; } } // Alloc buffers for the omx input port. error = m_omx_decoder.AllocInputBuffers(); if (error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_decoder AllocInputBuffers FAIL: " << COMXCore::getOMXError(error); return false; } error = m_omx_tunnel_decoder.Establish(false); if(error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_tunnel_decoder Establish FAIL: " << COMXCore::getOMXError(error); return false; } error = m_omx_decoder.SetStateForComponent(OMX_StateExecuting); if (error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_decoder OMX_StateExecuting FAIL: " << COMXCore::getOMXError(error); return false; } if(m_deinterlace) { OMX_CONFIG_IMAGEFILTERPARAMSTYPE image_filter; OMX_INIT_STRUCTURE(image_filter); image_filter.nPortIndex = m_omx_image_fx.GetOutputPort(); image_filter.nNumParams = 1; image_filter.nParams[0] = 3; image_filter.eImageFilter = OMX_ImageFilterDeInterlaceAdvanced; error = m_omx_image_fx.SetConfig(OMX_IndexConfigCommonImageFilterParameters, &image_filter); if(error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_image_fx SetConfig FAIL: " << COMXCore::getOMXError(error); return false; } error = m_omx_tunnel_image_fx.Establish(false); if(error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_image_fx Establish FAIL: " << COMXCore::getOMXError(error); return false; } error = m_omx_image_fx.SetStateForComponent(OMX_StateExecuting); if (error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_image_fx OMX_StateExecuting FAIL: " << COMXCore::getOMXError(error); return false; } m_omx_image_fx.DisablePort(m_omx_image_fx.GetInputPort(), false); m_omx_image_fx.DisablePort(m_omx_image_fx.GetOutputPort(), false); } error = m_omx_tunnel_sched.Establish(false); if(error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_tunnel_sched Establish FAIL: " << COMXCore::getOMXError(error); return false; } error = m_omx_sched.SetStateForComponent(OMX_StateExecuting); if (error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_sched OMX_StateExecuting FAIL: " << COMXCore::getOMXError(error); return false; } error = m_omx_render.SetStateForComponent(OMX_StateExecuting); if (error != OMX_ErrorNone) { ofLogError(__func__) << "m_omx_render OMX_StateExecuting FAIL: " << COMXCore::getOMXError(error); return false; } ofAddListener(ofEvents().update, this, &COMXVideo::onUpdate); if(!SendDecoderConfig()) { return false; } m_is_open = true; m_drop_state = false; m_setStartTime = true; OMX_CONFIG_DISPLAYREGIONTYPE configDisplay; OMX_INIT_STRUCTURE(configDisplay); configDisplay.nPortIndex = m_omx_render.GetInputPort(); //we provided a rectangle but returned early as we were not ready if (displayRect.getWidth()>0) { configureDisplay(); }else { float fAspect = (float)hints.aspect / (float)m_decoded_width * (float)m_decoded_height; float par = hints.aspect ? fAspect/display_aspect : 0.0f; // only set aspect when we have a aspect and display doesn't match the aspect bool doDisplayChange = true; if(doDisplayChange) { if(par != 0.0f && fabs(par - 1.0f) > 0.01f) { AVRational aspect; aspect = av_d2q(par, 100); configDisplay.set = OMX_DISPLAY_SET_PIXEL; configDisplay.pixel_x = aspect.num; configDisplay.pixel_y = aspect.den; ofLog(OF_LOG_VERBOSE, "Aspect : num %d den %d aspect %f pixel aspect %f\n", aspect.num, aspect.den, hints.aspect, par); error = m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); if(error != OMX_ErrorNone) { return false; } } } } ofLog(OF_LOG_VERBOSE, "%s::%s - decoder_component(0x%p), input_port(0x%x), output_port(0x%x) deinterlace %d hdmiclocksync %d\n", "OMXVideo", __func__, m_omx_decoder.GetComponent(), m_omx_decoder.GetInputPort(), m_omx_decoder.GetOutputPort(), m_deinterlace, m_hdmi_clock_sync); m_first_frame = true; // start from assuming all recent frames had valid pts m_history_valid_pts = ~0; return true; }