コード例 #1
0
DisplayManagerRPI::DisplayManagerRPI(QObject* parent) : DisplayManager(parent)
{
  connect(this, &DisplayManagerRPI::onTvChange,
          this, &DisplayManagerRPI::handleTvChange,
          Qt::QueuedConnection);

  vc_tv_register_callback(&tv_callback, (void *)this);
}
コード例 #2
0
static int start_monitor( void )
{
   if ( vcos_event_create( &quit_event, "tvservice" ) != VCOS_SUCCESS )
   {
      LOG_ERR( "Failed to create quit event" );

      return -1;
   }

   // Handle the INT and TERM signals so we can quit
   signal( SIGINT, control_c );
   signal( SIGTERM, control_c );

   vc_tv_register_callback( &tvservice_callback, NULL );

   return 0;
}
コード例 #3
0
ファイル: tvservice.c プロジェクト: 1stsetup/piMythclient
int tvserviceInit() 
{
	if (initialized) return 0;

	VCHI_INSTANCE_T vchi_instance;
	VCHI_CONNECTION_T *vchi_connections;

	// initialise bcm_host
	initializeBCM();
   
	// initialise vcos/vchi
	initializeVCOS();

	if (vchi_initialise(&vchi_instance) != VCHIQ_SUCCESS) {
		logInfo(LOG_TVSERVICE, "failed to open vchiq instance\n");
		return -2;
	}

	// create a vchi connection
	if ( vchi_connect( NULL, 0, vchi_instance ) != 0) {
		logInfo(LOG_TVSERVICE, "failed to connect to VCHI\n");
		return -3;
	}

	// connect to tvservice
	if ( vc_vchi_tv_init( vchi_instance, &vchi_connections, 1) != 0) {
		logInfo(LOG_TVSERVICE, "failed to connect to tvservice\n");
		return -4;
	}

	vc_tv_register_callback(&tvserviceCallback, NULL);

	tvstate = malloc(sizeof(TV_GET_STATE_RESP_T));

	vc_tv_get_state(tvstate);
	logInfo(LOG_TVSERVICE, "tvstate: %dx%d, %d fps, %s\n", tvstate->width, tvstate->height, tvstate->frame_rate, tvstate->scan_mode ? "interlaced" : "progressive");

	if (vc_tv_hdmi_set_spd("1st Setup", "piMythClient", HDMI_SPD_TYPE_PMP) != 0) {
		logInfo(LOG_TVSERVICE, "failed to vc_tv_hdmi_set_spd\n");
	}

	initialized = 1;

	return 0;
}
コード例 #4
0
ファイル: glus_raspberrypi_es.c プロジェクト: Pope991/OpenGL
GLUSvoid _glusDestroyNativeWindow()
{
	if (_nativeWindowCreated)
	{
		DISPMANX_UPDATE_HANDLE_T dispmanUpdate;

		dispmanUpdate = vc_dispmanx_update_start(0);
		vc_dispmanx_element_remove(dispmanUpdate, _nativeWindow.element);
		vc_dispmanx_update_submit_sync(dispmanUpdate);

		_nativeWindowCreated = GLUS_FALSE;
	}
	memset(&_nativeWindow, 0, sizeof(_nativeWindow));

	if (_nativeDisplay)
	{
		vc_dispmanx_display_close(_nativeDisplay);

		_nativeDisplay = 0;
	}

	if (_fullscreen)
	{
		vc_tv_register_callback(resizeDone, 0);

		if (vc_tv_hdmi_power_on_preferred() == 0)
		{
			waitResizeDone();
		}

		vc_tv_unregister_callback(resizeDone);

		_fullscreen = GLUS_FALSE;
	}

	SDL_ShowCursor(SDL_ENABLE);

	SDL_Quit();

	bcm_host_deinit();
}
コード例 #5
0
ファイル: vout.c プロジェクト: Kubink/vlc
static int Open(vlc_object_t *object)
{
    vout_display_t *vd = (vout_display_t *)object;
    vout_display_sys_t *sys;
    uint32_t buffer_pitch, buffer_height;
    vout_display_place_t place;
    MMAL_DISPLAYREGION_T display_region;
    uint32_t offsets[3];
    MMAL_STATUS_T status;
    int ret = VLC_SUCCESS;
    unsigned i;

    if (vout_display_IsWindowed(vd))
        return VLC_EGENERIC;

    sys = calloc(1, sizeof(struct vout_display_sys_t));
    if (!sys)
        return VLC_ENOMEM;
    vd->sys = sys;

    sys->layer = var_InheritInteger(vd, MMAL_LAYER_NAME);
    bcm_host_init();

    vd->info.has_hide_mouse = true;
    sys->opaque = vd->fmt.i_chroma == VLC_CODEC_MMAL_OPAQUE;

    status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &sys->component);
    if (status != MMAL_SUCCESS) {
        msg_Err(vd, "Failed to create MMAL component %s (status=%"PRIx32" %s)",
                        MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, status, mmal_status_to_string(status));
        ret = VLC_EGENERIC;
        goto out;
    }

    sys->component->control->userdata = (struct MMAL_PORT_USERDATA_T *)vd;
    status = mmal_port_enable(sys->component->control, control_port_cb);
    if (status != MMAL_SUCCESS) {
        msg_Err(vd, "Failed to enable control port %s (status=%"PRIx32" %s)",
                        sys->component->control->name, status, mmal_status_to_string(status));
        ret = VLC_EGENERIC;
        goto out;
    }

    sys->input = sys->component->input[0];
    sys->input->userdata = (struct MMAL_PORT_USERDATA_T *)vd;

    if (sys->opaque) {
        sys->input->format->encoding = MMAL_ENCODING_OPAQUE;
        sys->i_planes = 1;
        sys->buffer_size = sys->input->buffer_size_recommended;
    } else {
        sys->input->format->encoding = MMAL_ENCODING_I420;
        vd->fmt.i_chroma = VLC_CODEC_I420;
        buffer_pitch = align(vd->fmt.i_width, 32);
        buffer_height = align(vd->fmt.i_height, 16);
        sys->i_planes = 3;
        sys->buffer_size = 3 * buffer_pitch * buffer_height / 2;
    }

    sys->input->format->es->video.width = vd->fmt.i_width;
    sys->input->format->es->video.height = vd->fmt.i_height;
    sys->input->format->es->video.crop.x = 0;
    sys->input->format->es->video.crop.y = 0;
    sys->input->format->es->video.crop.width = vd->fmt.i_width;
    sys->input->format->es->video.crop.height = vd->fmt.i_height;
    sys->input->format->es->video.par.num = vd->source.i_sar_num;
    sys->input->format->es->video.par.den = vd->source.i_sar_den;

    status = mmal_port_format_commit(sys->input);
    if (status != MMAL_SUCCESS) {
        msg_Err(vd, "Failed to commit format for input port %s (status=%"PRIx32" %s)",
                        sys->input->name, status, mmal_status_to_string(status));
        ret = VLC_EGENERIC;
        goto out;
    }
    sys->input->buffer_size = sys->input->buffer_size_recommended;

    vout_display_PlacePicture(&place, &vd->source, vd->cfg, false);
    display_region.hdr.id = MMAL_PARAMETER_DISPLAYREGION;
    display_region.hdr.size = sizeof(MMAL_DISPLAYREGION_T);
    display_region.fullscreen = MMAL_FALSE;
    display_region.src_rect.x = vd->fmt.i_x_offset;
    display_region.src_rect.y = vd->fmt.i_y_offset;
    display_region.src_rect.width = vd->fmt.i_visible_width;
    display_region.src_rect.height = vd->fmt.i_visible_height;
    display_region.dest_rect.x = place.x;
    display_region.dest_rect.y = place.y;
    display_region.dest_rect.width = place.width;
    display_region.dest_rect.height = place.height;
    display_region.layer = sys->layer;
    display_region.set = MMAL_DISPLAY_SET_FULLSCREEN | MMAL_DISPLAY_SET_SRC_RECT |
            MMAL_DISPLAY_SET_DEST_RECT | MMAL_DISPLAY_SET_LAYER;
    status = mmal_port_parameter_set(sys->input, &display_region.hdr);
    if (status != MMAL_SUCCESS) {
        msg_Err(vd, "Failed to set display region (status=%"PRIx32" %s)",
                        status, mmal_status_to_string(status));
        ret = VLC_EGENERIC;
        goto out;
    }

    offsets[0] = 0;
    for (i = 0; i < sys->i_planes; ++i) {
        sys->planes[i].i_lines = buffer_height;
        sys->planes[i].i_pitch = buffer_pitch;
        sys->planes[i].i_visible_lines = vd->fmt.i_visible_height;
        sys->planes[i].i_visible_pitch = vd->fmt.i_visible_width;

        if (i > 0) {
            offsets[i] = offsets[i - 1] + sys->planes[i - 1].i_pitch * sys->planes[i - 1].i_lines;
            sys->planes[i].i_lines /= 2;
            sys->planes[i].i_pitch /= 2;
            sys->planes[i].i_visible_lines /= 2;
            sys->planes[i].i_visible_pitch /= 2;
        }

        sys->planes[i].p_pixels = (uint8_t *)offsets[i];
    }

    vlc_mutex_init(&sys->buffer_mutex);
    vlc_cond_init(&sys->buffer_cond);
    vlc_mutex_init(&sys->manage_mutex);

    vd->pool = vd_pool;
    vd->prepare = vd_prepare;
    vd->display = vd_display;
    vd->control = vd_control;
    vd->manage = vd_manage;

    vc_tv_register_callback(tvservice_cb, vd);

    if (query_resolution(vd, &sys->display_width, &sys->display_height) >= 0) {
        vout_display_SendEventDisplaySize(vd, sys->display_width, sys->display_height);
    } else {
        sys->display_width = vd->cfg->display.width;
        sys->display_height = vd->cfg->display.height;
    }

    sys->dmx_handle = vc_dispmanx_display_open(0);
    vd->info.subpicture_chromas = subpicture_chromas;

