Example #1
0
static const char *
eog_exif_entry_get_value (ExifEntry    *e,
			  char         *buf,
			  guint         n_buf)
{
	ExifByteOrder bo;

	/* For now we only want to reformat some GPS values */
	if (G_LIKELY (exif_entry_get_ifd (e) != EXIF_IFD_GPS))
		return exif_entry_get_value (e, buf, n_buf);

	bo = exif_data_get_byte_order (e->parent->parent);

	/* Cast to number to avoid warnings about values not in enumeration */
	switch ((guint16) e->tag) {
		case EXIF_TAG_GPS_LATITUDE:
		case EXIF_TAG_GPS_LONGITUDE:
		{
			gsize rational_size;
			ExifRational r;
			gfloat h = 0., m = 0.;


			rational_size = exif_format_get_size (EXIF_FORMAT_RATIONAL);
			if (G_UNLIKELY (e->components != 3 ||
			    e->format != EXIF_FORMAT_RATIONAL))
				return exif_entry_get_value (e, buf, n_buf);

			r = exif_get_rational (e->data, bo);
			if (r.denominator != 0)
				h = (gfloat)r.numerator / r.denominator;

			r = exif_get_rational (e->data + rational_size, bo);
			if (r.denominator != 0)
				m = (gfloat)r.numerator / (gfloat)r.denominator;

			r = exif_get_rational (e->data + (2 * rational_size),
					       bo);
			if (r.numerator != 0 && r.denominator != 0) {
				gfloat s;

				s = (gfloat)r.numerator / (gfloat)r.denominator;
				g_snprintf (buf, n_buf,
					    "%.0f° %.0f' %.2f\"",
					    h, m, s);
			} else {
				g_snprintf (buf, n_buf,
					    "%.0f° %.2f'",
					    h, m);
			}

			break;
		}
		case EXIF_TAG_GPS_LATITUDE_REF:
		case EXIF_TAG_GPS_LONGITUDE_REF:
		{
			if (G_UNLIKELY (e->components != 2 ||
			    e->format != EXIF_FORMAT_ASCII))
				return exif_entry_get_value (e, buf, n_buf);

			switch (e->data[0]) {
			case 'N':
				g_snprintf (buf, n_buf, "%s", _("North"));
				break;
			case 'E':
				g_snprintf (buf, n_buf, "%s", _("East"));
				break;
			case 'W':
				g_snprintf (buf, n_buf, "%s", _("West"));
				break;
			case 'S':
				g_snprintf (buf, n_buf, "%s", _("South"));
				break;
			default:
				return exif_entry_get_value (e, buf, n_buf);
				break;
			}
			break;
		}
		default:
			return exif_entry_get_value (e, buf, n_buf);
			break;
	}

	return buf;
}
Example #2
0
gpointer thumbnail_loader_thread( VFSAsyncTask* task, VFSThumbnailLoader* loader )
{
    ThumbnailRequest* req;
    int i;
    gboolean load_big, need_update;

    while( G_LIKELY( ! vfs_async_task_is_cancelled(task) ))
    {
        vfs_async_task_lock( task );
        req = (ThumbnailRequest*)g_queue_pop_head( loader->queue );
        vfs_async_task_unlock( task );
        if( G_UNLIKELY( ! req ) )
            break;
        /* g_debug("pop: %s", req->file->name); */

        /* Only we have the reference. That means, no body is using the file */
        if( req->file->n_ref == 1 )
        {
            thumbnail_request_free( req );
            continue;
        }

        need_update = FALSE;
        for ( i = 0; i < 2; ++i )
        {
            if ( 0 == req->n_requests[ i ] )
                continue;

            load_big = ( i == LOAD_BIG_THUMBNAIL );
            if ( ! vfs_file_info_is_thumbnail_loaded( req->file, load_big ) )
            {
                char* full_path;
                full_path = g_build_filename( loader->dir->path,
                                              vfs_file_info_get_name( req->file ),
                                              NULL );
                vfs_file_info_load_thumbnail( req->file, full_path, load_big );
                g_free( full_path );
                /*  Slow donwn for debugging.
                g_debug( "DELAY!!" );
                g_usleep(G_USEC_PER_SEC/2);
                */

                /* g_debug( "thumbnail loaded: %s", req->file ); */
            }
            need_update = TRUE;
        }

        if( ! vfs_async_task_is_cancelled(task) && need_update )
        {
            vfs_async_task_lock( task );
            g_queue_push_tail( loader->update_queue, vfs_file_info_ref(req->file) );
            if( 0 == loader->idle_handler)
                loader->idle_handler = g_idle_add_full( G_PRIORITY_LOW, (GSourceFunc) on_thumbnail_idle, loader, NULL );
            vfs_async_task_unlock( task );
        }
        /* g_debug( "NEED_UPDATE: %d", need_update ); */
        thumbnail_request_free( req );
    }

    if( vfs_async_task_is_cancelled(task) )
    {
        /* g_debug( "THREAD CANCELLED!!!" ); */
        vfs_async_task_lock( task );
        if( loader->idle_handler)
        {
            g_source_remove( loader->idle_handler );
            loader->idle_handler = 0;
        }
        vfs_async_task_unlock( task );
    }
    else
    {
        if( 0 == loader->idle_handler)
        {
            /* g_debug( "ADD IDLE HANDLER BEFORE THREAD ENDING" ); */
            loader->idle_handler = g_idle_add_full( G_PRIORITY_LOW, (GSourceFunc) on_thumbnail_idle, loader, NULL );
        }
    }
    /* g_debug("THREAD ENDED!");  */
    return NULL;
}
Example #3
0
void vfs_dir_finalize( GObject *obj )
{
    VFSDir * dir = VFS_DIR( obj );
//printf("vfs_dir_finalize  %s\n", dir->path );
    do{}
    while( g_source_remove_by_user_data( dir ) );

    if( G_UNLIKELY( dir->task ) )
    {
        g_signal_handlers_disconnect_by_func( dir->task, on_list_task_finished, dir );
        /* FIXME: should we generate a "file-list" signal to indicate the dir loading was cancelled? */
//printf("spacefm: vfs_dir_finalize -> vfs_async_task_cancel\n");
        vfs_async_task_cancel( dir->task );
        g_object_unref( dir->task );
        dir->task = NULL;
    }
    if ( dir->monitor )
    {
        vfs_file_monitor_remove( dir->monitor,
                                 vfs_dir_monitor_callback,
                                 dir );
    }
    if ( dir->path )
    {
        if( G_LIKELY( dir_hash ) )
        {
            g_hash_table_remove( dir_hash, dir->path );

            /* There is no VFSDir instance */
            if ( 0 == g_hash_table_size( dir_hash ) )
            {
                g_hash_table_destroy( dir_hash );
                dir_hash = NULL;

                vfs_mime_type_remove_reload_cb( mime_cb );
                mime_cb = NULL;

                if( change_notify_timeout )
                {
                    g_source_remove( change_notify_timeout );
                    change_notify_timeout = 0;
                }

                g_signal_handler_disconnect( gtk_icon_theme_get_default(),
                                                                theme_change_notify );
                theme_change_notify = 0;
            }
        }
        g_free( dir->path );
        g_free( dir->disp_path );
        dir->path = dir->disp_path = NULL;
    }
    /* g_debug( "dir->thumbnail_loader: %p", dir->thumbnail_loader ); */
    if( G_UNLIKELY( dir->thumbnail_loader ) )
    {
        /* g_debug( "FREE THUMBNAIL LOADER IN VFSDIR" ); */
        vfs_thumbnail_loader_free( dir->thumbnail_loader );
        dir->thumbnail_loader = NULL;
    }

    if ( dir->file_list )
    {
        g_list_foreach( dir->file_list, ( GFunc ) vfs_file_info_unref, NULL );
        g_list_free( dir->file_list );
        dir->file_list = NULL;
        dir->n_files = 0;
    }

    if( dir->changed_files )
    {
        g_slist_foreach( dir->changed_files, (GFunc)vfs_file_info_unref, NULL );
        g_slist_free( dir->changed_files );
        dir->changed_files = NULL;
    }

    if( dir->created_files )
    {
        g_slist_foreach( dir->created_files, (GFunc)g_free, NULL );
        g_slist_free( dir->created_files );
        dir->created_files = NULL;
    }

    g_mutex_free( dir->mutex );
    G_OBJECT_CLASS( parent_class ) ->finalize( obj );
}
Example #4
0
static void
output_loop (gpointer data)
{
    GstPad *pad;
    GOmxCore *gomx;
    GOmxPort *out_port;
    GstOmxBaseFilter *self;
    GstFlowReturn ret = GST_FLOW_OK;

    pad = data;
    self = GST_OMX_BASE_FILTER (gst_pad_get_parent (pad));
    gomx = self->gomx;

    GST_LOG_OBJECT (self, "begin");

    if (!self->initialized)
    {
        g_error ("not initialized");
        return;
    }

    out_port = self->out_port;

    if (G_LIKELY (out_port->enabled))
    {
        OMX_BUFFERHEADERTYPE *omx_buffer = NULL;

        GST_LOG_OBJECT (self, "request buffer");
        omx_buffer = g_omx_port_request_buffer (out_port);

        GST_LOG_OBJECT (self, "omx_buffer: %p", omx_buffer);

        if (G_UNLIKELY (!omx_buffer))
        {
            GST_WARNING_OBJECT (self, "null buffer: leaving");
            goto leave;
        }

        GST_DEBUG_OBJECT (self, "omx_buffer: size=%lu, len=%lu, flags=%lu, offset=%lu, timestamp=%lld",
                          omx_buffer->nAllocLen, omx_buffer->nFilledLen, omx_buffer->nFlags,
                          omx_buffer->nOffset, omx_buffer->nTimeStamp);

        if (G_LIKELY (omx_buffer->nFilledLen > 0))
        {
            GstBuffer *buf;

#if 1
            /** @todo remove this check */
            if (G_LIKELY (self->in_port->enabled))
            {
                GstCaps *caps = NULL;

                caps = gst_pad_get_negotiated_caps (self->srcpad);

                if (!caps)
                {
                    /** @todo We shouldn't be doing this. */
                    GST_WARNING_OBJECT (self, "faking settings changed notification");
                    if (gomx->settings_changed_cb)
                        gomx->settings_changed_cb (gomx);
                }
                else
                {
                    GST_LOG_OBJECT (self, "caps already fixed: %" GST_PTR_FORMAT, caps);
                    gst_caps_unref (caps);
                }
            }
#endif

            /* buf is always null when the output buffer pointer isn't shared. */
            buf = omx_buffer->pAppPrivate;

            if (buf && !(omx_buffer->nFlags & OMX_BUFFERFLAG_EOS))
            {
                GST_BUFFER_SIZE (buf) = omx_buffer->nFilledLen;
                if (self->use_timestamps)
                {
                    GST_BUFFER_TIMESTAMP (buf) = gst_util_uint64_scale_int (omx_buffer->nTimeStamp,
                                                                            GST_SECOND,
                                                                            OMX_TICKS_PER_SECOND);
                }

                omx_buffer->pAppPrivate = NULL;
                omx_buffer->pBuffer = NULL;

                ret = push_buffer (self, buf);

                gst_buffer_unref (buf);
            }
            else
            {
                /* This is only meant for the first OpenMAX buffers,
                 * which need to be pre-allocated. */
                /* Also for the very last one. */
                gst_pad_alloc_buffer_and_set_caps (self->srcpad,
                                                   GST_BUFFER_OFFSET_NONE,
                                                   omx_buffer->nFilledLen,
                                                   GST_PAD_CAPS (self->srcpad),
                                                   &buf);

                if (G_LIKELY (buf))
                {
                    memcpy (GST_BUFFER_DATA (buf), omx_buffer->pBuffer + omx_buffer->nOffset, omx_buffer->nFilledLen);
                    if (self->use_timestamps)
                    {

                        GST_BUFFER_TIMESTAMP (buf) = gst_util_uint64_scale_int (omx_buffer->nTimeStamp,
                                                                                GST_SECOND,
                                                                                OMX_TICKS_PER_SECOND);
                    }

                    if (self->share_output_buffer)
                    {
                        GST_WARNING_OBJECT (self, "couldn't zero-copy");
                        g_free (omx_buffer->pBuffer);
                        omx_buffer->pBuffer = NULL;
                    }

                    ret = push_buffer (self, buf);
                }
                else
                {
                    GST_WARNING_OBJECT (self, "couldn't allocate buffer of size %d",
                                        omx_buffer->nFilledLen);
                }
            }
        }
        else
        {
            GST_WARNING_OBJECT (self, "empty buffer");
        }

        if (G_UNLIKELY (omx_buffer->nFlags & OMX_BUFFERFLAG_EOS))
        {
            GST_DEBUG_OBJECT (self, "got eos");
            g_omx_core_set_done (gomx);
            goto leave;
        }

        if (self->share_output_buffer &&
            !omx_buffer->pBuffer &&
            omx_buffer->nOffset == 0)
        {
            GstBuffer *buf;
            GstFlowReturn result;

            GST_LOG_OBJECT (self, "allocate buffer");
            result = gst_pad_alloc_buffer_and_set_caps (self->srcpad,
                                                        GST_BUFFER_OFFSET_NONE,
                                                        omx_buffer->nAllocLen,
                                                        GST_PAD_CAPS (self->srcpad),
                                                        &buf);

            if (G_LIKELY (result == GST_FLOW_OK))
            {
                gst_buffer_ref (buf);
                omx_buffer->pAppPrivate = buf;

                omx_buffer->pBuffer = GST_BUFFER_DATA (buf);
                omx_buffer->nAllocLen = GST_BUFFER_SIZE (buf);
            }
            else
            {
                GST_WARNING_OBJECT (self, "could not pad allocate buffer, using malloc");
                omx_buffer->pBuffer = g_malloc (omx_buffer->nAllocLen);
            }
        }

        if (self->share_output_buffer &&
            !omx_buffer->pBuffer)
        {
            GST_ERROR_OBJECT (self, "no input buffer to share");
        }

        omx_buffer->nFilledLen = 0;
        GST_LOG_OBJECT (self, "release_buffer");
        g_omx_port_release_buffer (out_port, omx_buffer);
    }

leave:

    self->last_pad_push_return = ret;

    if (ret != GST_FLOW_OK)
    {
        GST_INFO_OBJECT (self, "pause task, reason:  %s",
                         gst_flow_get_name (ret));
        gst_pad_pause_task (self->srcpad);
    }

    GST_LOG_OBJECT (self, "end");

    gst_object_unref (self);
}
Example #5
0
static gboolean
pad_event (GstPad *pad,
           GstEvent *event)
{
    GstOmxBaseFilter *self;
    GOmxCore *gomx;
    GOmxPort *in_port;
    GOmxPort *out_port;
    gboolean ret;

    self = GST_OMX_BASE_FILTER (GST_OBJECT_PARENT (pad));
    gomx = self->gomx;
    in_port = self->in_port;
    out_port = self->out_port;

    GST_LOG_OBJECT (self, "begin");

    GST_INFO_OBJECT (self, "event: %s", GST_EVENT_TYPE_NAME (event));

    switch (GST_EVENT_TYPE (event))
    {
        case GST_EVENT_EOS:
            if (self->initialized)
            {
                /* send buffer with eos flag */
                /** @todo move to util */
                {
                    OMX_BUFFERHEADERTYPE *omx_buffer;

                    GST_LOG_OBJECT (self, "request buffer");
                    omx_buffer = g_omx_port_request_buffer (in_port);

                    if (G_LIKELY (omx_buffer))
                    {
                        omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS;

                        GST_LOG_OBJECT (self, "release_buffer");
                        /* foo_buffer_untaint (omx_buffer); */
                        g_omx_port_release_buffer (in_port, omx_buffer);
                    }
                    else
                    {
                        g_omx_core_set_done (gomx);
                    }
                }

                /* Wait for the output port to get the EOS. */
                g_omx_core_wait_for_done (gomx);
            }

            ret = gst_pad_push_event (self->srcpad, event);
            break;

        case GST_EVENT_FLUSH_START:
            gst_pad_push_event (self->srcpad, event);
            self->last_pad_push_return = GST_FLOW_WRONG_STATE;

            g_omx_core_flush_start (gomx);

            gst_pad_pause_task (self->srcpad);

            ret = TRUE;
            break;

        case GST_EVENT_FLUSH_STOP:
            gst_pad_push_event (self->srcpad, event);
            self->last_pad_push_return = GST_FLOW_OK;

            g_omx_core_flush_stop (gomx);

            gst_pad_start_task (self->srcpad, output_loop, self->srcpad);

            ret = TRUE;
            break;

        case GST_EVENT_NEWSEGMENT:
            ret = gst_pad_push_event (self->srcpad, event);
            break;

        default:
            ret = gst_pad_push_event (self->srcpad, event);
            break;
    }

    GST_LOG_OBJECT (self, "end");

    return ret;
}
static GstFlowReturn
gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
{
  GstWaylandSink *sink = GST_WAYLAND_SINK (bsink);
  GstBuffer *to_render;
  GstWlBuffer *wlbuffer;
  GstFlowReturn ret = GST_FLOW_OK;

  g_mutex_lock (&sink->render_lock);

  GST_LOG_OBJECT (sink, "render buffer %p", buffer);

  if (G_UNLIKELY (!sink->window)) {
    /* ask for window handle. Unlock render_lock while doing that because
     * set_window_handle & friends will lock it in this context */
    g_mutex_unlock (&sink->render_lock);
    gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY (sink));
    g_mutex_lock (&sink->render_lock);

    if (!sink->window) {
      /* if we were not provided a window, create one ourselves */
      sink->window =
          gst_wl_window_new_toplevel (sink->display, &sink->video_info);
    }
  }

  /* drop buffers until we get a frame callback */
  if (g_atomic_int_get (&sink->redraw_pending) == TRUE)
    goto done;

  /* make sure that the application has called set_render_rectangle() */
  if (G_UNLIKELY (sink->window->render_rectangle.w == 0))
    goto no_window_size;

  wlbuffer = gst_buffer_get_wl_buffer (buffer);

  if (G_LIKELY (wlbuffer && wlbuffer->display == sink->display)) {
    GST_LOG_OBJECT (sink, "buffer %p has a wl_buffer from our display, "
        "writing directly", buffer);
    to_render = buffer;
  } else {
    GstMemory *mem;
    struct wl_buffer *wbuf = NULL;

    GST_LOG_OBJECT (sink, "buffer %p does not have a wl_buffer from our "
        "display, creating it", buffer);

    mem = gst_buffer_peek_memory (buffer, 0);

    if (gst_is_wl_shm_memory (mem)) {
      wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
          &sink->video_info);
    }

    if (wbuf) {
      gst_buffer_add_wl_buffer (buffer, wbuf, sink->display);
      to_render = buffer;
    } else {
      GstMapInfo src;
      /* we don't know how to create a wl_buffer directly from the provided
       * memory, so we have to copy the data to a memory that we know how
       * to handle... */

      GST_LOG_OBJECT (sink, "buffer %p cannot have a wl_buffer, "
          "copying to wl_shm memory", buffer);

      /* sink->pool always exists (created in set_caps), but it may not
       * be active if upstream is not using it */
      if (!gst_buffer_pool_is_active (sink->pool) &&
          !gst_buffer_pool_set_active (sink->pool, TRUE))
        goto activate_failed;

      ret = gst_buffer_pool_acquire_buffer (sink->pool, &to_render, NULL);
      if (ret != GST_FLOW_OK)
        goto no_buffer;

      /* the first time we acquire a buffer,
       * we need to attach a wl_buffer on it */
      wlbuffer = gst_buffer_get_wl_buffer (to_render);
      if (G_UNLIKELY (!wlbuffer)) {
        mem = gst_buffer_peek_memory (to_render, 0);
        wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
            &sink->video_info);
        if (G_UNLIKELY (!wbuf))
          goto no_wl_buffer;

        gst_buffer_add_wl_buffer (to_render, wbuf, sink->display);
      }

      gst_buffer_map (buffer, &src, GST_MAP_READ);
      gst_buffer_fill (to_render, 0, src.data, src.size);
      gst_buffer_unmap (buffer, &src);
    }
  }

  /* drop double rendering */
  if (G_UNLIKELY (to_render == sink->last_buffer)) {
    GST_LOG_OBJECT (sink, "Buffer already being rendered");
    goto done;
  }

  gst_buffer_replace (&sink->last_buffer, to_render);
  render_last_buffer (sink);

  if (buffer != to_render)
    gst_buffer_unref (to_render);
  goto done;

