示例#1
0
文件: vout.c 项目: Kubink/vlc
static void adjust_refresh_rate(vout_display_t *vd, const video_format_t *fmt)
{
    vout_display_sys_t *sys = vd->sys;
    TV_DISPLAY_STATE_T display_state;
    TV_SUPPORTED_MODE_NEW_T supported_modes[VC_TV_MAX_MODE_IDS];
    char response[20]; /* answer is hvs_update_fields=%1d */
    int num_modes;
    double frame_rate = (double)fmt->i_frame_rate / fmt->i_frame_rate_base;
    int best_id = -1;
    double best_score, score;
    int i;

    vc_tv_get_display_state(&display_state);
    if(display_state.display.hdmi.mode != HDMI_MODE_OFF) {
        num_modes = vc_tv_hdmi_get_supported_modes_new(display_state.display.hdmi.group,
                        supported_modes, VC_TV_MAX_MODE_IDS, NULL, NULL);

        for (i = 0; i < num_modes; ++i) {
            TV_SUPPORTED_MODE_NEW_T *mode = &supported_modes[i];
            if (!sys->native_interlaced) {
                if (mode->width != display_state.display.hdmi.width ||
                                mode->height != display_state.display.hdmi.height ||
                                mode->scan_mode == HDMI_INTERLACED)
                    continue;
            } else {
                if (mode->width != vd->fmt.i_visible_width ||
                        mode->height != vd->fmt.i_visible_height)
                    continue;
                if (mode->scan_mode != sys->b_progressive ? HDMI_NONINTERLACED : HDMI_INTERLACED)
                    continue;
            }

            score = fmod(supported_modes[i].frame_rate, frame_rate);
            if((best_id < 0) || (score < best_score)) {
                best_id = i;
                best_score = score;
            }
        }

        if((best_id >= 0) && (display_state.display.hdmi.mode != supported_modes[best_id].code)) {
            msg_Info(vd, "Setting HDMI refresh rate to %"PRIu32,
                            supported_modes[best_id].frame_rate);
            vc_tv_hdmi_power_on_explicit_new(HDMI_MODE_HDMI,
                            supported_modes[best_id].group,
                            supported_modes[best_id].code);
        }

        if (sys->native_interlaced &&
                supported_modes[best_id].scan_mode == HDMI_INTERLACED) {
            char hvs_mode = sys->b_top_field_first ? '1' : '2';
            if (vc_gencmd(response, sizeof(response), "hvs_update_fields %c",
                    hvs_mode) != 0 || response[18] != hvs_mode)
                msg_Warn(vd, "Could not set hvs field mode");
            else
                msg_Info(vd, "Configured hvs field mode for interlaced %s playback",
                        sys->b_top_field_first ? "tff" : "bff");
        }
    }
}
bool DisplayManagerRPI::setDisplayMode(int display, int mode)
{
  if (!isValidDisplayMode(display, mode))
    return false;

  HDMI_PROPERTY_PARAM_T property;
  property.property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE;
  property.param1 = (mode % 2) ? HDMI_PIXEL_CLOCK_TYPE_NTSC : HDMI_PIXEL_CLOCK_TYPE_PAL;
  property.param2 = 0;
  vc_tv_hdmi_set_property(&property);

  TV_SUPPORTED_MODE_NEW_T* tvmode = &m_modes[mode / 2];
  bool ret = vc_tv_hdmi_power_on_explicit_new(HDMI_MODE_HDMI, (HDMI_RES_GROUP_T)tvmode->group, tvmode->code) == 0;
  if (!ret)
  {
    QLOG_ERROR() << "Failed to switch display mode" << ret;
  }

  return ret;
}
示例#3
0
/**
 * Return old mode so we can reset
 */