out:
    if (ret != VLC_SUCCESS)
        Close(object);

    return ret;
}
コード例 #6
0
ファイル: context_rpi.c プロジェクト: rcombs/mpv
static bool recreate_dispmanx(struct ra_ctx *ctx)
{
    struct priv *p = ctx->priv;
    int display_nr = 0;
    int layer = 0;

    MP_VERBOSE(ctx, "Recreating DISPMANX state...\n");

    destroy_dispmanx(ctx);

    p->display = vc_dispmanx_display_open(display_nr);
    p->update = vc_dispmanx_update_start(0);
    if (!p->display || !p->update) {
        MP_FATAL(ctx, "Could not get DISPMANX objects.\n");
        goto fail;
    }

    uint32_t dispw, disph;
    if (graphics_get_display_size(0, &dispw, &disph) < 0) {
        MP_FATAL(ctx, "Could not get display size.\n");
        goto fail;
    }
    p->w = dispw;
    p->h = disph;

    if (ctx->vo->opts->fullscreen) {
        p->x = p->y = 0;
    } else {
        struct vo_win_geometry geo;
        struct mp_rect screenrc = {0, 0, p->w, p->h};

        vo_calc_window_geometry(ctx->vo, &screenrc, &geo);

        mp_rect_intersection(&geo.win, &screenrc);

        p->x = geo.win.x0;
        p->y = geo.win.y0;
        p->w = geo.win.x1 - geo.win.x0;
        p->h = geo.win.y1 - geo.win.y0;
    }

    // dispmanx is like a neanderthal version of Wayland - you can add an
    // overlay any place on the screen.
    VC_RECT_T dst = {.x = p->x, .y = p->y, .width = p->w, .height = p->h};
    VC_RECT_T src = {.width = p->w << 16, .height = p->h << 16};
    VC_DISPMANX_ALPHA_T alpha = {
        .flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE,
        .opacity = 0xFF,
    };
    p->window = vc_dispmanx_element_add(p->update, p->display, layer, &dst, 0,
                                        &src, DISPMANX_PROTECTION_NONE, &alpha,
                                        0, 0);
    if (!p->window) {
        MP_FATAL(ctx, "Could not add DISPMANX element.\n");
        goto fail;
    }

    vc_dispmanx_update_submit_sync(p->update);
    p->update = vc_dispmanx_update_start(0);

    p->egl_window = (EGL_DISPMANX_WINDOW_T){
        .element = p->window,
        .width = p->w,
        .height = p->h,
    };
    p->egl_surface = eglCreateWindowSurface(p->egl_display, p->egl_config,
                                            &p->egl_window, NULL);

    if (p->egl_surface == EGL_NO_SURFACE) {
        MP_FATAL(ctx, "Could not create EGL surface!\n");
        goto fail;
    }

    if (!eglMakeCurrent(p->egl_display, p->egl_surface, p->egl_surface,
                        p->egl_context))
    {
        MP_FATAL(ctx, "Failed to set context!\n");
        goto fail;
    }

    p->display_fps = 0;
    TV_GET_STATE_RESP_T tvstate;
    TV_DISPLAY_STATE_T tvstate_disp;
    if (!vc_tv_get_state(&tvstate) && !vc_tv_get_display_state(&tvstate_disp)) {
        if (tvstate_disp.state & (VC_HDMI_HDMI | VC_HDMI_DVI)) {
            p->display_fps = tvstate_disp.display.hdmi.frame_rate;

            HDMI_PROPERTY_PARAM_T param = {
                .property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE,
            };
            if (!vc_tv_hdmi_get_property(&param) &&
                param.param1 == HDMI_PIXEL_CLOCK_TYPE_NTSC)
                p->display_fps = p->display_fps / 1.001;
        } else {
            p->display_fps = tvstate_disp.display.sdtv.frame_rate;
        }
    }

    p->win_params[0] = display_nr;
    p->win_params[1] = layer;
    p->win_params[2] = p->x;
    p->win_params[3] = p->y;

    ctx->vo->dwidth = p->w;
    ctx->vo->dheight = p->h;
    ra_gl_ctx_resize(ctx->swapchain, p->w, p->h, 0);

    ctx->vo->want_redraw = true;

    vo_event(ctx->vo, VO_EVENT_WIN_STATE);
    return true;

fail:
    destroy_dispmanx(ctx);
    return false;
}