no_window_size:
  {
    GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
        ("Window has no size set"),
        ("Make sure you set the size after calling set_window_handle"));
    ret = GST_FLOW_ERROR;
    goto done;
  }
no_buffer:
  {
    GST_WARNING_OBJECT (sink, "could not create buffer");
    goto done;
  }
no_wl_buffer:
  {
    GST_ERROR_OBJECT (sink, "could not create wl_buffer out of wl_shm memory");
    ret = GST_FLOW_ERROR;
    goto done;
  }
activate_failed:
  {
    GST_ERROR_OBJECT (sink, "failed to activate bufferpool.");
    ret = GST_FLOW_ERROR;
    goto done;
  }
done:
  {
    g_mutex_unlock (&sink->render_lock);
    return ret;
  }
}
Example #7
0
/**
 * gst_adapter_masked_scan_uint32_peek:
 * @adapter: a #GstAdapter
 * @mask: mask to apply to data before matching against @pattern
 * @pattern: pattern to match (after mask is applied)
 * @offset: offset into the adapter data from which to start scanning, returns
 *          the last scanned position.
 * @size: number of bytes to scan from offset
 * @value: pointer to uint32 to return matching data
 *
 * Scan for pattern @pattern with applied mask @mask in the adapter data,
 * starting from offset @offset.  If a match is found, the value that matched
 * is returned through @value, otherwise @value is left untouched.
 *
 * The bytes in @pattern and @mask are interpreted left-to-right, regardless
 * of endianness.  All four bytes of the pattern must be present in the
 * adapter for it to match, even if the first or last bytes are masked out.
 *
 * It is an error to call this function without making sure that there is
 * enough data (offset+size bytes) in the adapter.
 *
 * Returns: offset of the first match, or -1 if no match was found.
 *
 * Since: 0.10.30
 */
guint
gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask,
    guint32 pattern, guint offset, guint size, guint32 * value)
{
  GSList *g;
  guint skip, bsize, i;
  guint32 state;
  guint8 *bdata;
  GstBuffer *buf;

  g_return_val_if_fail (size > 0, -1);
  g_return_val_if_fail (offset + size <= adapter->size, -1);

  /* we can't find the pattern with less than 4 bytes */
  if (G_UNLIKELY (size < 4))
    return -1;

  skip = offset + adapter->skip;

  /* first step, do skipping and position on the first buffer */
  /* optimistically assume scanning continues sequentially */
  if (adapter->priv->scan_entry && (adapter->priv->scan_offset <= skip)) {
    g = adapter->priv->scan_entry;
    skip -= adapter->priv->scan_offset;
  } else {
    g = adapter->buflist;
    adapter->priv->scan_offset = 0;
    adapter->priv->scan_entry = NULL;
  }
  buf = g->data;
  bsize = GST_BUFFER_SIZE (buf);
  while (G_UNLIKELY (skip >= bsize)) {
    skip -= bsize;
    g = g_slist_next (g);
    adapter->priv->scan_offset += bsize;
    adapter->priv->scan_entry = g;
    buf = g->data;
    bsize = GST_BUFFER_SIZE (buf);
  }
  /* get the data now */
  bsize -= skip;
  bdata = GST_BUFFER_DATA (buf) + skip;
  skip = 0;

  /* set the state to something that does not match */
  state = ~pattern;

  /* now find data */
  do {
    bsize = MIN (bsize, size);
    for (i = 0; i < bsize; i++) {
      state = ((state << 8) | bdata[i]);
      if (G_UNLIKELY ((state & mask) == pattern)) {
        /* we have a match but we need to have skipped at
         * least 4 bytes to fill the state. */
        if (G_LIKELY (skip + i >= 3)) {
          if (G_LIKELY (value))
            *value = state;
          return offset + skip + i - 3;
        }
      }
    }
    size -= bsize;
    if (size == 0)
      break;

    /* nothing found yet, go to next buffer */
    skip += bsize;
    g = g_slist_next (g);
    adapter->priv->scan_offset += GST_BUFFER_SIZE (buf);
    adapter->priv->scan_entry = g;
    buf = g->data;
    bsize = GST_BUFFER_SIZE (buf);
    bdata = GST_BUFFER_DATA (buf);
  } while (TRUE);

  /* nothing found */
  return -1;
}
Example #8
0
static void
gst_jpeg_dec_decode_indirect (GstJpegDec * dec, GstVideoFrame * frame, gint r_v,
    gint r_h, gint comp)
{
  guchar *y_rows[16], *u_rows[16], *v_rows[16];
  guchar **scanarray[3] = { y_rows, u_rows, v_rows };
  gint i, j, k;
  gint lines;
  guchar *base[3], *last[3];
  gint stride[3];
  gint width, height;

  GST_DEBUG_OBJECT (dec,
      "unadvantageous width or r_h, taking slow route involving memcpy");

  width = GST_VIDEO_FRAME_WIDTH (frame);
  height = GST_VIDEO_FRAME_HEIGHT (frame);

  if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
    return;

  for (i = 0; i < 3; i++) {
    base[i] = GST_VIDEO_FRAME_COMP_DATA (frame, i);
    stride[i] = GST_VIDEO_FRAME_COMP_STRIDE (frame, i);
    /* make sure we don't make jpeglib write beyond our buffer,
     * which might happen if (height % (r_v*DCTSIZE)) != 0 */
    last[i] = base[i] + (GST_VIDEO_FRAME_COMP_STRIDE (frame, i) *
        (GST_VIDEO_FRAME_COMP_HEIGHT (frame, i) - 1));
  }

  memcpy (y_rows, dec->idr_y, 16 * sizeof (gpointer));
  memcpy (u_rows, dec->idr_u, 16 * sizeof (gpointer));
  memcpy (v_rows, dec->idr_v, 16 * sizeof (gpointer));

  /* fill chroma components for grayscale */
  if (comp == 1) {
    GST_DEBUG_OBJECT (dec, "grayscale, filling chroma");
    for (i = 0; i < 16; i++) {
      memset (u_rows[i], GST_ROUND_UP_32 (width), 0x80);
      memset (v_rows[i], GST_ROUND_UP_32 (width), 0x80);
    }
  }

  for (i = 0; i < height; i += r_v * DCTSIZE) {
    lines = jpeg_read_raw_data (&dec->cinfo, scanarray, r_v * DCTSIZE);
    if (G_LIKELY (lines > 0)) {
      for (j = 0, k = 0; j < (r_v * DCTSIZE); j += r_v, k++) {
        if (G_LIKELY (base[0] <= last[0])) {
          memcpy (base[0], y_rows[j], stride[0]);
          base[0] += stride[0];
        }
        if (r_v == 2) {
          if (G_LIKELY (base[0] <= last[0])) {
            memcpy (base[0], y_rows[j + 1], stride[0]);
            base[0] += stride[0];
          }
        }
        if (G_LIKELY (base[1] <= last[1] && base[2] <= last[2])) {
          if (r_h == 2) {
            memcpy (base[1], u_rows[k], stride[1]);
            memcpy (base[2], v_rows[k], stride[2]);
          } else if (r_h == 1) {
            hresamplecpy1 (base[1], u_rows[k], stride[1]);
            hresamplecpy1 (base[2], v_rows[k], stride[2]);
          } else {
            /* FIXME: implement (at least we avoid crashing by doing nothing) */
          }
        }

        if (r_v == 2 || (k & 1) != 0) {
          base[1] += stride[1];
          base[2] += stride[2];
        }
      }
    } else {
      GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
    }
  }
}
Example #9
0
/*
 * Provide a variant that takes just the vtable for small fixed-size objects.
 * The aligned size is already computed and stored in vt->gc_descr.
 * Note: every SGEN_SCAN_START_SIZE or so we are given the chance to do some special
 * processing. We can keep track of where objects start, for example,
 * so when we scan the thread stacks for pinned objects, we can start
 * a search for the pinned object in SGEN_SCAN_START_SIZE chunks.
 */