int
rpi_set_display_framerate(float fps, int width, int height)
{
  TV_DISPLAY_STATE_T state = {};

  if(vc_tv_get_display_state(&state)) {
    TRACE(TRACE_DEBUG, "TV", "Failed to get TV state");
    return -1;
  }

  TRACE(TRACE_DEBUG, "TV",
        "Searching for mode for %d x %d @ %f fps. Current mode=%d",
        width, height, fps, state.display.hdmi.mode);


  HDMI_RES_GROUP_T prefer_group;
  uint32_t prefer_mode;

  int native_deinterlace = 0;

  int num_modes =
    vc_tv_hdmi_get_supported_modes_new(HDMI_RES_GROUP_CEA, NULL, 0,
                                       &prefer_group, &prefer_mode);

  if(num_modes <= 0)
    return -1;

  TV_SUPPORTED_MODE_NEW_T *modes = alloca(sizeof(TV_SUPPORTED_MODE_NEW_T) *
                                          num_modes);

  num_modes =
    vc_tv_hdmi_get_supported_modes_new(HDMI_RES_GROUP_CEA, modes, num_modes,
                                       &prefer_group, &prefer_mode);

  TV_SUPPORTED_MODE_NEW_T *best_mode = NULL;

  uint32_t best_score = 1<<30;

  for(int i = 0; i < num_modes; i++) {
    TV_SUPPORTED_MODE_NEW_T *tv = modes + i;

    uint32_t score = 0;
    uint32_t w = tv->width;
    uint32_t h = tv->height;
    uint32_t r = tv->frame_rate;

    /* Check if frame rate match (equal or exact multiple) */
    if(fabs(r - 1.0f*fps) / fps < 0.002f)
      score += 0;
    else if(fabs(r - 2.0f*fps) / fps < 0.002f)
      score += 1<<8;
    else
      score += (1<<16) + (1<<20)/r; // bad - but prefer higher framerate

    /* Check size too, only choose, bigger resolutions */
    if(width && height)
      {
        /* cost of too small a resolution is high */
        score += MAX((int)(width -w), 0) * (1<<16);
        score += MAX((int)(height-h), 0) * (1<<16);
        /* cost of too high a resolution is lower */
        score += MAX((int)(w-width ), 0) * (1<<4);
        score += MAX((int)(h-height), 0) * (1<<4);
      }

    // native is good
    if (!tv->native)
      score += 1<<16;

#if 0
    // wanting 3D but not getting it is a negative
    if (is3d == CONF_FLAGS_FORMAT_SBS && !(tv->struct_3d_mask & HDMI_3D_STRUCT_SIDE_BY_SIDE_HALF_HORIZONTAL))
      score += 1<<18;
    if (is3d == CONF_FLAGS_FORMAT_TB  && !(tv->struct_3d_mask & HDMI_3D_STRUCT_TOP_AND_BOTTOM))
      score += 1<<18;
#endif

    // prefer square pixels modes
    float par = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio)*(float)tv->height/(float)tv->width;
    score += fabs(par - 1.0f) * (1<<12);

    if(score < best_score) {
      best_mode = tv;
      best_score = score;
    }
  }

  if(best_mode == NULL)
    return -1;


  char response[80];
  TRACE(TRACE_DEBUG, "TV",
        "Output mode %d: %dx%d@%d %s%s:%x\n",
        best_mode->code, best_mode->width, best_mode->height,
        best_mode->frame_rate, best_mode->native ? "N":"",
        best_mode->scan_mode?"I":"", best_mode->code);

  if (native_deinterlace && best_mode->scan_mode)
    vc_gencmd(response, sizeof response, "hvs_update_fields %d", 1);

  // if we are closer to ntsc version of framerate, let gpu know
  int ifps = (int)(fps+0.5f);
  int ntsc_freq = fabs(fps*1001.0f/1000.0f - ifps) < fabs(fps-ifps);
  vc_gencmd(response, sizeof response, "hdmi_ntsc_freqs %d", ntsc_freq);

  /* Inform TV of any 3D settings. Note this property just applies
     to next hdmi mode change, so no need to call for 2D modes */
  HDMI_PROPERTY_PARAM_T property;
  property.property = HDMI_PROPERTY_3D_STRUCTURE;
  property.param1 = HDMI_3D_FORMAT_NONE;
  property.param2 = 0;

#if 0
  if (is3d != CONF_FLAGS_FORMAT_NONE)
    {
      if (is3d == CONF_FLAGS_FORMAT_SBS && best_mode->struct_3d_mask & HDMI_3D_STRUCT_SIDE_BY_SIDE_HALF_HORIZONTAL)
        property.param1 = HDMI_3D_FORMAT_SBS_HALF;
      else if (is3d == CONF_FLAGS_FORMAT_TB && best_mode->struct_3d_mask & HDMI_3D_STRUCT_TOP_AND_BOTTOM)
        property.param1 = HDMI_3D_FORMAT_TB_HALF;
      m_BcmHost.vc_tv_hdmi_set_property(&property);
    }