static void rpi_swap_buffers(struct ra_ctx *ctx)
{
    struct priv *p = ctx->priv;
    eglSwapBuffers(p->egl_display, p->egl_surface);
}

static bool rpi_init(struct ra_ctx *ctx)
{
    struct priv *p = ctx->priv = talloc_zero(ctx, struct priv);

    bcm_host_init();

    vc_tv_register_callback(tv_callback, ctx);

    p->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (!eglInitialize(p->egl_display, NULL, NULL)) {
        MP_FATAL(ctx, "EGL failed to initialize.\n");
        goto fail;
    }

    if (!mpegl_create_context(ctx, p->egl_display, &p->egl_context, &p->egl_config))
        goto fail;

    if (recreate_dispmanx(ctx) < 0)
        goto fail;

    mpegl_load_functions(&p->gl, ctx->log);

    struct ra_gl_ctx_params params = {
        .swap_buffers = rpi_swap_buffers,
        .native_display_type = "MPV_RPI_WINDOW",
        .native_display = p->win_params,
    };

    if (!ra_gl_ctx_init(ctx, &p->gl, params))
        goto fail;

    return true;

fail:
    rpi_uninit(ctx);
    return false;
}

static bool rpi_reconfig(struct ra_ctx *ctx)
{
    return recreate_dispmanx(ctx);
}