static void*
mono_gc_alloc_obj_nolock (MonoVTable *vtable, size_t size)
{
	/* FIXME: handle OOM */
	void **p;
	char *new_next;
	TLAB_ACCESS_INIT;

	HEAVY_STAT (++stat_objects_alloced);
	if (size <= SGEN_MAX_SMALL_OBJ_SIZE)
		HEAVY_STAT (stat_bytes_alloced += size);
	else
		HEAVY_STAT (stat_bytes_alloced_los += size);

	size = ALIGN_UP (size);

	g_assert (vtable->gc_descr);

	if (G_UNLIKELY (has_per_allocation_action)) {
		static int alloc_count;
		int current_alloc = InterlockedIncrement (&alloc_count);

		if (collect_before_allocs) {
			if (((current_alloc % collect_before_allocs) == 0) && nursery_section) {
				sgen_collect_nursery_no_lock (0);
				if (!degraded_mode && sgen_can_alloc_size (size) && size <= SGEN_MAX_SMALL_OBJ_SIZE) {
					// FIXME:
					g_assert_not_reached ();
				}
			}
		} else if (verify_before_allocs) {
			if ((current_alloc % verify_before_allocs) == 0)
				sgen_check_whole_heap_stw ();
		}
	}

	/*
	 * We must already have the lock here instead of after the
	 * fast path because we might be interrupted in the fast path
	 * (after confirming that new_next < TLAB_TEMP_END) by the GC,
	 * and we'll end up allocating an object in a fragment which
	 * no longer belongs to us.
	 *
	 * The managed allocator does not do this, but it's treated
	 * specially by the world-stopping code.
	 */

	if (size > SGEN_MAX_SMALL_OBJ_SIZE) {
		p = sgen_los_alloc_large_inner (vtable, size);
	} else {
		/* tlab_next and tlab_temp_end are TLS vars so accessing them might be expensive */

		p = (void**)TLAB_NEXT;
		/* FIXME: handle overflow */
		new_next = (char*)p + size;
		TLAB_NEXT = new_next;

		if (G_LIKELY (new_next < TLAB_TEMP_END)) {
			/* Fast path */

			/* 
			 * FIXME: We might need a memory barrier here so the change to tlab_next is 
			 * visible before the vtable store.
			 */

			DEBUG (6, fprintf (gc_debug_file, "Allocated object %p, vtable: %p (%s), size: %zd\n", p, vtable, vtable->klass->name, size));
			binary_protocol_alloc (p , vtable, size);
			g_assert (*p == NULL);
			mono_atomic_store_seq (p, vtable);

			return p;
		}

		/* Slow path */

		/* there are two cases: the object is too big or we run out of space in the TLAB */
		/* we also reach here when the thread does its first allocation after a minor 
		 * collection, since the tlab_ variables are initialized to NULL.
		 * there can be another case (from ORP), if we cooperate with the runtime a bit:
		 * objects that need finalizers can have the high bit set in their size
		 * so the above check fails and we can readily add the object to the queue.
		 * This avoids taking again the GC lock when registering, but this is moot when
		 * doing thread-local allocation, so it may not be a good idea.
		 */
		if (TLAB_NEXT >= TLAB_REAL_END) {
			int available_in_tlab;
			/* 
			 * Run out of space in the TLAB. When this happens, some amount of space
			 * remains in the TLAB, but not enough to satisfy the current allocation
			 * request. Currently, we retire the TLAB in all cases, later we could
			 * keep it if the remaining space is above a treshold, and satisfy the
			 * allocation directly from the nursery.
			 */
			TLAB_NEXT -= size;
			/* when running in degraded mode, we continue allocing that way
			 * for a while, to decrease the number of useless nursery collections.
			 */
			if (degraded_mode && degraded_mode < DEFAULT_NURSERY_SIZE) {
				p = alloc_degraded (vtable, size, FALSE);
				binary_protocol_alloc_degraded (p, vtable, size);
				return p;
			}

			available_in_tlab = TLAB_REAL_END - TLAB_NEXT;
			if (size > tlab_size || available_in_tlab > SGEN_MAX_NURSERY_WASTE) {
				/* Allocate directly from the nursery */
				do {
					p = sgen_nursery_alloc (size);
					if (!p) {
						sgen_minor_collect_or_expand_inner (size);
						if (degraded_mode) {
							p = alloc_degraded (vtable, size, FALSE);
							binary_protocol_alloc_degraded (p, vtable, size);
							return p;
						} else {
							p = sgen_nursery_alloc (size);
						}
					}
				} while (!p);
				if (!p) {
					// no space left
					g_assert (0);
				}

				if (nursery_clear_policy == CLEAR_AT_TLAB_CREATION) {
					memset (p, 0, size);
				}
			} else {
				size_t alloc_size = 0;
				if (TLAB_START)
					DEBUG (3, fprintf (gc_debug_file, "Retire TLAB: %p-%p [%ld]\n", TLAB_START, TLAB_REAL_END, (long)(TLAB_REAL_END - TLAB_NEXT - size)));
				sgen_nursery_retire_region (p, available_in_tlab);

				do {
					p = sgen_nursery_alloc_range (tlab_size, size, &alloc_size);
					if (!p) {
						sgen_minor_collect_or_expand_inner (tlab_size);
						if (degraded_mode) {
							p = alloc_degraded (vtable, size, FALSE);
							binary_protocol_alloc_degraded (p, vtable, size);
							return p;
						} else {
							p = sgen_nursery_alloc_range (tlab_size, size, &alloc_size);
						}		
					}
				} while (!p);
					
				if (!p) {
					// no space left
					g_assert (0);
				}

				/* Allocate a new TLAB from the current nursery fragment */
				TLAB_START = (char*)p;
				TLAB_NEXT = TLAB_START;
				TLAB_REAL_END = TLAB_START + alloc_size;
				TLAB_TEMP_END = TLAB_START + MIN (SGEN_SCAN_START_SIZE, alloc_size);

				if (nursery_clear_policy == CLEAR_AT_TLAB_CREATION) {
					memset (TLAB_START, 0, alloc_size);
				}

				/* Allocate from the TLAB */
				p = (void*)TLAB_NEXT;
				TLAB_NEXT += size;
				sgen_set_nursery_scan_start ((char*)p);
			}
		} else {
			/* Reached tlab_temp_end */

			/* record the scan start so we can find pinned objects more easily */
			sgen_set_nursery_scan_start ((char*)p);
			/* we just bump tlab_temp_end as well */
			TLAB_TEMP_END = MIN (TLAB_REAL_END, TLAB_NEXT + SGEN_SCAN_START_SIZE);
			DEBUG (5, fprintf (gc_debug_file, "Expanding local alloc: %p-%p\n", TLAB_NEXT, TLAB_TEMP_END));
		}
	}

	if (G_LIKELY (p)) {
		DEBUG (6, fprintf (gc_debug_file, "Allocated object %p, vtable: %p (%s), size: %zd\n", p, vtable, vtable->klass->name, size));
		binary_protocol_alloc (p, vtable, size);
		mono_atomic_store_seq (p, vtable);
	}

	return p;
}
Example #10
0
static void
marlin_text_renderer_set_widget (MarlinTextRenderer *text_renderer,
                                 GtkWidget          *widget)
{
    PangoFontMetrics *metrics;
    PangoContext *context;
    gint focus_padding;
    gint focus_line_width;
    const PangoFontDescription *font_desc;

    if (G_LIKELY (widget == text_renderer->widget))
        return;

    /* disconnect from the previously set widget */
    if (G_UNLIKELY (text_renderer->widget != NULL))
    {
        g_signal_handlers_disconnect_by_func (G_OBJECT (text_renderer->widget), marlin_text_renderer_invalidate, text_renderer);
        g_object_unref (G_OBJECT (text_renderer->layout));
        g_object_unref (G_OBJECT (text_renderer->widget));
    }

    /* activate the new widget */
    text_renderer->widget = widget;

    /* connect to the new widget */
    if (G_LIKELY (widget != NULL))
    {
        /* take a reference on the widget */
        g_object_ref (G_OBJECT (widget));

        /* we need to recalculate the metrics when a new style (and thereby a new font) is set */
        g_signal_connect_swapped (G_OBJECT (text_renderer->widget), "destroy", G_CALLBACK (marlin_text_renderer_invalidate), text_renderer);
        g_signal_connect_swapped (G_OBJECT (text_renderer->widget), "style-set", G_CALLBACK (marlin_text_renderer_invalidate), text_renderer);

        /* allocate a new pango layout for this widget */
        context = gtk_widget_get_pango_context (widget);
        text_renderer->layout = pango_layout_new (context);

        /* disable automatic text direction, but use the direction specified by Gtk+ */
        pango_layout_set_auto_dir (text_renderer->layout, FALSE);

        /* we don't want to interpret line separators in file names */
        pango_layout_set_single_paragraph_mode (text_renderer->layout, TRUE);

        font_desc = pango_layout_get_font_description (text_renderer->layout);

        /* calculate the average character dimensions */
        metrics = pango_context_get_metrics (context, font_desc, pango_context_get_language (context));

        text_renderer->char_width = PANGO_PIXELS (pango_font_metrics_get_approximate_char_width (metrics));
        text_renderer->char_height = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) + pango_font_metrics_get_descent (metrics));
        pango_font_metrics_unref (metrics);

        /* tell the cell renderer about the fixed height if we're not wrapping text */
        if (G_LIKELY (text_renderer->wrap_width < 0))
            gtk_cell_renderer_set_fixed_size (GTK_CELL_RENDERER (text_renderer), -1, text_renderer->char_height);

        /* determine the focus-padding and focus-line-width style properties from the widget */
        gtk_widget_style_get (widget, "focus-padding", &focus_padding, "focus-line-width", &focus_line_width, NULL);
        text_renderer->focus_width = focus_padding + focus_line_width;
    }
    else
    {
        text_renderer->layout = NULL;
        text_renderer->char_width = 0;
        text_renderer->char_height = 0;
    }
}
/*
 * gst_debug_bin_to_dot_file:
 * @bin: the top-level pipeline that should be analyzed
 * @file_name: output base filename (e.g. "myplayer")
 *
 * To aid debugging applications one can use this method to write out the whole
 * network of gstreamer elements that form the pipeline into an dot file.
 * This file can be processed with graphviz to get an image.
 * <informalexample><programlisting>
 *  dot -Tpng -oimage.png graph_lowlevel.dot
 * </programlisting></informalexample>
 */
void
gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details,
    const gchar * file_name)
{
  gchar *full_file_name = NULL;
  FILE *out;

  g_return_if_fail (GST_IS_BIN (bin));

  if (G_LIKELY (priv_gst_dump_dot_dir == NULL))
    return;

  if (!file_name) {
    file_name = g_get_application_name ();
    if (!file_name)
      file_name = "unnamed";
  }

  full_file_name = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s.dot",
      priv_gst_dump_dot_dir, file_name);

  if ((out = fopen (full_file_name, "wb"))) {
    gchar *state_name = NULL;
    gchar *param_name = NULL;

    if (details & GST_DEBUG_GRAPH_SHOW_STATES) {
      state_name = debug_dump_get_element_state (GST_ELEMENT (bin));
    }
    if (details & GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS) {
      param_name = debug_dump_get_element_params (GST_ELEMENT (bin));
    }

    /* write header */
    fprintf (out,
        "digraph pipeline {\n"
        "  rankdir=LR;\n"
        "  fontname=\"sans\";\n"
        "  fontsize=\"10\";\n"
        "  labelloc=t;\n"
        "  nodesep=.1;\n"
        "  ranksep=.2;\n"
        "  label=\"<%s>\\n%s%s%s\";\n"
        "  node [style=filled, shape=box, fontsize=\"9\", fontname=\"sans\", margin=\"0.0,0.0\"];\n"
        "  edge [labelfontsize=\"6\", fontsize=\"9\", fontname=\"monospace\"];\n"
        "\n", G_OBJECT_TYPE_NAME (bin), GST_OBJECT_NAME (bin),
        (state_name ? state_name : ""), (param_name ? param_name : "")
        );
    if (state_name)
      g_free (state_name);
    if (param_name)
      g_free (param_name);

    debug_dump_element (bin, details, out, 1);

    /* write footer */
    fprintf (out, "}\n");
    fclose (out);
    GST_INFO ("wrote bin graph to : '%s'", full_file_name);
  } else {
    GST_WARNING ("Failed to open file '%s' for writing: %s", full_file_name,
        g_strerror (errno));
  }
  g_free (full_file_name);
}
Example #12
0
static void
marlin_text_renderer_get_size (GtkCellRenderer      *cell,
                               GtkWidget            *widget,
                               const GdkRectangle   *cell_area,
                               gint                 *x_offset,
                               gint                 *y_offset,
                               gint                 *width,
                               gint                 *height)
{
    MarlinTextRenderer *text_renderer = MARLIN_TEXT_RENDERER (cell);
    gint text_length;
    gint text_width;
    gint text_height;
    gint xpad, ypad;

    /* setup the new widget */
    marlin_text_renderer_set_widget (text_renderer, widget);

    gfloat xalign, yalign;
    gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);

    /* we can guess the dimensions if we don't wrap */
    if (text_renderer->wrap_width < 0)
    {
        /* determine the text_length in characters */
        text_length = g_utf8_strlen (text_renderer->text, -1);

        /* the approximation is usually 1-2 chars wrong, so wth */
        text_length += 2;

        /* calculate the appromixate text width/height */
        text_width = text_renderer->char_width * text_length;
        text_height = text_renderer->char_height;
    }
    else
    {
        /* calculate the real text dimension */
        pango_layout_set_ellipsize (text_renderer->layout, PANGO_ELLIPSIZE_END);
        pango_layout_set_height (text_renderer->layout, -3);
        pango_layout_set_width (text_renderer->layout, text_renderer->wrap_width * PANGO_SCALE);
        pango_layout_set_wrap (text_renderer->layout, text_renderer->wrap_mode);
        pango_layout_set_text (text_renderer->layout, text_renderer->text, -1);
        if (xalign == 0.5f)
            pango_layout_set_alignment (text_renderer->layout, PANGO_ALIGN_CENTER);

        pango_layout_get_pixel_size (text_renderer->layout, &text_width, &text_height);
    }

    /* if we have to follow the state manually, we'll need
     * to reserve some space to render the indicator to.
     */
    if (text_renderer->follow_state)
    {
        text_width += 2 * text_renderer->focus_width;
        text_height += 2 * text_renderer->focus_width;
    }

    gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
    /* update width/height */
    if (G_LIKELY (width != NULL))
        *width = text_width + 2 * xpad;
    if (G_LIKELY (height != NULL))
        *height = text_height + 2 * ypad;

    /* update the x/y offsets */
    if (G_LIKELY (cell_area != NULL))
    {
        /*gfloat xalign, yalign;
        gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);*/
        if (G_LIKELY (x_offset != NULL))
        {
            *x_offset = ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ?
                         (1.0 - xalign) : xalign) *
                        (cell_area->width - text_width - (2 * xpad));
            *x_offset = MAX (*x_offset, 0);
        }

        if (G_LIKELY (y_offset != NULL))
        {
            *y_offset = yalign * (cell_area->height - text_height - (2 * ypad));
            *y_offset = MAX (*y_offset, 0);
        }
    }
}
Example #13
0
static void
marlin_text_renderer_set_property (GObject      *object,
                                   guint         prop_id,
                                   const GValue *value,
                                   GParamSpec   *pspec)
{
    MarlinTextRenderer *text_renderer = MARLIN_TEXT_RENDERER (object);
    const gchar        *sval;

    switch (prop_id)
    {
    case PROP_FOLLOW_PRELIT:
        text_renderer->follow_prelit = g_value_get_boolean (value);
        break;

    case PROP_FOLLOW_STATE:
        text_renderer->follow_state = g_value_get_boolean (value);
        break;

    case PROP_TEXT:
        /* release the previous text (if not static) */
        if (!text_renderer->text_static)
            g_free (text_renderer->text);
        sval = g_value_get_string (value);
        text_renderer->text_static = (value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS);
        text_renderer->text = (sval == NULL) ? "" : (gchar *)sval;
        if (!text_renderer->text_static)
            text_renderer->text = g_strdup (text_renderer->text);
        break;

    case PROP_BACKGROUND:
        g_free (text_renderer->background);
        sval = g_value_get_string (value);
        text_renderer->background = g_strdup (sval);
        break;

    case PROP_ZOOM_LEVEL:
        text_renderer->zoom_level = g_value_get_enum (value);
        if (text_renderer->layout != NULL) {
            if (text_renderer->zoom_level < MARLIN_ZOOM_LEVEL_NORMAL)
                pango_layout_set_attributes (text_renderer->layout, eel_pango_attr_list_small ());
            else
                pango_layout_set_attributes (text_renderer->layout, NULL);
        }
        break;

    case PROP_WRAP_MODE:
        text_renderer->wrap_mode = g_value_get_enum (value);
        break;

    case PROP_WRAP_WIDTH:
        /* be sure to reset fixed height if wrapping is requested */
        text_renderer->wrap_width = g_value_get_int (value);
        if (G_LIKELY (text_renderer->wrap_width >= 0))
            gtk_cell_renderer_set_fixed_size (GTK_CELL_RENDERER (text_renderer), -1, -1);
        break;

    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
    }
}
static GstFlowReturn
gst_speex_enc_encode (GstSpeexEnc * enc, GstBuffer * buf)
{
  gint frame_size = enc->frame_size;
  gint bytes = frame_size * 2 * enc->channels, samples;
  gint outsize, written, dtx_ret = 0;
  GstMapInfo map;
  guint8 *data, *data0 = NULL, *bdata;
  gsize bsize, size;
  GstBuffer *outbuf;
  GstFlowReturn ret = GST_FLOW_OK;

  if (G_LIKELY (buf)) {
    gst_buffer_map (buf, &map, GST_MAP_READ);
    bdata = map.data;
    bsize = map.size;

    if (G_UNLIKELY (bsize % bytes)) {
      GST_DEBUG_OBJECT (enc, "draining; adding silence samples");

      size = ((bsize / bytes) + 1) * bytes;
      data0 = data = g_malloc0 (size);
      memcpy (data, bdata, bsize);
      gst_buffer_unmap (buf, &map);
      bdata = NULL;
    } else {
      data = bdata;
      size = bsize;
    }
  } else {
    GST_DEBUG_OBJECT (enc, "nothing to drain");
    goto done;
  }

  samples = size / (2 * enc->channels);
  speex_bits_reset (&enc->bits);

  /* FIXME what about dropped samples if DTS enabled ?? */

  while (size) {
    GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes)", frame_size, bytes);

    if (enc->channels == 2) {
      speex_encode_stereo_int ((gint16 *) data, frame_size, &enc->bits);
    }
    dtx_ret += speex_encode_int (enc->state, (gint16 *) data, &enc->bits);

    data += bytes;
    size -= bytes;
  }

  speex_bits_insert_terminator (&enc->bits);
  outsize = speex_bits_nbytes (&enc->bits);

  if (bdata)
    gst_buffer_unmap (buf, &map);