#endif

  TRACE(TRACE_DEBUG, "TV",
        "ntsc_freq:%d %s%s\n", ntsc_freq,
        property.param1 == HDMI_3D_FORMAT_SBS_HALF ? "3DSBS":"",
        property.param1 == HDMI_3D_FORMAT_TB_HALF ? "3DTB":"");

  int err =
    vc_tv_hdmi_power_on_explicit_new(HDMI_MODE_HDMI,
                                     HDMI_RES_GROUP_CEA,
                                     best_mode->code);

  if(err) {
    TRACE(TRACE_DEBUG, "TV", "Failed to set mode %d", best_mode->code);
    return -1;
  }
  return state.display.hdmi.mode;
}
示例#4
0
EGLNativeWindowType _glusCreateNativeWindowType(const char* title, const GLUSint width, const GLUSint height, const GLUSboolean fullscreen, const GLUSboolean noResize)
{
	const SDL_VideoInfo* videoInfo;

	//

	DISPMANX_UPDATE_HANDLE_T dispmanUpdate;
	DISPMANX_ELEMENT_HANDLE_T dispmanElement;
	VC_RECT_T dstRect;
	VC_RECT_T srcRect;
	VC_DISPMANX_ALPHA_T dispmanAlpha;
	int32_t success;
	int32_t windowWidth;
	int32_t windowHeight;

	glusLogPrint(GLUS_LOG_INFO, "Parameters 'title' and 'noResize' are not used");

	// Initialize graphics system

	bcm_host_init();

	// Set fullscreen, if wanted

	if (fullscreen)
	{
		const uint32_t MAX_SUPPORTED_MODES = 128;
		HDMI_RES_GROUP_T group = HDMI_RES_GROUP_DMT;
		TV_SUPPORTED_MODE_NEW_T supportedModes[MAX_SUPPORTED_MODES];
		int32_t i, numberSupportedModes;

		numberSupportedModes = vc_tv_hdmi_get_supported_modes_new(group, supportedModes, MAX_SUPPORTED_MODES, 0, 0);

		for (i = 0; i < numberSupportedModes; i++)
		{
			if (supportedModes[i].width == (uint32_t)width && supportedModes[i].height == (uint32_t)height && supportedModes[i].frame_rate >= 60)
			{
				break;
			}
		}

		if (i == numberSupportedModes)
		{
			glusLogPrint(GLUS_LOG_ERROR, "No matching display resolution found: ", width, height);

			return EGL_NO_SURFACE ;
		}

		vc_tv_register_callback(resizeDone, 0);

		if (vc_tv_hdmi_power_on_explicit_new(group, supportedModes[i].group, supportedModes[i].code) != 0)
		{
			vc_tv_unregister_callback(resizeDone);

			glusLogPrint(GLUS_LOG_ERROR, "Could not switch to full screen: ", width, height);

			return EGL_NO_SURFACE ;
		}

		waitResizeDone();

		vc_tv_unregister_callback(resizeDone);

		windowWidth = width;
		windowHeight = height;

		_fullscreen = GLUS_TRUE;
	}
	else
	{
		windowWidth = width;
		windowHeight = height;
	}

	//

	_nativeDisplay = vc_dispmanx_display_open(0 /* LCD */);

	if (!_nativeDisplay)
	{
		glusLogPrint(GLUS_LOG_ERROR, "Could not open display");

		return EGL_NO_SURFACE ;
	}

	//

	if (SDL_Init(SDL_INIT_VIDEO) != 0)
	{
		glusLogPrint(GLUS_LOG_ERROR, "Could not initialize SDL");

		return EGL_NO_SURFACE ;
	}

	videoInfo = SDL_GetVideoInfo();

	if (!videoInfo)
	{
		glusLogPrint(GLUS_LOG_ERROR, "Could not get video info for SDL");

		return EGL_NO_SURFACE ;
	}

	if (!SDL_SetVideoMode(videoInfo->current_w, videoInfo->current_h, videoInfo->vfmt->BitsPerPixel, SDL_HWSURFACE))
	{
		glusLogPrint(GLUS_LOG_ERROR, "Set video mode for SDL failed");

		return EGL_NO_SURFACE ;
	}

	SDL_ShowCursor(SDL_DISABLE);

	//

	dstRect.x = 0;
	dstRect.y = 0;
	dstRect.width = windowWidth;
	dstRect.height = windowHeight;

	srcRect.x = 0;
	srcRect.y = 0;
	srcRect.width = windowWidth << 16;
	srcRect.height = windowHeight << 16;

	dispmanAlpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
	dispmanAlpha.mask = 0xFFFFFFFF;
	dispmanAlpha.opacity = 255;

	dispmanUpdate = vc_dispmanx_update_start(0);

	dispmanElement = vc_dispmanx_element_add(dispmanUpdate, _nativeDisplay, 0 /*layer*/, &dstRect, 0 /*src*/, &srcRect, DISPMANX_PROTECTION_NONE, &dispmanAlpha, 0/*clamp*/, 0/*transform*/);

	success = vc_dispmanx_update_submit_sync(dispmanUpdate);

	if (!dispmanElement || success < 0)
	{
		glusLogPrint(GLUS_LOG_ERROR, "Could not add element");

		return EGL_NO_SURFACE ;
	}

	_width = windowWidth;
	_height = windowHeight;

	_nativeWindow.element = dispmanElement;
	_nativeWindow.width = windowWidth;
	_nativeWindow.height = windowHeight;

	_nativeWindowCreated = GLUS_TRUE;

	return (EGLNativeWindowType)&_nativeWindow;
}