static struct mp_image *take_screenshot(struct ra_ctx *ctx)
{
    struct priv *p = ctx->priv;

    if (!p->display)
        return NULL;

    struct mp_image *img = mp_image_alloc(IMGFMT_BGR0, p->w, p->h);
    if (!img)
        return NULL;

    DISPMANX_RESOURCE_HANDLE_T resource =
        vc_dispmanx_resource_create(VC_IMAGE_ARGB8888,
                                    img->w | ((img->w * 4) << 16), img->h,
                                    &(int32_t){0});
    if (!resource)
        goto fail;

    if (vc_dispmanx_snapshot(p->display, resource, 0))
        goto fail;

    VC_RECT_T rc = {.width = img->w, .height = img->h};
    if (vc_dispmanx_resource_read_data(resource, &rc, img->planes[0], img->stride[0]))
        goto fail;

    vc_dispmanx_resource_delete(resource);
    return img;

fail:
    vc_dispmanx_resource_delete(resource);
    talloc_free(img);
    return NULL;
}

static int rpi_control(struct ra_ctx *ctx, int *events, int request, void *arg)
{
    struct priv *p = ctx->priv;

    switch (request) {
    case VOCTRL_SCREENSHOT_WIN:
        *(struct mp_image **)arg = take_screenshot(ctx);
        return VO_TRUE;
    case VOCTRL_FULLSCREEN:
        recreate_dispmanx(ctx);
        return VO_TRUE;
    case VOCTRL_CHECK_EVENTS:
        if (atomic_fetch_and(&p->reload_display, 0)) {
            MP_WARN(ctx, "Recovering from display mode switch...\n");
            recreate_dispmanx(ctx);
        }
        return VO_TRUE;
    case VOCTRL_GET_DISPLAY_FPS:
        *(double *)arg = p->display_fps;
        return VO_TRUE;
    }

    return VO_NOTIMPL;
}

const struct ra_ctx_fns ra_ctx_rpi = {
    .type           = "opengl",
    .name           = "rpi",
    .reconfig       = rpi_reconfig,
    .control        = rpi_control,
    .init           = rpi_init,
    .uninit         = rpi_uninit,
};
コード例 #7
0
ファイル: glus_raspberrypi_es.c プロジェクト: Pope991/OpenGL
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;
}