#if 0
  ret = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc),
      GST_BUFFER_OFFSET_NONE, outsize,
      GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (enc)), &outbuf);

  if ((GST_FLOW_OK != ret))
    goto done;
#endif
  outbuf = gst_buffer_new_allocate (NULL, outsize, NULL);
  gst_buffer_map (outbuf, &map, GST_MAP_WRITE);

  written = speex_bits_write (&enc->bits, (gchar *) map.data, outsize);

  if (G_UNLIKELY (written < outsize)) {
    GST_ERROR_OBJECT (enc, "short write: %d < %d bytes", written, outsize);
  } else if (G_UNLIKELY (written > outsize)) {
    GST_ERROR_OBJECT (enc, "overrun: %d > %d bytes", written, outsize);
    written = outsize;
  }
  gst_buffer_unmap (outbuf, &map);
  gst_buffer_resize (outbuf, 0, written);

  if (!dtx_ret)
    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP);

  ret = gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (enc),
      outbuf, samples);

done:
  g_free (data0);
  return ret;
}
/* For the clock skew we use a windowed low point averaging algorithm as can be
 * found in Fober, Orlarey and Letz, 2005, "Real Time Clock Skew Estimation
 * over Network Delays":
 * http://www.grame.fr/Ressources/pub/TR-050601.pdf
 * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.102.1546
 *
 * The idea is that the jitter is composed of:
 *
 *  J = N + n
 *
 *   N   : a constant network delay.
 *   n   : random added noise. The noise is concentrated around 0
 *
 * In the receiver we can track the elapsed time at the sender with:
 *
 *  send_diff(i) = (Tsi - Ts0);
 *
 *   Tsi : The time at the sender at packet i
 *   Ts0 : The time at the sender at the first packet
 *
 * This is the difference between the RTP timestamp in the first received packet
 * and the current packet.
 *
 * At the receiver we have to deal with the jitter introduced by the network.
 *
 *  recv_diff(i) = (Tri - Tr0)
 *
 *   Tri : The time at the receiver at packet i
 *   Tr0 : The time at the receiver at the first packet
 *
 * Both of these values contain a jitter Ji, a jitter for packet i, so we can
 * write:
 *
 *  recv_diff(i) = (Cri + D + ni) - (Cr0 + D + n0))
 *
 *    Cri    : The time of the clock at the receiver for packet i
 *    D + ni : The jitter when receiving packet i
 *
 * We see that the network delay is irrelevant here as we can elliminate D:
 *
 *  recv_diff(i) = (Cri + ni) - (Cr0 + n0))
 *
 * The drift is now expressed as:
 *
 *  Drift(i) = recv_diff(i) - send_diff(i);
 *
 * We now keep the W latest values of Drift and find the minimum (this is the
 * one with the lowest network jitter and thus the one which is least affected
 * by it). We average this lowest value to smooth out the resulting network skew.
 *
 * Both the window and the weighting used for averaging influence the accuracy
 * of the drift estimation. Finding the correct parameters turns out to be a
 * compromise between accuracy and inertia.
 *
 * We use a 2 second window or up to 512 data points, which is statistically big
 * enough to catch spikes (FIXME, detect spikes).
 * We also use a rather large weighting factor (125) to smoothly adapt. During
 * startup, when filling the window, we use a parabolic weighting factor, the
 * more the window is filled, the faster we move to the detected possible skew.
 *
 * Returns: @time adjusted with the clock skew.
 */
static GstClockTime
calculate_skew (RTPJitterBuffer * jbuf, guint32 rtptime, GstClockTime time)
{
  guint64 ext_rtptime;
  guint64 send_diff, recv_diff;
  gint64 delta;
  gint64 old;
  gint pos, i;
  GstClockTime gstrtptime, out_time;
  guint64 slope;

  ext_rtptime = gst_rtp_buffer_ext_timestamp (&jbuf->ext_rtptime, rtptime);

  if (jbuf->last_rtptime != -1 && ext_rtptime == jbuf->last_rtptime)
    return jbuf->prev_out_time;

  gstrtptime =
      gst_util_uint64_scale_int (ext_rtptime, GST_SECOND, jbuf->clock_rate);

  /* keep track of the last extended rtptime */
  jbuf->last_rtptime = ext_rtptime;

  /* first time, lock on to time and gstrtptime */
  if (G_UNLIKELY (jbuf->base_time == -1)) {
    jbuf->base_time = time;
    jbuf->prev_out_time = -1;
    GST_DEBUG ("Taking new base time %" GST_TIME_FORMAT, GST_TIME_ARGS (time));
  }
  if (G_UNLIKELY (jbuf->base_rtptime == -1)) {
    jbuf->base_rtptime = gstrtptime;
    jbuf->base_extrtp = ext_rtptime;
    jbuf->prev_send_diff = -1;
    GST_DEBUG ("Taking new base rtptime %" GST_TIME_FORMAT,
        GST_TIME_ARGS (gstrtptime));
  }

  if (G_LIKELY (gstrtptime >= jbuf->base_rtptime))
    send_diff = gstrtptime - jbuf->base_rtptime;
  else if (time != -1) {
    /* elapsed time at sender, timestamps can go backwards and thus be smaller
     * than our base time, take a new base time in that case. */
    GST_WARNING ("backward timestamps at server, taking new base time");
    rtp_jitter_buffer_resync (jbuf, time, gstrtptime, ext_rtptime, FALSE);
    send_diff = 0;
  } else {
    GST_WARNING ("backward timestamps at server but no timestamps");
    send_diff = 0;
    /* at least try to get a new timestamp.. */
    jbuf->base_time = -1;
  }

  GST_DEBUG ("extrtp %" G_GUINT64_FORMAT ", gstrtp %" GST_TIME_FORMAT ", base %"
      GST_TIME_FORMAT ", send_diff %" GST_TIME_FORMAT, ext_rtptime,
      GST_TIME_ARGS (gstrtptime), GST_TIME_ARGS (jbuf->base_rtptime),
      GST_TIME_ARGS (send_diff));

  /* we don't have an arrival timestamp so we can't do skew detection. we
   * should still apply a timestamp based on RTP timestamp and base_time */
  if (time == -1 || jbuf->base_time == -1)
    goto no_skew;

  /* elapsed time at receiver, includes the jitter */
  recv_diff = time - jbuf->base_time;

  /* measure the diff */
  delta = ((gint64) recv_diff) - ((gint64) send_diff);

  /* measure the slope, this gives a rought estimate between the sender speed
   * and the receiver speed. This should be approximately 8, higher values
   * indicate a burst (especially when the connection starts) */
  if (recv_diff > 0)
    slope = (send_diff * 8) / recv_diff;
  else
    slope = 8;

  GST_DEBUG ("time %" GST_TIME_FORMAT ", base %" GST_TIME_FORMAT ", recv_diff %"
      GST_TIME_FORMAT ", slope %" G_GUINT64_FORMAT, GST_TIME_ARGS (time),
      GST_TIME_ARGS (jbuf->base_time), GST_TIME_ARGS (recv_diff), slope);

  /* if the difference between the sender timeline and the receiver timeline
   * changed too quickly we have to resync because the server likely restarted
   * its timestamps. */
  if (ABS (delta - jbuf->skew) > GST_SECOND) {
    GST_WARNING ("delta - skew: %" GST_TIME_FORMAT " too big, reset skew",
        GST_TIME_ARGS (ABS (delta - jbuf->skew)));
    rtp_jitter_buffer_resync (jbuf, time, gstrtptime, ext_rtptime, TRUE);
    send_diff = 0;
    delta = 0;
  }

  pos = jbuf->window_pos;

  if (G_UNLIKELY (jbuf->window_filling)) {
    /* we are filling the window */
    GST_DEBUG ("filling %d, delta %" G_GINT64_FORMAT, pos, delta);
    jbuf->window[pos++] = delta;
    /* calc the min delta we observed */
    if (G_UNLIKELY (pos == 1 || delta < jbuf->window_min))
      jbuf->window_min = delta;

    if (G_UNLIKELY (send_diff >= MAX_TIME || pos >= MAX_WINDOW)) {
      jbuf->window_size = pos;

      /* window filled */
      GST_DEBUG ("min %" G_GINT64_FORMAT, jbuf->window_min);

      /* the skew is now the min */
      jbuf->skew = jbuf->window_min;
      jbuf->window_filling = FALSE;
    } else {
      gint perc_time, perc_window, perc;

      /* figure out how much we filled the window, this depends on the amount of
       * time we have or the max number of points we keep. */
      perc_time = send_diff * 100 / MAX_TIME;
      perc_window = pos * 100 / MAX_WINDOW;
      perc = MAX (perc_time, perc_window);

      /* make a parabolic function, the closer we get to the MAX, the more value
       * we give to the scaling factor of the new value */
      perc = perc * perc;

      /* quickly go to the min value when we are filling up, slowly when we are
       * just starting because we're not sure it's a good value yet. */
      jbuf->skew =
          (perc * jbuf->window_min + ((10000 - perc) * jbuf->skew)) / 10000;
      jbuf->window_size = pos + 1;
    }
  } else {
    /* pick old value and store new value. We keep the previous value in order
     * to quickly check if the min of the window changed */
    old = jbuf->window[pos];
    jbuf->window[pos++] = delta;

    if (G_UNLIKELY (delta <= jbuf->window_min)) {
      /* if the new value we inserted is smaller or equal to the current min,
       * it becomes the new min */
      jbuf->window_min = delta;
    } else if (G_UNLIKELY (old == jbuf->window_min)) {
      gint64 min = G_MAXINT64;

      /* if we removed the old min, we have to find a new min */
      for (i = 0; i < jbuf->window_size; i++) {
        /* we found another value equal to the old min, we can stop searching now */
        if (jbuf->window[i] == old) {
          min = old;
          break;
        }
        if (jbuf->window[i] < min)
          min = jbuf->window[i];
      }
      jbuf->window_min = min;
    }
    /* average the min values */
    jbuf->skew = (jbuf->window_min + (124 * jbuf->skew)) / 125;
    GST_DEBUG ("delta %" G_GINT64_FORMAT ", new min: %" G_GINT64_FORMAT,
        delta, jbuf->window_min);
  }
  /* wrap around in the window */
  if (G_UNLIKELY (pos >= jbuf->window_size))
    pos = 0;
  jbuf->window_pos = pos;

no_skew:
  /* the output time is defined as the base timestamp plus the RTP time
   * adjusted for the clock skew .*/
  if (jbuf->base_time != -1) {
    out_time = jbuf->base_time + send_diff;
    /* skew can be negative and we don't want to make invalid timestamps */
    if (jbuf->skew < 0 && out_time < -jbuf->skew) {
      out_time = 0;
    } else {
      out_time += jbuf->skew;
    }
    /* check if timestamps are not going backwards, we can only check this if we
     * have a previous out time and a previous send_diff */
    if (G_LIKELY (jbuf->prev_out_time != -1 && jbuf->prev_send_diff != -1)) {
      /* now check for backwards timestamps */
      if (G_UNLIKELY (
              /* if the server timestamps went up and the out_time backwards */
              (send_diff > jbuf->prev_send_diff
                  && out_time < jbuf->prev_out_time) ||
              /* if the server timestamps went backwards and the out_time forwards */
              (send_diff < jbuf->prev_send_diff
                  && out_time > jbuf->prev_out_time) ||
              /* if the server timestamps did not change */
              send_diff == jbuf->prev_send_diff)) {
        GST_DEBUG ("backwards timestamps, using previous time");
        out_time = jbuf->prev_out_time;
      }
    }
    if (time != -1 && out_time + jbuf->delay < time) {
      /* if we are going to produce a timestamp that is later than the input
       * timestamp, we need to reset the jitterbuffer. Likely the server paused
       * temporarily */
      GST_DEBUG ("out %" GST_TIME_FORMAT " + %" G_GUINT64_FORMAT " < time %"
          GST_TIME_FORMAT ", reset jitterbuffer", GST_TIME_ARGS (out_time),
          jbuf->delay, GST_TIME_ARGS (time));
      rtp_jitter_buffer_resync (jbuf, time, gstrtptime, ext_rtptime, TRUE);
      out_time = time;
      send_diff = 0;
    }
  } else
    out_time = -1;

  jbuf->prev_out_time = out_time;
  jbuf->prev_send_diff = send_diff;

  GST_DEBUG ("skew %" G_GINT64_FORMAT ", out %" GST_TIME_FORMAT,
      jbuf->skew, GST_TIME_ARGS (out_time));

  return out_time;
}
Example #16
0
static void*
mono_gc_try_alloc_obj_nolock (MonoVTable *vtable, size_t size)
{
	void **p;
	char *new_next;
	TLAB_ACCESS_INIT;

	size = ALIGN_UP (size);

	g_assert (vtable->gc_descr);
	if (size > SGEN_MAX_SMALL_OBJ_SIZE)
		return NULL;

	if (G_UNLIKELY (size > tlab_size)) {
		/* Allocate directly from the nursery */
		p = sgen_nursery_alloc (size);
		if (!p)
			return NULL;
		sgen_set_nursery_scan_start ((char*)p);

		/*FIXME we should use weak memory ops here. Should help specially on x86. */
		if (nursery_clear_policy == CLEAR_AT_TLAB_CREATION)
			memset (p, 0, size);
	} else {
		int available_in_tlab;
		char *real_end;
		/* tlab_next and tlab_temp_end are TLS vars so accessing them might be expensive */

		p = (void**)TLAB_NEXT;
		/* FIXME: handle overflow */
		new_next = (char*)p + size;

		real_end = TLAB_REAL_END;
		available_in_tlab = real_end - (char*)p;

		if (G_LIKELY (new_next < real_end)) {
			TLAB_NEXT = new_next;

			/* Second case, we overflowed temp end */
			if (G_UNLIKELY (new_next >= TLAB_TEMP_END)) {
				sgen_set_nursery_scan_start (new_next);
				/* we just bump tlab_temp_end as well */
				TLAB_TEMP_END = MIN (TLAB_REAL_END, TLAB_NEXT + SGEN_SCAN_START_SIZE);
				DEBUG (5, fprintf (gc_debug_file, "Expanding local alloc: %p-%p\n", TLAB_NEXT, TLAB_TEMP_END));		
			}
		} else if (available_in_tlab > SGEN_MAX_NURSERY_WASTE) {
			/* Allocate directly from the nursery */
			p = sgen_nursery_alloc (size);
			if (!p)
				return NULL;

			if (nursery_clear_policy == CLEAR_AT_TLAB_CREATION)
				memset (p, 0, size);			
		} else {
			size_t alloc_size = 0;

			sgen_nursery_retire_region (p, available_in_tlab);
			new_next = sgen_nursery_alloc_range (tlab_size, size, &alloc_size);
			p = (void**)new_next;
			if (!p)
				return NULL;

			TLAB_START = (char*)new_next;
			TLAB_NEXT = new_next + size;
			TLAB_REAL_END = new_next + alloc_size;
			TLAB_TEMP_END = new_next + MIN (SGEN_SCAN_START_SIZE, alloc_size);
			sgen_set_nursery_scan_start ((char*)p);

			if (nursery_clear_policy == CLEAR_AT_TLAB_CREATION)
				memset (new_next, 0, alloc_size);
		}
	}

	HEAVY_STAT (++stat_objects_alloced);
	HEAVY_STAT (stat_bytes_alloced += size);

	DEBUG (6, fprintf (gc_debug_file, "Allocated object %p, vtable: %p (%s), size: %zd\n", p, vtable, vtable->klass->name, size));
	binary_protocol_alloc (p, vtable, size);
	g_assert (*p == NULL); /* FIXME disable this in non debug builds */

	mono_atomic_store_seq (p, vtable);

	return p;
}
/**
 * rtp_jitter_buffer_insert:
 * @jbuf: an #RTPJitterBuffer
 * @item: an #RTPJitterBufferItem to insert
 * @head: TRUE when the head element changed.
 * @percent: the buffering percent after insertion
 *
 * Inserts @item into the packet queue of @jbuf. The sequence number of the
 * packet will be used to sort the packets. This function takes ownerhip of
 * @buf when the function returns %TRUE.
 *
 * When @head is %TRUE, the new packet was added at the head of the queue and
 * will be available with the next call to rtp_jitter_buffer_pop() and
 * rtp_jitter_buffer_peek().
 *
 * Returns: %FALSE if a packet with the same number already existed.
 */
