diff options
| author | phintuka <phintuka> | 2008-12-06 00:34:09 +0000 | 
|---|---|---|
| committer | phintuka <phintuka> | 2008-12-06 00:34:09 +0000 | 
| commit | 32c5a57368c8772d8b9f5de6958a7fa25a49845f (patch) | |
| tree | a16187501a3ef9bf9b1ff8ece633a2a1392ef649 | |
| parent | 20d8c1c8e3731a7bc406709020ea145658804108 (diff) | |
| download | xineliboutput-32c5a57368c8772d8b9f5de6958a7fa25a49845f.tar.gz xineliboutput-32c5a57368c8772d8b9f5de6958a7fa25a49845f.tar.bz2 | |
exec_osd_set_rle()
| -rw-r--r-- | xine_input_vdr.c | 351 | 
1 files changed, 174 insertions, 177 deletions
| diff --git a/xine_input_vdr.c b/xine_input_vdr.c index 982ed2a9..6a3a9949 100644 --- a/xine_input_vdr.c +++ b/xine_input_vdr.c @@ -4,7 +4,7 @@   * See the main source file 'xineliboutput.c' for copyright information and   * how to reach the author.   * - * $Id: xine_input_vdr.c,v 1.205 2008-12-05 21:30:19 phintuka Exp $ + * $Id: xine_input_vdr.c,v 1.206 2008-12-06 00:34:09 phintuka Exp $   *   */ @@ -1837,55 +1837,185 @@ static int exec_osd_close(vdr_input_plugin_t *this, xine_stream_t *stream,  }  /* + * exec_osd_set_rle() + * + */ +static int exec_osd_set_rle(vdr_input_plugin_t *this, xine_stream_t *stream,  +			    video_overlay_manager_t *ovl_manager, osd_command_t *cmd) +{ +  video_overlay_event_t ov_event   = {0}; +  vo_overlay_t          ov_overlay = {0}; +  int use_unscaled       = 0; +  int rle_scaled         = 0; +  int unscaled_supported = 1; +  int vo_scaling         = 0; +  int handle             = this->osdhandle[cmd->wnd]; + +  stream->video_out->enable_ovl(stream->video_out, 1); + +  /* get / allocate OSD handle */ +  if (handle < 0) +    handle = this->osdhandle[cmd->wnd] = ovl_manager->get_handle(ovl_manager,0); + +  /* fill SHOW event */ +  ov_event.event_type         = OVERLAY_EVENT_SHOW; +  ov_event.vpts               = osd_exec_vpts(this, stream, cmd); +  ov_event.object.handle      = handle; +  ov_event.object.overlay     = &ov_overlay; +  ov_event.object.object_type = 1; /* menu */ + +  /* check for unscaled OSD capability and request */ +  if (! (stream->video_out->get_capabilities(stream->video_out) & VO_CAP_UNSCALED_OVERLAY)) +    unscaled_supported = 0; +  else if (cmd->flags & OSDFLAG_UNSCALED) +    use_unscaled = 1; + +  /* store osd for later rescaling (done if video size changes) */ + +  clear_osdcmd(&this->osddata[cmd->wnd]); + +  memcpy(&this->osddata[cmd->wnd], cmd, sizeof(osd_command_t)); +  this->osddata[cmd->wnd].data = NULL; +  if (cmd->palette) { +    this->osddata[cmd->wnd].palette = malloc(sizeof(xine_clut_t)*cmd->colors); +    memcpy(this->osddata[cmd->wnd].palette, cmd->palette, 4*cmd->colors); +  } + +  /* request OSD scaling from video_out layer */ +  if (stream->video_out->get_capabilities(stream->video_out) & VO_CAP_OSDSCALING) { +    stream->video_out->set_property(stream->video_out, VO_PROP_OSD_SCALING, cmd->scaling ? 1 : 0); +    vo_scaling = 1; +  } + +  /* if video size differs from expected (VDR osd is designed for 720x576), +     scale osd to video size or use unscaled (display resolution) +     blending */ +  if (!vo_scaling && !use_unscaled) { +    int w_hi = this->vdr_osd_width  * 1100 / 1000; +    int w_lo = this->vdr_osd_width  *  950 / 1000; +    int h_hi = this->vdr_osd_height * 1100 / 1000; +    int h_lo = this->vdr_osd_height *  950 / 1000; +    int width_diff = 0, height_diff = 0; + +    if      (this->video_width  < w_lo) width_diff  = -1; +    else if (this->video_width  > w_hi) width_diff  =  1; +    if      (this->video_height < h_lo) height_diff = -1; +    else if (this->video_height > h_hi) height_diff =  1; + +    if (width_diff || height_diff) { +      int new_w = (0x100*cmd->w * this->video_width  +		   / this->vdr_osd_width)>>8; +      int new_h = (0x100*cmd->h * this->video_height  +		   / this->vdr_osd_height)>>8; +      LOGOSD("Size out of margins, rescaling rle image"); +      if (width_diff < 0 || height_diff < 0) +	if (unscaled_supported && (cmd->flags & OSDFLAG_UNSCALED_LOWRES)) +	  use_unscaled = 1; + +      if (!use_unscaled && cmd->scaling > 0) { + +	if (height_diff || width_diff) { +	  /* store original RLE data */ +	  this->osddata[cmd->wnd].data = cmd->data; +	  this->osddata[cmd->wnd].datalen = cmd->datalen; +	     +	  rle_scaled = 1; +	  scale_rle_image(cmd, new_w, new_h, this->class->fast_osd_scaling ? 0 : 1); +	} else { +	  LOGOSD("osd_command: size out of margins, using UNSCALED"); +	  use_unscaled = unscaled_supported; +	} +      } +    } +  } + +  if (!vo_scaling && use_unscaled) { +    int win_width  = stream->video_out->get_property(stream->video_out,  +						     VO_PROP_WINDOW_WIDTH); +    int win_height = stream->video_out->get_property(stream->video_out,  +						     VO_PROP_WINDOW_HEIGHT); +    if (cmd->scaling > 0) { +      /* it is not nice to have subs in _middle_ of display when using 1440x900 etc... */ + +      if (win_width > 240 && win_height > 196) { +	if (cmd->scaling > 0) { +	  /*LOGMSG("Scaling unscaled OSD to %dx%d", win_width, win_height);*/ +	  if (win_width != this->vdr_osd_width || win_height != this->vdr_osd_height) { +	    int new_w = (0x100*cmd->w * win_width  +			 / this->vdr_osd_width)>>8; +	    int new_h = (0x100*cmd->h * win_height  +			 / this->vdr_osd_height)>>8; + +	    /* store original RLE data */ +	    this->osddata[cmd->wnd].data = cmd->data; +	    this->osddata[cmd->wnd].datalen = cmd->datalen; +	     +	    rle_scaled = 1; +	    scale_rle_image(cmd, new_w, new_h, this->class->fast_osd_scaling ? 0 : 1); +	  } +	} +      } +    } +  } + +  /* fill ov_overlay */ +  osdcmd_to_overlay(&ov_overlay, cmd); +  ov_overlay.unscaled = use_unscaled; + +  /* tag this overlay */ +  ov_overlay.hili_rgb_clut = -9999; +     +  /* if no scaling was required, we may still need to re-center OSD */ +  if (!vo_scaling && !rle_scaled) { +    if (this->video_width != this->vdr_osd_width) +      ov_overlay.x += (this->video_width - this->vdr_osd_width)/2; +    if (this->video_height != this->vdr_osd_height) +      ov_overlay.y += (this->video_height - this->vdr_osd_height)/2; +  } + +  /* store rle for later scaling (done if video size changes) */ +  if (!rle_scaled /* if scaled, we already have a copy (original data) */ ) { +    this->osddata[cmd->wnd].data = malloc(cmd->datalen); +    memcpy(this->osddata[cmd->wnd].data, cmd->data, cmd->datalen); +  } +  cmd->data = NULL; /* we 'consume' data (ownership goes for xine-lib osd manager) */ + +  /* send event to overlay manager */ +  while (ovl_manager->add_event(ovl_manager, (void *)&ov_event) < 0) { +    LOGDBG("OSD_Set_RLE(%d): overlay manager queue full !", cmd->wnd); +    ovl_manager->flush_events(ovl_manager); +    continue; +  } + +  this->last_changed_vpts[cmd->wnd] = ov_event.vpts ?: xine_get_current_vpts(stream); + +  return CONTROL_OK; +} + +/*   * exec_osd_command()   *   * - handler for VDR-based osd_command_t events   */  static int exec_osd_command(vdr_input_plugin_t *this, osd_command_t *cmd)  { -  video_overlay_manager_t *ovl_manager; -  xine_stream_t           *stream = this->slave_stream ?: this->stream; -  int handle = -1; +  xine_stream_t *stream = this->slave_stream ?: this->stream;    /* Caller must have locked this->osd_lock ! */    LOGOSD("exec_osd_command %d", cmd ? cmd->cmd : -1);     /* Check parameters */ - -  if (!cmd || !this || !stream) { +  if (!cmd || !stream) {      LOGMSG("exec_osd_command: Stream not initialized !");      return CONTROL_DISCONNECTED;    } -    if (cmd->wnd < 0 || cmd->wnd >= MAX_OSD_OBJECT) {      LOGMSG("exec_osd_command: OSD window handle %d out of range !", cmd->wnd);      return CONTROL_PARAM_ERROR;    } -  handle = this->osdhandle[cmd->wnd]; - -  /* we already have port ticket */ -  ovl_manager = stream->video_out->get_overlay_manager(stream->video_out); -  if(!ovl_manager) { -    LOGMSG("exec_osd_command: Stream has no overlay manager !"); -    return CONTROL_DISCONNECTED; -  } - -  /* Does the OSD exist ? */ -  if (handle < 0) { -    if (cmd->cmd == OSD_Close) { -      LOGMSG("exec_osd_command: Attempt to close non-existing OSD (%d) !", cmd->wnd); -      return CONTROL_PARAM_ERROR; -    } -    if (cmd->cmd == OSD_Move  || -	cmd->cmd == OSD_SetPalette) { -      LOGMSG("exec_osd_command: Attempt to modify non-existing OSD (%d) !", cmd->wnd); -      return CONTROL_PARAM_ERROR; -    } -  } - -  /* Execute command */ +  /* execute */    if (cmd->cmd == OSD_Nop)      return exec_osd_nop(this, stream, cmd); @@ -1899,163 +2029,30 @@ static int exec_osd_command(vdr_input_plugin_t *this, osd_command_t *cmd)    if (cmd->cmd == OSD_Move)      return exec_osd_move(this, cmd); +  /* Get overlay manager. We already have port ticket. */ +  video_overlay_manager_t *ovl_manager = stream->video_out->get_overlay_manager(stream->video_out); +  if (!ovl_manager) { +    LOGMSG("exec_osd_command: Stream has no overlay manager !"); +    return CONTROL_DISCONNECTED; +  } +    if (cmd->cmd == OSD_Flush)      return exec_osd_flush(this, ovl_manager, cmd); +  if (cmd->cmd == OSD_Set_RLE) +    return exec_osd_set_rle(this, stream, ovl_manager, cmd); +    if (cmd->cmd == OSD_Close)      return exec_osd_close(this, stream, ovl_manager, cmd); -  if(cmd->cmd == OSD_Set_YUV) { +  if (cmd->cmd == OSD_Set_YUV) {      /* TODO */ - -  } else if(cmd->cmd == OSD_Set_RLE) { - -    vo_overlay_t ov_overlay = {0}; -    int use_unscaled = 0; -    int rle_scaled = 0; -    int unscaled_supported = 1; - -    stream->video_out->enable_ovl(stream->video_out, 1); - -    /* allocate OSD handle */ -    if(handle < 0) -      handle = this->osdhandle[cmd->wnd] =  -	ovl_manager->get_handle(ovl_manager,0); - -    /* fill SHOW event */ -    video_overlay_event_t ov_event = {0}; -    ov_event.event_type = OVERLAY_EVENT_SHOW; -    ov_event.vpts = osd_exec_vpts(this, stream, cmd); -    ov_event.object.handle = handle; -    ov_event.object.overlay = &ov_overlay; -    ov_event.object.object_type = 1; /* menu */ - -    /* check for unscaled OSD capability and request */ -    if(!(stream->video_out->get_capabilities(stream->video_out) & -	 VO_CAP_UNSCALED_OVERLAY)) -      unscaled_supported = 0; -    else if(cmd->flags & OSDFLAG_UNSCALED) -      use_unscaled = 1; - -    /* store osd for later rescaling (done if video size changes) */ - -    clear_osdcmd(&this->osddata[cmd->wnd]); - -    memcpy(&this->osddata[cmd->wnd], cmd, sizeof(osd_command_t)); -    this->osddata[cmd->wnd].data = NULL; -    if(cmd->palette) { -      this->osddata[cmd->wnd].palette = malloc(sizeof(xine_clut_t)*cmd->colors); -      memcpy(this->osddata[cmd->wnd].palette, cmd->palette, 4*cmd->colors); -    } - -    /* if video size differs from expected (VDR osd is designed for 720x576), -       scale osd to video size or use unscaled (display resolution) -       blending */ -    if(!use_unscaled) { -      int w_hi = this->vdr_osd_width  * 1100 / 1000; -      int w_lo = this->vdr_osd_width  *  950 / 1000; -      int h_hi = this->vdr_osd_height * 1100 / 1000; -      int h_lo = this->vdr_osd_height *  950 / 1000; -      int width_diff = 0, height_diff = 0; - -      if(this->video_width  < w_lo)  width_diff  = -1; -      else if(this->video_width  > w_hi)  width_diff  =  1; -      if(this->video_height < h_lo) height_diff = -1; -      else if(this->video_height > h_hi) height_diff =  1; - -      if(width_diff || height_diff) { -	int new_w = (0x100*cmd->w * this->video_width  -		     / this->vdr_osd_width)>>8; -	int new_h = (0x100*cmd->h * this->video_height  -		     / this->vdr_osd_height)>>8; -	LOGOSD("Size out of margins, rescaling rle image"); -	if(width_diff < 0 || height_diff < 0) -	  if(unscaled_supported && (cmd->flags & OSDFLAG_UNSCALED_LOWRES)) -	    use_unscaled = 1; - -	if(!use_unscaled && cmd->scaling > 0) { - -	  if(height_diff || width_diff) { -	    this->osddata[cmd->wnd].data = cmd->data; -	    this->osddata[cmd->wnd].datalen = cmd->datalen; -	     -	    rle_scaled = 1; -	    scale_rle_image(cmd, new_w, new_h, this->class->fast_osd_scaling ? 0 : 1); -	  } else { -	    LOGOSD("osd_command: size out of margins, using UNSCALED"); -	    use_unscaled = unscaled_supported; -	  } -	} -      } -    } - -    if(use_unscaled) { -      int win_width  = stream->video_out->get_property(stream->video_out,  -						       VO_PROP_WINDOW_WIDTH); -      int win_height = stream->video_out->get_property(stream->video_out,  -						       VO_PROP_WINDOW_HEIGHT); -      if(cmd->scaling > 0) { -	/* it is not nice to have subs in _middle_ of display when using 1440x900 etc... */ -	 -	if(win_width > 240 && win_height > 196) { -	  if(cmd->scaling > 0) { -	    /*LOGMSG("Scaling unscaled OSD to %dx%d", win_width, win_height);*/ -	    if(win_width != this->vdr_osd_width || win_height != this->vdr_osd_height) { -	      int new_w = (0x100*cmd->w * win_width  -			   / this->vdr_osd_width)>>8; -	      int new_h = (0x100*cmd->h * win_height  -			   / this->vdr_osd_height)>>8; - -	      this->osddata[cmd->wnd].data = cmd->data; -	      this->osddata[cmd->wnd].datalen = cmd->datalen; -	     -	      rle_scaled = 1; -	      scale_rle_image(cmd, new_w, new_h, this->class->fast_osd_scaling ? 0 : 1); -	    } -	  } -	} -      } -    } - -    /* fill ov_overlay */ -    osdcmd_to_overlay(&ov_overlay, cmd); - -    ov_overlay.unscaled = use_unscaled; - -    /* no scaling required, but may still need to re-center OSD */ -    if(!rle_scaled) { -      if(this->video_width != this->vdr_osd_width) -	ov_overlay.x += (this->video_width - this->vdr_osd_width)/2; -      if(this->video_height != this->vdr_osd_height) -	ov_overlay.y += (this->video_height - this->vdr_osd_height)/2; -    } - -    /* store rle for later scaling (done if video size changes) */ -    if(/*!use_unscaled &&*/ -       /*!this->osddata[cmd->wnd].data && */ -       !rle_scaled /*if scaled, we already have a copy (original data)*/ ) { -      this->osddata[cmd->wnd].data = malloc(cmd->datalen); -      memcpy(this->osddata[cmd->wnd].data, cmd->data, cmd->datalen); -    } -    cmd->data = NULL;/* we 'consume' data (ownership goes for osd manager) */ - -    /* send event to overlay manager */ -    while (ovl_manager->add_event(ovl_manager, (void *)&ov_event) < 0) { -      LOGDBG("OSD_Set_RLE(%d): overlay manager queue full !", cmd->wnd); -      ovl_manager->flush_events(ovl_manager); -      continue; -    } - -    this->last_changed_vpts[cmd->wnd] =  -      ov_event.vpts ?: xine_get_current_vpts(stream); - -  } else { -    LOGMSG("Unknown OSD command %d", cmd->cmd); +    LOGMSG("exec_osd_command: OSD_Set_YUV not implemented !");      return CONTROL_PARAM_ERROR;    } -  LOGOSD("OSD command %d done", cmd->cmd);  -  return CONTROL_OK; +  LOGMSG("Unknown OSD command %d", cmd->cmd); +  return CONTROL_PARAM_ERROR;  }  static void vdr_scale_osds(vdr_input_plugin_t *this,  | 