gboolean
rtp_jitter_buffer_insert (RTPJitterBuffer * jbuf, RTPJitterBufferItem * item,
    gboolean * head, gint * percent)
{
  GList *list, *event = NULL;
  guint32 rtptime;
  guint16 seqnum;
  GstClockTime dts;

GST_DEBUG ("INSERT BY SERBAN\n");

  g_return_val_if_fail (jbuf != NULL, FALSE);
  g_return_val_if_fail (item != NULL, FALSE);

  list = jbuf->packets->tail;

  /* no seqnum, simply append then */
  if (item->seqnum == -1)
    goto append;

  seqnum = item->seqnum;

  /* loop the list to skip strictly larger seqnum buffers */
  for (; list; list = g_list_previous (list)) {
    guint16 qseq;
    gint gap;
    RTPJitterBufferItem *qitem = (RTPJitterBufferItem *) list;

    if (qitem->seqnum == -1) {
      /* keep a pointer to the first consecutive event if not already
       * set. we will insert the packet after the event if we can't find
       * a packet with lower sequence number before the event. */
      if (event == NULL)
        event = list;
      continue;
    }

    qseq = qitem->seqnum;

    /* compare the new seqnum to the one in the buffer */
    gap = gst_rtp_buffer_compare_seqnum (seqnum, qseq);

    /* we hit a packet with the same seqnum, notify a duplicate */
    if (G_UNLIKELY (gap == 0))
      goto duplicate;

    /* seqnum > qseq, we can stop looking */
    if (G_LIKELY (gap < 0))
      break;

    /* if we've found a packet with greater sequence number, cleanup the
     * event pointer as the packet will be inserted before the event */
    event = NULL;
  }

  /* if event is set it means that packets before the event had smaller
   * sequence number, so we will insert our packet after the event */
  if (event)
    list = event;

  dts = item->dts;
  if (item->rtptime == -1)
    goto append;

  rtptime = item->rtptime;

  /* rtp time jumps are checked for during skew calculation, but bypassed
   * in other mode, so mind those here and reset jb if needed.
   * Only reset if valid input time, which is likely for UDP input
   * where we expect this might happen due to async thread effects
   * (in seek and state change cycles), but not so much for TCP input */
  if (GST_CLOCK_TIME_IS_VALID (dts) &&
      jbuf->mode != RTP_JITTER_BUFFER_MODE_SLAVE &&
      jbuf->base_time != -1 && jbuf->last_rtptime != -1) {
    GstClockTime ext_rtptime = jbuf->ext_rtptime;

    ext_rtptime = gst_rtp_buffer_ext_timestamp (&ext_rtptime, rtptime);
    if (ext_rtptime > jbuf->last_rtptime + 3 * jbuf->clock_rate ||
        ext_rtptime + 3 * jbuf->clock_rate < jbuf->last_rtptime) {
      /* reset even if we don't have valid incoming time;
       * still better than producing possibly very bogus output timestamp */
      GST_WARNING ("rtp delta too big, reset skew");
      rtp_jitter_buffer_reset_skew (jbuf);
    }
  }

  switch (jbuf->mode) {
    case RTP_JITTER_BUFFER_MODE_NONE:
    case RTP_JITTER_BUFFER_MODE_BUFFER:
      /* send 0 as the first timestamp and -1 for the other ones. This will
       * interpollate them from the RTP timestamps with a 0 origin. In buffering
       * mode we will adjust the outgoing timestamps according to the amount of
       * time we spent buffering. */
      if (jbuf->base_time == -1)
        dts = 0;
      else
        dts = -1;
      break;
    case RTP_JITTER_BUFFER_MODE_SYNCED:
      /* synchronized clocks, take first timestamp as base, use RTP timestamps
       * to interpolate */
      if (jbuf->base_time != -1)
        dts = -1;
      break;
    case RTP_JITTER_BUFFER_MODE_SLAVE:
    default:
      break;
  }
  /* do skew calculation by measuring the difference between rtptime and the
   * receive dts, this function will return the skew corrected rtptime. */
  item->pts = calculate_skew (jbuf, rtptime, dts);

append:
  queue_do_insert (jbuf, list, (GList *) item);

  /* buffering mode, update buffer stats */
  if (jbuf->mode == RTP_JITTER_BUFFER_MODE_BUFFER)
    update_buffer_level (jbuf, percent);
  else if (percent)
    *percent = -1;

  /* head was changed when we did not find a previous packet, we set the return
   * flag when requested. */
  if (G_LIKELY (head))
    *head = (list == NULL);

  return TRUE;

  /* ERRORS */
duplicate:
  {
    GST_WARNING ("duplicate packet %d found", (gint) seqnum);
    return FALSE;
  }
}
Example #18
0
static void
_cogl_path_arc (CoglPath *path,
                float center_x,
	        float center_y,
                float radius_x,
                float radius_y,
                float angle_1,
                float angle_2,
                float angle_step,
                unsigned int move_first)
{
  float a = 0x0;
  float cosa = 0x0;
  float sina = 0x0;
  float px = 0x0;
  float py = 0x0;

  /* Fix invalid angles */

  if (angle_1 == angle_2 || angle_step == 0x0)
    return;

  if (angle_step < 0x0)
    angle_step = -angle_step;

  /* Walk the arc by given step */

  a = angle_1;
  while (a != angle_2)
    {
      cosa = cosf (a * (G_PI/180.0));
      sina = sinf (a * (G_PI/180.0));

      px = center_x + (cosa * radius_x);
      py = center_y + (sina * radius_y);

      if (a == angle_1 && move_first)
	cogl2_path_move_to (path, px, py);
      else
	cogl2_path_line_to (path, px, py);

      if (G_LIKELY (angle_2 > angle_1))
        {
          a += angle_step;
          if (a > angle_2)
            a = angle_2;
        }
      else
        {
          a -= angle_step;
          if (a < angle_2)
            a = angle_2;
        }
    }

  /* Make sure the final point is drawn */

  cosa = cosf (angle_2 * (G_PI/180.0));
  sina = sinf (angle_2 * (G_PI/180.0));

  px = center_x + (cosa * radius_x);
  py = center_y + (sina * radius_y);

  cogl2_path_line_to (path, px, py);
}
Example #19
0
static GstFlowReturn
gst_ac3_parse_handle_frame (GstBaseParse * parse,
    GstBaseParseFrame * frame, gint * skipsize)
{
  GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
  GstBuffer *buf = frame->buffer;
  GstByteReader reader;
  gint off;
  gboolean lost_sync, draining, eac, more = FALSE;
  guint frmsiz, blocks, sid;
  guint rate, chans;
  gboolean update_rate = FALSE;
  gint framesize = 0;
  gint have_blocks = 0;
  GstMapInfo map;
  gboolean ret = FALSE;
  GstFlowReturn res = GST_FLOW_OK;

  gst_buffer_map (buf, &map, GST_MAP_READ);

  if (G_UNLIKELY (map.size < 6)) {
    *skipsize = 1;
    goto cleanup;
  }

  gst_byte_reader_init (&reader, map.data, map.size);
  off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffff0000, 0x0b770000,
      0, map.size);

  GST_LOG_OBJECT (parse, "possible sync at buffer offset %d", off);

  /* didn't find anything that looks like a sync word, skip */
  if (off < 0) {
    *skipsize = map.size - 3;
    goto cleanup;
  }

  /* possible frame header, but not at offset 0? skip bytes before sync */
  if (off > 0) {
    *skipsize = off;
    goto cleanup;
  }

  /* make sure the values in the frame header look sane */
  if (!gst_ac3_parse_frame_header (ac3parse, buf, 0, &frmsiz, &rate, &chans,
          &blocks, &sid, &eac)) {
    *skipsize = off + 2;
    goto cleanup;
  }

  GST_LOG_OBJECT (parse, "size: %u, blocks: %u, rate: %u, chans: %u", frmsiz,
      blocks, rate, chans);

  framesize = frmsiz;

  if (G_UNLIKELY (g_atomic_int_get (&ac3parse->align) ==
          GST_AC3_PARSE_ALIGN_NONE))
    gst_ac3_parse_set_alignment (ac3parse, eac);

  GST_LOG_OBJECT (parse, "got frame");

  lost_sync = GST_BASE_PARSE_LOST_SYNC (parse);
  draining = GST_BASE_PARSE_DRAINING (parse);

  if (g_atomic_int_get (&ac3parse->align) == GST_AC3_PARSE_ALIGN_IEC61937) {
    /* We need 6 audio blocks from each substream, so we keep going forwards
     * till we have it */

    g_assert (blocks > 0);
    GST_LOG_OBJECT (ac3parse, "Need %d frames before pushing", 6 / blocks);

    if (sid != 0) {
      /* We need the first substream to be the one with id 0 */
      GST_LOG_OBJECT (ac3parse, "Skipping till we find sid 0");
      *skipsize = off + 2;
      goto cleanup;
    }

    framesize = 0;

    /* Loop till we have 6 blocks per substream */
    for (have_blocks = 0; !more && have_blocks < 6; have_blocks += blocks) {
      /* Loop till we get one frame from each substream */
      do {
        framesize += frmsiz;

        if (!gst_byte_reader_skip (&reader, frmsiz)
            || map.size < (framesize + 6)) {
          more = TRUE;
          break;
        }

        if (!gst_ac3_parse_frame_header (ac3parse, buf, framesize, &frmsiz,
                NULL, NULL, NULL, &sid, &eac)) {
          *skipsize = off + 2;
          goto cleanup;
        }
      } while (sid);
    }

    /* We're now at the next frame, so no need to skip if resyncing */
    frmsiz = 0;
  }

  if (lost_sync && !draining) {
    guint16 word = 0;

    GST_DEBUG_OBJECT (ac3parse, "resyncing; checking next frame syncword");

    if (more || !gst_byte_reader_skip (&reader, frmsiz) ||
        !gst_byte_reader_get_uint16_be (&reader, &word)) {
      GST_DEBUG_OBJECT (ac3parse, "... but not sufficient data");
      gst_base_parse_set_min_frame_size (parse, framesize + 6);
      *skipsize = 0;
      goto cleanup;
    } else {
      if (word != 0x0b77) {
        GST_DEBUG_OBJECT (ac3parse, "0x%x not OK", word);
        *skipsize = off + 2;
        goto cleanup;
      } else {
        /* ok, got sync now, let's assume constant frame size */
        gst_base_parse_set_min_frame_size (parse, framesize);
      }
    }
  }

  /* expect to have found a frame here */
  g_assert (framesize);
  ret = TRUE;

  /* arrange for metadata setup */
  if (G_UNLIKELY (sid)) {
    /* dependent frame, no need to (ac)count for or consider further */
    GST_LOG_OBJECT (parse, "sid: %d", sid);
    frame->flags |= GST_BASE_PARSE_FRAME_FLAG_NO_FRAME;
    /* TODO maybe also mark as DELTA_UNIT,
     * if that does not surprise baseparse elsewhere */
    /* occupies same time space as previous base frame */
    if (G_LIKELY (GST_BUFFER_TIMESTAMP (buf) >= GST_BUFFER_DURATION (buf)))
      GST_BUFFER_TIMESTAMP (buf) -= GST_BUFFER_DURATION (buf);
    /* only shortcut if we already arranged for caps */
    if (G_LIKELY (ac3parse->sample_rate > 0))
      goto cleanup;
  }

  if (G_UNLIKELY (ac3parse->sample_rate != rate || ac3parse->channels != chans
          || ac3parse->eac != eac)) {
    GstCaps *caps = gst_caps_new_simple (eac ? "audio/x-eac3" : "audio/x-ac3",
        "framed", G_TYPE_BOOLEAN, TRUE, "rate", G_TYPE_INT, rate,
        "channels", G_TYPE_INT, chans, NULL);
    gst_caps_set_simple (caps, "alignment", G_TYPE_STRING,
        g_atomic_int_get (&ac3parse->align) == GST_AC3_PARSE_ALIGN_IEC61937 ?
        "iec61937" : "frame", NULL);
    gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
    gst_caps_unref (caps);

    ac3parse->sample_rate = rate;
    ac3parse->channels = chans;
    ac3parse->eac = eac;

    update_rate = TRUE;
  }

  if (G_UNLIKELY (ac3parse->blocks != blocks)) {
    ac3parse->blocks = blocks;

    update_rate = TRUE;
  }

  if (G_UNLIKELY (update_rate))
    gst_base_parse_set_frame_rate (parse, rate, 256 * blocks, 2, 2);

cleanup:
  gst_buffer_unmap (buf, &map);

  if (ret && framesize <= map.size) {
    res = gst_base_parse_finish_frame (parse, frame, framesize);
  }

  return res;
}
Example #20
0
/**
 * g_vfs_ftp_task_acquire_connection:
 * @task: a task without an associated connection
 *
 * Acquires a new connection for use by this @task. This uses the connection
 * pool of @task's backend, so it reuses previously opened connections and
 * does not reopen new connections unnecessarily. If all connections are busy,
 * it waits %G_VFS_FTP_TIMEOUT_IN_SECONDS seconds for a new connection to
 * become available. Keep in mind that a newly acquired connection might have
 * timed out and therefore closed by the FTP server. You must account for
 * this when sending the first command to the server.
 *
 * Returns: %TRUE if a connection could be acquired, %FALSE if an error
 *          occured
 **/
static gboolean
g_vfs_ftp_task_acquire_connection (GVfsFtpTask *task)
{
  GVfsBackendFtp *ftp;
  gint64 end_time;
  gulong id;

  g_return_val_if_fail (task != NULL, FALSE);
  g_return_val_if_fail (task->conn == NULL, FALSE);

  if (g_vfs_ftp_task_is_in_error (task))
    return FALSE;

  ftp = task->backend;
  g_mutex_lock (&ftp->mutex);
  id = g_cancellable_connect (task->cancellable,
        		      G_CALLBACK (do_broadcast),
        		      &ftp->cond, NULL);
  while (task->conn == NULL && ftp->queue != NULL)
    {
      if (g_cancellable_is_cancelled (task->cancellable))
        {
          task->error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED,
        		                     _("Operation was cancelled"));
          break;
        }

      task->conn = g_queue_pop_head (ftp->queue);
      if (task->conn != NULL)
        break;

      if (ftp->connections < ftp->max_connections)
        {
          static GThread *last_thread = NULL;
          /* Save current number of connections here, so we can limit maximum
           * connections later.
           * This is necessary for threading reasons (connections can be
           * opened or closed while we are still in the opening process. */
          guint maybe_max_connections = ftp->connections;

          ftp->connections++;
          last_thread = g_thread_self ();
          g_mutex_unlock (&ftp->mutex);
          task->conn = g_vfs_ftp_connection_new (ftp->addr, task->cancellable, &task->error);
          if (G_LIKELY (task->conn != NULL))
            {
              g_vfs_ftp_task_receive (task, 0, NULL);
              g_vfs_ftp_task_login (task, ftp->user, ftp->password);
              g_vfs_ftp_task_setup_connection (task);
              if (G_LIKELY (!g_vfs_ftp_task_is_in_error (task)))
                break;
            }

          g_vfs_ftp_connection_free (task->conn);
          task->conn = NULL;
          g_mutex_lock (&ftp->mutex);
          ftp->connections--;
          /* If this value is still equal to our thread it means there were no races 
           * trying to open connections and the maybe_max_connections value is 
           * reliable. */
          if (last_thread == g_thread_self () && 
              !g_vfs_ftp_task_error_matches (task, G_IO_ERROR, G_IO_ERROR_CANCELLED))
            {
              g_print ("maybe: %u, max %u (due to %s)\n", maybe_max_connections, ftp->max_connections, task->error->message);
              ftp->max_connections = MIN (ftp->max_connections, maybe_max_connections);
              if (ftp->max_connections == 0)
                {
                  g_debug ("no more connections left, exiting...\n");
                  /* FIXME: shut down properly */
                  exit (0);
                }
            }

          g_vfs_ftp_task_clear_error (task);
          continue;
        }

      end_time = g_get_monotonic_time () + G_VFS_FTP_TIMEOUT_IN_SECONDS * G_TIME_SPAN_SECOND;
      if (ftp->busy_connections >= ftp->connections ||
          !g_cond_wait_until (&ftp->cond, &ftp->mutex, end_time))
        {
          task->error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_BUSY,
        		                     _("The FTP server is busy. Try again later"));
          break;
        }
    }
  g_cancellable_disconnect (task->cancellable, id);
  g_mutex_unlock (&ftp->mutex);

  return task->conn != NULL;
}
static void
gst_mpegv_parse_update_src_caps (GstMpegvParse * mpvparse)
{
  GstCaps *caps = NULL;

  /* only update if no src caps yet or explicitly triggered */
  if (G_LIKELY (gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (mpvparse)) &&
          !mpvparse->update_caps))
    return;

  /* carry over input caps as much as possible; override with our own stuff */
  caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (mpvparse));
  if (caps) {
    caps = gst_caps_make_writable (caps);
  } else {
    caps = gst_caps_new_empty_simple ("video/mpeg");
  }

  /* typically we don't output buffers until we have properly parsed some
   * config data, so we should at least know about version.
   * If not, it means it has been requested not to drop data, and
   * upstream and/or app must know what they are doing ... */

  if (G_LIKELY (mpvparse->mpeg_version))
    gst_caps_set_simple (caps,
        "mpegversion", G_TYPE_INT, mpvparse->mpeg_version, NULL);

  gst_caps_set_simple (caps, "systemstream", G_TYPE_BOOLEAN, FALSE,
      "parsed", G_TYPE_BOOLEAN, TRUE, NULL);

  if (mpvparse->sequencehdr.width > 0 && mpvparse->sequencehdr.height > 0) {
    gst_caps_set_simple (caps, "width", G_TYPE_INT, mpvparse->sequencehdr.width,
        "height", G_TYPE_INT, mpvparse->sequencehdr.height, NULL);
  }

  /* perhaps we have  a framerate */
  if (mpvparse->fps_num > 0 && mpvparse->fps_den > 0) {
    gint fps_num = mpvparse->fps_num;
    gint fps_den = mpvparse->fps_den;
    GstClockTime latency = gst_util_uint64_scale (GST_SECOND, fps_den, fps_num);

    gst_caps_set_simple (caps, "framerate",
        GST_TYPE_FRACTION, fps_num, fps_den, NULL);
    gst_base_parse_set_frame_rate (GST_BASE_PARSE (mpvparse),
        fps_num, fps_den, 0, 0);
    gst_base_parse_set_latency (GST_BASE_PARSE (mpvparse), latency, latency);
  }

  /* or pixel-aspect-ratio */
  if (mpvparse->sequencehdr.par_w && mpvparse->sequencehdr.par_h > 0) {
    gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
        mpvparse->sequencehdr.par_w, mpvparse->sequencehdr.par_h, NULL);
  }

  if (mpvparse->config != NULL) {
    gst_caps_set_simple (caps, "codec_data",
        GST_TYPE_BUFFER, mpvparse->config, NULL);
  }

  if (mpvparse->mpeg_version == 2) {
    const guint profile_c = mpvparse->sequenceext.profile;
    const guint level_c = mpvparse->sequenceext.level;
    const gchar *profile = NULL, *level = NULL;
    /*
     * Profile indication - 1 => High, 2 => Spatially Scalable,
     *                      3 => SNR Scalable, 4 => Main, 5 => Simple
     * 4:2:2 and Multi-view have profile = 0, with the escape bit set to 1
     */
    const gchar *const profiles[] =
        { "high", "spatial", "snr", "main", "simple" };
    /*
     * Level indication - 4 => High, 6 => High-1440, 8 => Main, 10 => Low,
     *                    except in the case of profile = 0
     */
    const gchar *const levels[] = { "high", "high-1440", "main", "low" };

    if (profile_c > 0 && profile_c < 6)
      profile = profiles[profile_c - 1];

    if ((level_c > 3) && (level_c < 11) && (level_c % 2 == 0))
      level = levels[(level_c >> 1) - 2];

    if (profile_c == 8) {
      /* Non-hierarchical profile */
      switch (level_c) {
        case 2:
          level = levels[0];
        case 5:
          level = levels[2];
          profile = "4:2:2";
          break;
        case 10:
          level = levels[0];
        case 11:
          level = levels[1];
        case 13:
          level = levels[2];
        case 14:
          level = levels[3];
          profile = "multiview";
          break;
        default:
          break;
      }
    }

    /* FIXME does it make sense to expose profile/level in the caps ? */

    GST_DEBUG_OBJECT (mpvparse, "profile:'%s' level:'%s'", profile, level);

    if (profile)
      gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
    else
      GST_DEBUG_OBJECT (mpvparse, "Invalid profile - %u", profile_c);

    if (level)
      gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
    else
      GST_DEBUG_OBJECT (mpvparse, "Invalid level - %u", level_c);

    gst_caps_set_simple (caps, "interlaced",
        G_TYPE_BOOLEAN, !mpvparse->sequenceext.progressive, NULL);
  }

  gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (mpvparse), caps);
  gst_caps_unref (caps);

  mpvparse->update_caps = FALSE;
}
Example #22
0
char* vfs_file_resolve_path( const char* cwd, const char* relative_path )
{
    GString* ret = g_string_sized_new( 4096 );
    int len;
    gboolean strip_tail;

    g_return_val_if_fail( G_LIKELY(relative_path), NULL );

    len = strlen( relative_path );
    strip_tail = (0 == len || relative_path[len-1] != '/');

    if( G_UNLIKELY(*relative_path != '/') ) /* relative path */
    {
        if( G_UNLIKELY(relative_path[0] == '~') ) /* home dir */
        {
            g_string_append( ret, g_get_home_dir());
            ++relative_path;
        }
        else
        {
            if( ! cwd )
            {
                char *cwd_new;
                cwd_new = g_get_current_dir();
                g_string_append( ret, cwd_new );
                g_free( cwd_new );
            }
            else
                g_string_append( ret, cwd );
        }
    }

    if( relative_path[0] != '/'  && (0 == ret->len || ret->str[ ret->len - 1 ] != '/' ) )
        g_string_append_c( ret, '/' );

    while( G_LIKELY( *relative_path ) )
    {
        if( G_UNLIKELY(*relative_path == '.') )
        {
            if( relative_path[1] == '/' || relative_path[1] == '\0' ) /* current dir */
            {
                relative_path += relative_path[1] ? 2 : 1;
                continue;
            }
            if( relative_path[1] == '.' &&
                ( relative_path[2] == '/' || relative_path[2] == '\0') ) /* parent dir */
            {
                gsize len = ret->len - 2;
                while( ret->str[ len ] != '/' )
                    --len;
                g_string_truncate( ret, len + 1 );
                relative_path += relative_path[2] ? 3 : 2;
                continue;
            }
        }

        do
        {
            g_string_append_c( ret, *relative_path );
        }while( G_LIKELY( *(relative_path++) != '/' && *relative_path ) );
    }

    /* if original path contains tailing '/', preserve it; otherwise, remove it. */
    if( strip_tail && G_LIKELY( ret->len > 1 ) && G_UNLIKELY( ret->str[ ret->len - 1 ] == '/' ) )
        g_string_truncate( ret, ret->len - 1 );
    return g_string_free( ret, FALSE );
}
Example #23
0
static GstFlowReturn
pad_chain (GstPad *pad,
           GstBuffer *buf)
{
    GOmxCore *gomx;
    GOmxPort *in_port;
    GstOmxBaseFilter *self;
    GstFlowReturn ret = GST_FLOW_OK;

    self = GST_OMX_BASE_FILTER (GST_OBJECT_PARENT (pad));

    gomx = self->gomx;

    GST_LOG_OBJECT (self, "begin");
    GST_LOG_OBJECT (self, "gst_buffer: size=%lu", GST_BUFFER_SIZE (buf));

    GST_LOG_OBJECT (self, "state: %d", gomx->omx_state);

    if (G_UNLIKELY (gomx->omx_state == OMX_StateLoaded))
    {
        GST_INFO_OBJECT (self, "omx: prepare");

        /** @todo this should probably go after doing preparations. */
        if (self->omx_setup)
        {
            self->omx_setup (self);
        }

        setup_ports (self);

        g_omx_core_prepare (self->gomx);

        self->initialized = TRUE;
        gst_pad_start_task (self->srcpad, output_loop, self->srcpad);
    }

    in_port = self->in_port;

    if (G_LIKELY (in_port->enabled))
    {
        guint buffer_offset = 0;

        if (G_UNLIKELY (gomx->omx_state == OMX_StateIdle))
        {
            GST_INFO_OBJECT (self, "omx: play");
            g_omx_core_start (gomx);

            /* send buffer with codec data flag */
            /** @todo move to util */
            if (self->codec_data)
            {
                OMX_BUFFERHEADERTYPE *omx_buffer;

                GST_LOG_OBJECT (self, "request buffer");
                omx_buffer = g_omx_port_request_buffer (in_port);

                if (G_LIKELY (omx_buffer))
                {
                    omx_buffer->nFlags |= 0x00000080; /* codec data flag */

                    omx_buffer->nFilledLen = GST_BUFFER_SIZE (self->codec_data);
                    memcpy (omx_buffer->pBuffer + omx_buffer->nOffset, GST_BUFFER_DATA (self->codec_data), omx_buffer->nFilledLen);

                    GST_LOG_OBJECT (self, "release_buffer");
                    g_omx_port_release_buffer (in_port, omx_buffer);
                }
            }
        }

        if (G_UNLIKELY (gomx->omx_state != OMX_StateExecuting))
        {
            GST_ERROR_OBJECT (self, "Whoa! very wrong");
        }

        while (G_LIKELY (buffer_offset < GST_BUFFER_SIZE (buf)))
        {
            OMX_BUFFERHEADERTYPE *omx_buffer;

            if (self->last_pad_push_return != GST_FLOW_OK)
            {
                goto out_flushing;
            }

            GST_LOG_OBJECT (self, "request buffer");
            omx_buffer = g_omx_port_request_buffer (in_port);

            GST_LOG_OBJECT (self, "omx_buffer: %p", omx_buffer);

            if (G_LIKELY (omx_buffer))
            {
                GST_DEBUG_OBJECT (self, "omx_buffer: size=%lu, len=%lu, flags=%lu, offset=%lu, timestamp=%lld",
                                  omx_buffer->nAllocLen, omx_buffer->nFilledLen, omx_buffer->nFlags,
                                  omx_buffer->nOffset, omx_buffer->nTimeStamp);

                if (omx_buffer->nOffset == 0 &&
                    self->share_input_buffer)
                {
                    {
                        GstBuffer *old_buf;
                        old_buf = omx_buffer->pAppPrivate;

                        if (old_buf)
                        {
                            gst_buffer_unref (old_buf);
                        }
                        else if (omx_buffer->pBuffer)
                        {
                            g_free (omx_buffer->pBuffer);
                        }
                    }

                    omx_buffer->pBuffer = GST_BUFFER_DATA (buf);
                    omx_buffer->nAllocLen = GST_BUFFER_SIZE (buf);
                    omx_buffer->nFilledLen = GST_BUFFER_SIZE (buf);
                    omx_buffer->pAppPrivate = buf;
                }
                else
                {
                    omx_buffer->nFilledLen = MIN (GST_BUFFER_SIZE (buf) - buffer_offset,
                                                  omx_buffer->nAllocLen - omx_buffer->nOffset);
                    memcpy (omx_buffer->pBuffer + omx_buffer->nOffset, GST_BUFFER_DATA (buf) + buffer_offset, omx_buffer->nFilledLen);
                }

                if (self->use_timestamps)
                {
                    omx_buffer->nTimeStamp = gst_util_uint64_scale_int (GST_BUFFER_TIMESTAMP (buf),
                                                                        OMX_TICKS_PER_SECOND,
                                                                        GST_SECOND);
                }

                buffer_offset += omx_buffer->nFilledLen;

                GST_LOG_OBJECT (self, "release_buffer");
                /** @todo untaint buffer */
                g_omx_port_release_buffer (in_port, omx_buffer);
            }
            else
            {
                GST_WARNING_OBJECT (self, "null buffer");
                goto out_flushing;
            }
        }
    }
    else
    {
        GST_WARNING_OBJECT (self, "done");
        ret = GST_FLOW_UNEXPECTED;
    }

    if (!self->share_input_buffer)
    {
        gst_buffer_unref (buf);
    }

    GST_LOG_OBJECT (self, "end");

    return ret;

    /* special conditions */
out_flushing:
    {
        gst_buffer_unref (buf);
        return self->last_pad_push_return;
    }
}
/* Given a paint volume that has been transformed by an arbitrary
 * modelview and is no longer axis aligned, this derives a replacement
 * that is axis aligned. */
void
_clutter_paint_volume_axis_align (ClutterPaintVolume *pv)
{
  int count;
  int i;
  ClutterVertex origin;
  float max_x;
  float max_y;
  float max_z;

  g_return_if_fail (pv != NULL);

  if (pv->is_empty)
    return;

  if (G_LIKELY (pv->is_axis_aligned))
    return;

  if (G_LIKELY (pv->vertices[0].x == pv->vertices[1].x &&
                pv->vertices[0].y == pv->vertices[3].y &&
                pv->vertices[0].z == pv->vertices[4].z))
    {
      pv->is_axis_aligned = TRUE;
      return;
    }

  if (!pv->is_complete)
    _clutter_paint_volume_complete (pv);

  origin = pv->vertices[0];
  max_x = pv->vertices[0].x;
  max_y = pv->vertices[0].y;
  max_z = pv->vertices[0].z;

  count = pv->is_2d ? 4 : 8;
  for (i = 1; i < count; i++)
    {
      if (pv->vertices[i].x < origin.x)
        origin.x = pv->vertices[i].x;
      else if (pv->vertices[i].x > max_x)
        max_x = pv->vertices[i].x;

      if (pv->vertices[i].y < origin.y)
        origin.y = pv->vertices[i].y;
      else if (pv->vertices[i].y > max_y)
        max_y = pv->vertices[i].y;

      if (pv->vertices[i].z < origin.z)
        origin.z = pv->vertices[i].z;
      else if (pv->vertices[i].z > max_z)
        max_z = pv->vertices[i].z;
    }

  pv->vertices[0] = origin;

  pv->vertices[1].x = max_x;
  pv->vertices[1].y = origin.y;
  pv->vertices[1].z = origin.z;

  pv->vertices[3].x = origin.x;
  pv->vertices[3].y = max_y;
  pv->vertices[3].z = origin.z;

  pv->vertices[4].x = origin.x;
  pv->vertices[4].y = origin.y;
  pv->vertices[4].z = max_z;

  pv->is_complete = FALSE;
  pv->is_axis_aligned = TRUE;

  if (pv->vertices[4].z == pv->vertices[0].z)
    pv->is_2d = TRUE;
  else
    pv->is_2d = FALSE;
}
static void
xfce_accessibility_helper_set_xkb (XfceAccessibilityHelper *helper,
                                   gulong                   mask)
{

    XkbDescPtr xkb;
    gint       delay, interval, time_to_max;
    gint       max_speed, curve;

    gdk_error_trap_push ();

    /* allocate */
    xkb = XkbAllocKeyboard ();
    if (G_LIKELY (xkb))
    {
        /* we always change this, so add it to the mask */
        SET_FLAG (mask, XkbControlsEnabledMask);

        /* if setting sticky keys, we set expiration too */
        if (HAS_FLAG (mask, XkbStickyKeysMask) ||
                HAS_FLAG (mask, XkbSlowKeysMask) ||
                HAS_FLAG (mask, XkbBounceKeysMask) ||
                HAS_FLAG (mask, XkbMouseKeysMask) ||
                HAS_FLAG (mask, XkbAccessXKeysMask))
          SET_FLAG (mask, XkbAccessXTimeoutMask);

        /* add the mouse keys values mask if needed */
        if (HAS_FLAG (mask, XkbMouseKeysMask))
            SET_FLAG (mask, XkbMouseKeysAccelMask);

        /* load the xkb controls into the structure */
        XkbGetControls (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), mask, xkb);

        /* AccessXKeys */
        if (HAS_FLAG (mask, XkbAccessXKeysMask))
        {
            if (xfconf_channel_get_bool (helper->channel, "/AccessXKeys", FALSE))
            {
                SET_FLAG (xkb->ctrls->enabled_ctrls, XkbAccessXKeysMask);
                UNSET_FLAG (xkb->ctrls->axt_ctrls_mask, XkbAccessXKeysMask);
                UNSET_FLAG (xkb->ctrls->axt_ctrls_values, XkbAccessXKeysMask);

                xfsettings_dbg (XFSD_DEBUG_ACCESSIBILITY, "AccessXKeys enabled");
            }
            else
            {
                UNSET_FLAG (xkb->ctrls->enabled_ctrls, XkbAccessXKeysMask);
                SET_FLAG (xkb->ctrls->axt_ctrls_mask, XkbAccessXKeysMask);
                UNSET_FLAG (xkb->ctrls->axt_ctrls_values, XkbAccessXKeysMask);

                xfsettings_dbg (XFSD_DEBUG_ACCESSIBILITY, "AccessXKeys disabled");
            }
        }

        /* Sticky keys */
        if (HAS_FLAG (mask, XkbStickyKeysMask))
        {
            if (xfconf_channel_get_bool (helper->channel, "/StickyKeys", FALSE))
            {
                SET_FLAG (xkb->ctrls->enabled_ctrls, XkbStickyKeysMask);
                UNSET_FLAG (xkb->ctrls->axt_ctrls_mask, XkbStickyKeysMask);
                UNSET_FLAG (xkb->ctrls->axt_ctrls_values, XkbStickyKeysMask);

                if (xfconf_channel_get_bool (helper->channel, "/StickyKeys/LatchToLock", FALSE))
                    SET_FLAG (xkb->ctrls->ax_options, XkbAX_LatchToLockMask);
                else
                    UNSET_FLAG (xkb->ctrls->ax_options, XkbAX_LatchToLockMask);

                if (xfconf_channel_get_bool (helper->channel, "/StickyKeys/TwoKeysDisable", FALSE))
                    SET_FLAG (xkb->ctrls->ax_options, XkbAX_TwoKeysMask);
                else
                    UNSET_FLAG (xkb->ctrls->ax_options, XkbAX_TwoKeysMask);

                xfsettings_dbg (XFSD_DEBUG_ACCESSIBILITY, "stickykeys enabled (ax_options=%d)",
                                xkb->ctrls->ax_options);
            }
            else
            {
                UNSET_FLAG (xkb->ctrls->enabled_ctrls, XkbStickyKeysMask);
                SET_FLAG (xkb->ctrls->axt_ctrls_mask, XkbStickyKeysMask);
                UNSET_FLAG (xkb->ctrls->axt_ctrls_values, XkbStickyKeysMask);

                xfsettings_dbg (XFSD_DEBUG_ACCESSIBILITY, "stickykeys disabled");
            }
        }

        /* Slow keys */
        if (HAS_FLAG (mask, XkbSlowKeysMask))
        {
            if (xfconf_channel_get_bool (helper->channel, "/SlowKeys", FALSE))
            {
                SET_FLAG (xkb->ctrls->enabled_ctrls, XkbSlowKeysMask);
                UNSET_FLAG (xkb->ctrls->axt_ctrls_mask, XkbSlowKeysMask);
                UNSET_FLAG (xkb->ctrls->axt_ctrls_values, XkbSlowKeysMask);

                delay = xfconf_channel_get_int (helper->channel, "/SlowKeys/Delay", 100);
                xkb->ctrls->slow_keys_delay = CLAMP (delay, 1, G_MAXUSHORT);

                xfsettings_dbg (XFSD_DEBUG_ACCESSIBILITY, "slowkeys enabled (delay=%d)",
                                xkb->ctrls->slow_keys_delay);
            }
            else
            {
                UNSET_FLAG (xkb->ctrls->enabled_ctrls, XkbSlowKeysMask);
                SET_FLAG (xkb->ctrls->axt_ctrls_mask, XkbSlowKeysMask);
                UNSET_FLAG (xkb->ctrls->axt_ctrls_values, XkbSlowKeysMask);

                xfsettings_dbg (XFSD_DEBUG_ACCESSIBILITY, "slowkeys disabled");
            }
        }

        /* Bounce keys */
        if (HAS_FLAG (mask, XkbBounceKeysMask))
        {
            if (xfconf_channel_get_bool (helper->channel, "/BounceKeys", FALSE))
            {
                SET_FLAG (xkb->ctrls->enabled_ctrls, XkbBounceKeysMask);
                UNSET_FLAG (xkb->ctrls->axt_ctrls_mask, XkbBounceKeysMask);
                UNSET_FLAG (xkb->ctrls->axt_ctrls_values, XkbBounceKeysMask);

                delay = xfconf_channel_get_int (helper->channel, "/BounceKeys/Delay", 100);
                xkb->ctrls->debounce_delay = CLAMP (delay, 1, G_MAXUSHORT);

                xfsettings_dbg (XFSD_DEBUG_ACCESSIBILITY, "bouncekeys enabled (delay=%d)",
                                xkb->ctrls->debounce_delay);
            }
            else
            {
                UNSET_FLAG (xkb->ctrls->enabled_ctrls, XkbBounceKeysMask);
                SET_FLAG (xkb->ctrls->axt_ctrls_mask, XkbBounceKeysMask);
                UNSET_FLAG (xkb->ctrls->axt_ctrls_values, XkbBounceKeysMask);

                xfsettings_dbg (XFSD_DEBUG_ACCESSIBILITY, "bouncekeys disabled");
            }
        }

        /* Mouse keys */
        if (HAS_FLAG (mask, XkbMouseKeysMask))
        {
            if (xfconf_channel_get_bool (helper->channel, "/MouseKeys", FALSE))
            {
                SET_FLAG (xkb->ctrls->enabled_ctrls, XkbMouseKeysMask);
                UNSET_FLAG (xkb->ctrls->axt_ctrls_mask, XkbMouseKeysMask);
                UNSET_FLAG (xkb->ctrls->axt_ctrls_values, XkbMouseKeysMask);

                /* get values */
                delay = xfconf_channel_get_int (helper->channel, "/MouseKeys/Delay", 160);
                interval = xfconf_channel_get_int (helper->channel, "/MouseKeys/Interval", 20);
                time_to_max = xfconf_channel_get_int (helper->channel, "/MouseKeys/TimeToMax", 3000);
                max_speed = xfconf_channel_get_int (helper->channel, "/MouseKeys/MaxSpeed", 1000);
                curve = xfconf_channel_get_int (helper->channel, "/MouseKeys/Curve", 0);

                /* calculate maximum speed and to to reach it */
                interval = CLAMP (interval, 1, G_MAXUSHORT);
                max_speed = (max_speed * interval) / 1000;
                time_to_max = (time_to_max + interval / 2) / interval;

                /* set new values, clamp to limits */
                xkb->ctrls->mk_delay = CLAMP (delay, 1, G_MAXUSHORT);
                xkb->ctrls->mk_interval = interval;
                xkb->ctrls->mk_time_to_max = CLAMP (time_to_max, 1, G_MAXUSHORT);
                xkb->ctrls->mk_max_speed = CLAMP (max_speed, 1, G_MAXUSHORT);
                xkb->ctrls->mk_curve = CLAMP (curve, -1000, 1000);

                xfsettings_dbg (XFSD_DEBUG_ACCESSIBILITY, "mousekeys enabled (delay=%d, interval=%d, "
                                "time_to_max=%d, max_speed=%d, curve=%d)",
                                xkb->ctrls->mk_delay, xkb->ctrls->mk_interval,
                                xkb->ctrls->mk_time_to_max, xkb->ctrls->mk_max_speed,
                                xkb->ctrls->mk_curve);
            }
            else
            {
                UNSET_FLAG (xkb->ctrls->enabled_ctrls, XkbMouseKeysMask);
                SET_FLAG (xkb->ctrls->axt_ctrls_mask, XkbMouseKeysMask);
                UNSET_FLAG (xkb->ctrls->axt_ctrls_values, XkbMouseKeysMask);
                UNSET_FLAG (mask, XkbMouseKeysAccelMask);

                xfsettings_dbg (XFSD_DEBUG_ACCESSIBILITY, "mousekeys disabled");
            }
        }

        /* set the modified controls */
        if (!XkbSetControls (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), mask, xkb))
            g_message ("Setting the xkb controls failed");

        /* free the structure */
        XkbFreeControls (xkb, mask, True);
        XFree (xkb);
    }
    else
    {
        /* warning */
        g_critical ("XkbAllocKeyboard() returned a null pointer");
    }

    if (gdk_error_trap_pop () != 0)
       g_critical ("Failed to set keyboard controls");
}
Example #26
0
File: table.c Project: gbl/vte
/* Check if a string matches something in the tree. */
const char *
_vte_table_match(struct _vte_table *table,
		 const gunichar *candidate, gssize length,
		 const char **res, const gunichar **consumed,
		 GValueArray **array)
{
	struct _vte_table *head;
	const gunichar *dummy_consumed;
	const char *dummy_res;
	GValueArray *dummy_array;
	const char *ret;
	unsigned char *original, *p;
	gssize original_length;
	int i;
	struct _vte_table_arginfo_head params;
	struct _vte_table_arginfo *arginfo;

	/* Clean up extracted parameters. */
	if (G_UNLIKELY (res == NULL)) {
		res = &dummy_res;
	}
	*res = NULL;
	if (G_UNLIKELY (consumed == NULL)) {
		consumed = &dummy_consumed;
	}
	*consumed = candidate;
	if (G_UNLIKELY (array == NULL)) {
		dummy_array = NULL;
		array = &dummy_array;
	}

	/* Provide a fast path for the usual "not a sequence" cases. */
	if (G_LIKELY (length == 0 || candidate == NULL)) {
		return NULL;
	}

	/* If there's no literal path, and no generic path, and the numeric
	 * path isn't available, then it's not a sequence, either. */
	if (table->table == NULL ||
	    table->table[_vte_table_map_literal(candidate[0])] == NULL) {
		if (table->table_string == NULL) {
			if (table->table_number == NULL ||
					!_vte_table_is_numeric(candidate[0])){
				if (table->table_number_list == NULL ||
					!_vte_table_is_numeric_list(candidate[0])){
					/* No match. */
					return NULL;
				}
			}
		}
	}

	/* Check for a literal match. */
	for (i = 0, head = table; i < length && head != NULL; i++) {
		if (head->table == NULL) {
			head = NULL;
		} else {
			head = head->table[_vte_table_map_literal(candidate[i])];
		}
	}
	if (head != NULL && head->result != NULL) {
		/* Got a literal match. */
		*consumed = candidate + i;
		*res = head->result;
		return *res;
	}

	_vte_table_arginfo_head_init (&params);

	/* Check for a pattern match. */
	ret = _vte_table_matchi(table, candidate, length,
				res, consumed,
				&original, &original_length,
				&params);
	*res = ret;

	/* If we got a match, extract the parameters. */
	if (ret != NULL && ret[0] != '\0' && array != &dummy_array) {
		g_assert(original != NULL);
		p = original;
		arginfo = _vte_table_arginfo_head_reverse (&params);
		do {
			/* All of the interesting arguments begin with '%'. */
			if (p[0] == '%') {
				/* Handle an escaped '%'. */
				if (p[1] == '%') {
					p++;
				}
				/* Handle numeric parameters. */
				else if ((p[1] == 'd') || (p[1] == 'm')) {
					_vte_table_extract_numbers(array,
								   arginfo);
					p++;
				}
				/* Handle string parameters. */
				else if (p[1] == 's') {
					_vte_table_extract_string(array,
								  arginfo);
					p++;
				} else {
					_vte_debug_print (VTE_DEBUG_PARSE,
                                                          "Invalid sequence %s\n",
							  original);
				}
			} /* else Literal. */
			arginfo = arginfo->next;
		} while (++p < original + original_length && arginfo);
	}

	/* Clean up extracted parameters. */
	_vte_table_arginfo_head_finalize (&params);

	return ret;
}
Example #27
0
/* Thanks to the freedesktop.org, things are much more complicated now... */
const char* vfs_get_desktop_dir()
{
    char* def;

    if( G_LIKELY(is_desktop_set) )
        return desktop_dir;

/* glib provides API for this since ver. 2.14, but I think my implementation is better. */
#if GLIB_CHECK_VERSION( 2, 14, 0 ) && 0  /* Delete && 0 to use the one provided by glib */
    desktop_dir = g_get_user_special_dir( G_USER_DIRECTORY_DESKTOP );
#else
    def = g_build_filename( g_get_user_config_dir(), "user-dirs.dirs", NULL );
    if( def )
    {
        int fd = open( def, O_RDONLY );
        g_free( def );
        if( G_LIKELY( fd != -1 ) )
        {
            struct stat s;   // skip stat64
            if( G_LIKELY( fstat( fd, &s ) != -1 ) )
            {
                char* buf = g_malloc( s.st_size + 1 );
                if( (s.st_size = read( fd, buf, s.st_size )) != -1 )
                {
                    char* line;
                    buf[ s.st_size ] = 0;
                    line = strstr( buf, "XDG_DESKTOP_DIR=" );
                    if( G_LIKELY( line ) )
                    {
                        char* eol;
                        line += 16;
                        if( G_LIKELY( ( eol = strchr( line, '\n' ) ) ) )
                            *eol = '\0';
                        line = g_shell_unquote( line, NULL );
                        if( g_str_has_prefix(line, "$HOME") )
                        {
                            desktop_dir = g_build_filename( g_get_home_dir(), line + 5, NULL );
                            g_free( line );
                        }
                        else
                            desktop_dir = line;
                    }
                }
                g_free( buf );
            }
            close( fd );
        }
    }

    if( ! desktop_dir )
        desktop_dir = g_build_filename( g_get_home_dir(), "Desktop", NULL );
#endif

#if 0
    /* FIXME: what should we do if the user has no desktop dir? */
    if( ! g_file_test( desktop_dir, G_FILE_TEST_IS_DIR ) )
    {
        g_free( desktop_dir );
        desktop_dir = NULL;
    }
#endif
    is_desktop_set = TRUE;
    return desktop_dir;
}
static void
cheese_video_format_free (CheeseVideoFormat *format)
{
  if (G_LIKELY (format != NULL))
    g_slice_free (CheeseVideoFormat, format);
}
Example #29
0
gpointer vfs_dir_load_thread(  VFSAsyncTask* task, VFSDir* dir )
{
    const gchar * file_name;
    char* full_path;
    GDir* dir_content;
    VFSFileInfo* file;
    char* hidden = NULL;  //MOD added

    dir->file_listed = 0;
    dir->load_complete = 0;
    dir->xhidden_count = 0;  //MOD
    if ( dir->path )
    {
        /* Install file alteration monitor */
        dir->monitor = vfs_file_monitor_add_dir( dir->path,
                                             vfs_dir_monitor_callback,
                                             dir );

        dir_content = g_dir_open( dir->path, 0, NULL );

        if ( dir_content )
        {
            GKeyFile* kf;

            if( G_UNLIKELY(dir->is_trash) )
                kf = g_key_file_new();

            // MOD  dir contains .hidden file?
            hidden = gethidden( dir->path );

            while ( ! vfs_async_task_is_cancelled( dir->task )
                        && ( file_name = g_dir_read_name( dir_content ) ) )
            {
                full_path = g_build_filename( dir->path, file_name, NULL );
                if ( !full_path )
                    continue;

                //MOD ignore if in .hidden
                if ( hidden && ishidden( hidden, file_name ) )
                {
                    dir->xhidden_count++;
                    continue;
                }
                /* FIXME: Is locking GDK needed here? */
                /* GDK_THREADS_ENTER(); */
                file = vfs_file_info_new();
                if ( G_LIKELY( vfs_file_info_get( file, full_path, file_name ) ) )
                {
                    g_mutex_lock( dir->mutex );

                    /* Special processing for desktop folder */
                    vfs_file_info_load_special_info( file, full_path );

                    /* FIXME: load info, too when new file is added to trash dir */
                    if( G_UNLIKELY( dir->is_trash ) ) /* load info of trashed files */
                    {
                        gboolean info_loaded;
                        char* info = g_strconcat( home_trash_dir, "/info/", file_name, ".trashinfo", NULL );

                        info_loaded = g_key_file_load_from_file( kf, info, 0, NULL );
                        g_free( info );
                        if( info_loaded )
                        {
                            char* ori_path = g_key_file_get_string( kf, "Trash Info", "Path", NULL );
                            if( ori_path )
                            {
                                /* Thanks to the stupid freedesktop.org spec, the filename is encoded
                                 * like a URL, which is insane. This add nothing more than overhead. */
                                char* fake_uri = g_strconcat( "file://", ori_path, NULL );
                                g_free( ori_path );
                                ori_path = g_filename_from_uri( fake_uri, NULL, NULL );
                                /* g_debug( ori_path ); */

                                if( file->disp_name && file->disp_name != file->name )
                                    g_free( file->disp_name );
                                file->disp_name = g_filename_display_basename( ori_path );
                                g_free( ori_path );
                            }
                        }
                    }

                    dir->file_list = g_list_prepend( dir->file_list, file );
                    g_mutex_unlock( dir->mutex );
                    ++dir->n_files;
                }
                else
                {
                    vfs_file_info_unref( file );
                }
                /* GDK_THREADS_LEAVE(); */
                g_free( full_path );
            }
            g_dir_close( dir_content );
            if ( hidden )
                g_free( hidden );

            if( G_UNLIKELY(dir->is_trash) )
                g_key_file_free( kf );
        }
    }
    return NULL;
}
Example #30
0
static void
parse_args (gint    *argc_p,
            gchar ***argv_p)
{
  gchar **argv = *argv_p;
  gchar  *s;
  gint    argc = *argc_p;
  gint    n;
  gint    m;

  for (n = 1; n < argc; ++n)
    {
      if (strcmp (argv[n], "--help") == 0
          || strcmp (argv[n], "-h") == 0)
        {
          print_usage ();
          exit (EXIT_SUCCESS);
        }
      else if (strcmp (argv[n], "--version") == 0
          || strcmp (argv[n], "-V") == 0)
        {
          print_version ();
          exit (EXIT_SUCCESS);
        }
      else if (strcmp (argv[n], "--extern") == 0)
        {
          gen_linkage = "";
          argv[n] = NULL;
        }
      else if (strcmp (argv[n], "--static") == 0)
        {
          gen_linkage = "static ";
          argv[n] = NULL;
        }
      else if (strncmp (argv[n], "--name=", 7) == 0
          || strcmp (argv[n], "--name") == 0)
        {
          s = argv[n] + 6;

          if (G_LIKELY (*s == '='))
            {
              gen_varname = g_strdup (s + 1);
            }
          else if (n + 1 < argc)
            {
              gen_varname = g_strdup (argv[n + 1]);
              argv[n++] = NULL;
            }

          argv[n] = NULL;
        }
      else if (strcmp (argv[n], "--build-list") == 0)
        {
          gen_buildlist = TRUE;
          argv[n] = NULL;
        }
      else if (strcmp (argv[n], "--strip-comments") == 0)
        {
          gen_stripcomments = TRUE;
          argv[n] = NULL;
        }
      else if (strcmp (argv[n], "--strip-content") == 0)
        {
          gen_stripcontent = TRUE;
          argv[n] = NULL;
        }
    }

  for (m = 0, n = 1; n < argc; ++n)
    {
      if (m > 0)
        {
          if (argv[n] != NULL)
            {
              argv[m++] = argv[n];
              argv[n] = NULL;
            }
        }
      else if (argv[n] == NULL)
        {
          m = n;
        }
    }

  if (m > 0)
    *argc_p = m;
}