Beispiel #1
0
//-- Render -------------------------------------------------------------------
// Called once per frame. Do all rendering here.
//-----------------------------------------------------------------------------
extern "C" void Render()
{
  if ( g_goom )
  {
    goom_set_screenbuffer( g_goom, g_goom_buffer );
    if (!g_texid)
    {
      // initialize the texture we'll be using
      glGenTextures( 1, &g_texid );
      if (!g_texid)
        return;
      goom_update( g_goom, g_audio_data, 0, 0, NULL, (char*)"XBMC" );
      glEnable(GL_TEXTURE_2D);
      glBindTexture( GL_TEXTURE_2D, g_texid );
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
      glTexImage2D( GL_TEXTURE_2D, 0, 4, g_tex_width, g_tex_height, 0,
                    GL_RGBA, GL_UNSIGNED_BYTE, g_goom_buffer );
      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    }
    else
    {
      // update goom frame and copy to our texture
      goom_update( g_goom, g_audio_data, 0, 0, NULL, (char*)"XBMC" );
      glEnable(GL_TEXTURE_2D);
      glBindTexture( GL_TEXTURE_2D, g_texid );
      glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, g_tex_width, g_tex_height,
                       GL_RGBA, GL_UNSIGNED_BYTE, g_goom_buffer );
      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    }

    glDisable(GL_BLEND);
    glBegin( GL_QUADS );
    {
      glColor3f( 1.0, 1.0, 1.0 );
      glTexCoord2f( 0.0, 0.0 );
      glVertex2f( g_window_xpos, g_window_ypos );

      glTexCoord2f( 0.0, 1.0 );
      glVertex2f( g_window_xpos, g_window_ypos + g_window_height );

      glTexCoord2f( 1.0, 1.0 );
      glVertex2f( g_window_xpos + g_window_width, g_window_ypos + g_window_height );

      glTexCoord2f( 1.0, 0.0 );
      glVertex2f( g_window_xpos + g_window_width, g_window_ypos );
    }
    glEnd();
    glDisable( GL_TEXTURE_2D );
    glEnable(GL_BLEND);
  }
}
Beispiel #2
0
static gboolean
gst_goom2k1_render (GstAudioVisualizer * base, GstBuffer * audio,
    GstVideoFrame * video)
{
  GstGoom2k1 *goom = GST_GOOM2K1 (base);
  GstMapInfo amap;
  gint16 datain[2][GOOM2K1_SAMPLES];
  gint16 *adata;
  gint i;

  /* get next GOOM2K1_SAMPLES, we have at least this amount of samples */
  gst_buffer_map (audio, &amap, GST_MAP_READ);
  adata = (gint16 *) amap.data;

  if (goom->channels == 2) {
    for (i = 0; i < GOOM2K1_SAMPLES; i++) {
      datain[0][i] = *adata++;
      datain[1][i] = *adata++;
    }
  } else {
    for (i = 0; i < GOOM2K1_SAMPLES; i++) {
      datain[0][i] = *adata;
      datain[1][i] = *adata++;
    }
  }

  video->data[0] = goom_update (&(goom->goomdata), datain);
  gst_buffer_unmap (audio, &amap);

  return TRUE;
}
Beispiel #3
0
//-- Start --------------------------------------------------------------------
// Called when a new soundtrack is played
//-----------------------------------------------------------------------------
extern "C" void Start(int iChannels, int iSamplesPerSec, int iBitsPerSample, const char* szSongName)
{
  if ( g_goom )
  {
    goom_update( g_goom, g_audio_data, 0, 0, (char*)szSongName, (char*)"XBMC" );
  }
}
static int lv_goom_render (VisPluginData *plugin, VisVideo *video, VisAudio *audio)
{
	GoomPrivate *priv = visual_object_get_private (VISUAL_OBJECT (plugin));
	VisSongInfo *songinfo;
	short pcmdata[2][512];
	float fpcmdata[2][512];
	uint32_t *buf;
	uint8_t *vidbuf = visual_video_get_pixels (video);
	int showinfo = TRUE;
	int i;

	visual_buffer_set_data_pair (priv->pcmbuf1, fpcmdata[0], sizeof (float) * 512);
	visual_audio_get_sample (audio, priv->pcmbuf1, VISUAL_AUDIO_CHANNEL_LEFT);

	visual_buffer_set_data_pair (priv->pcmbuf2, fpcmdata[1], sizeof (float) * 512);
	visual_audio_get_sample (audio, priv->pcmbuf2, VISUAL_AUDIO_CHANNEL_RIGHT);

	for (i = 0; i < 512; i++) {
		pcmdata[0][i] = fpcmdata[0][i] * 32767;
		pcmdata[1][i] = fpcmdata[1][i] * 32767;
	}

	/* Retrieve the songinfo */
	songinfo = VISUAL_ACTOR_PLUGIN (visual_plugin_get_specific (plugin))->songinfo;

	/* FIXME goom should support setting a pointer, so we don't need that final visual_mem_copy */
	if (songinfo != NULL && visual_songinfo_get_age (songinfo) <= 1 && showinfo == TRUE) {
	    VisSongInfoType songinfo_type = visual_songinfo_get_type (songinfo);

		if (songinfo_type == VISUAL_SONGINFO_TYPE_SIMPLE)
		    buf = goom_update (priv->goominfo, pcmdata, 0, 0, visual_songinfo_get_simple_name (songinfo), NULL);
		else if (songinfo_type == VISUAL_SONGINFO_TYPE_ADVANCED)
		    buf = goom_update (priv->goominfo, pcmdata, 0, 0, visual_songinfo_get_song (songinfo), NULL);
		else
			buf = goom_update (priv->goominfo, pcmdata, 0, 0, NULL, NULL);
	}
	else
		buf = goom_update (priv->goominfo, pcmdata, 0, 0, NULL, NULL);

	visual_mem_copy_pitch (vidbuf, buf, video->pitch,
			video->width * video->bpp,
			video->width * video->bpp,
			video->height);

	return 0;
}
Beispiel #5
0
/*****************************************************************************
 * Thread:
 *****************************************************************************/
static void *Thread( void *p_thread_data )
{
    goom_thread_t *p_thread = (goom_thread_t*)p_thread_data;
    date_t i_pts;
    int16_t p_data[2][512];
    int i_data = 0, i_count = 0;
    PluginInfo *p_plugin_info;
    int canc = vlc_savecancel ();

    p_plugin_info = goom_init( p_thread->i_width, p_thread->i_height );

    for( ;; )
    {
        uint32_t  *plane;
        picture_t *p_pic;

        /* FIXME the way the update is done is not really good.
         *  Supurious wake up from p_thread->wait will make it generates a frame
         * without using new samples (probably rare as we should not be waiting
         * samples).
         *  The frame rate at which the video is generated is not well controlled
         * nor the time at which each frame is displayed (not smooth)
         */
        /* goom_update is damn slow, so just copy data and release the lock */
        vlc_mutex_lock( &p_thread->lock );
        if( !p_thread->b_exit &&
            FillBuffer( (int16_t *)p_data, &i_data,
                        &i_pts, &p_thread->date, p_thread ) != VLC_SUCCESS )
            vlc_cond_wait( &p_thread->wait, &p_thread->lock );
        bool b_exit = p_thread->b_exit;
        vlc_mutex_unlock( &p_thread->lock );

        if( b_exit )
            break;

        /* Speed selection */
        if( p_thread->i_speed && (++i_count % (p_thread->i_speed+1)) ) continue;

        /* Frame dropping if necessary */
        if( date_Get( &i_pts ) + GOOM_DELAY <= mdate() ) continue;

        plane = goom_update( p_plugin_info, p_data, 0, 0.0,
                             NULL, NULL );

        p_pic = vout_GetPicture( p_thread->p_vout );
        if( unlikely(p_pic == NULL) )
            continue;

        memcpy( p_pic->p[0].p_pixels, plane, p_thread->i_width * p_thread->i_height * 4 );

        p_pic->date = date_Get( &i_pts ) + GOOM_DELAY;
        vout_PutPicture( p_thread->p_vout, p_pic );
    }

    goom_close( p_plugin_info );
    vlc_restorecancel (canc);
    return NULL;
}
Beispiel #6
0
// our main method for processing images
// should  return a surface no matter what in the future
static PyObject* pygoom_process(PyObject *self, PyObject *args)
{
    if (init == 0) {
        if (data_import_init() == 0) {
            goomInfo = goom_init(width, height);
            init     = 1;
        }
        else {
            data_import_clean();
            return RAISE(PyExc_ValueError, "Error initializing mmap");
        }
    }

    if (mmap_area->count > counter || mmap_area->count < counter) {
        counter = mmap_area->count;

#ifdef USE_FASTMEMCPY
        fast_memcpy(data, mmap_area + sizeof(data_t), 2048);
#else
        memcpy(data, mmap_area + sizeof(data_t), 2048);
#endif
#ifdef VERBOSE
        printf ("goomInfo=%p, data=%p, FXMODE=%d, fps=%.1f, songtitle=%s, message=%s\n", 
            goomInfo, data, FXMODE, fps, songtitle, message);
#endif
        render_data = goom_update(goomInfo, data, FXMODE, fps, songtitle, message);

        if (!render_data) {
            data_import_clean();
            return RAISE(PyExc_ValueError, "Goom didn't give any result!");
        }

        if (!surf) {
            return RAISE(PyExc_ValueError, "Resolution not set");
        }

#ifdef USE_FASTMEMCPY
        fast_memcpy(surf->pixels, render_data, width * height * sizeof(uint32_t));
#else
        memcpy(surf->pixels, render_data, width * height * sizeof(uint32_t));
#endif
    }
    return Py_BuildValue("O", PySurface_New(surf));
}
Beispiel #7
0
// our main method for processing images
// should  return a surface no matter what in the future
static PyObject* pympav_process() {
	if(!sharedfile) {
		RAISE(PyExc_ValueError, "Export file not set");
	}
	
	if (init == 0) {
		if (data_import_init() == 0) {
			goom_init(width, height, cinema);
			goom_setAsmUse(1);
			init = 1;
		}
		else {
			data_import_clean();
			RAISE(PyExc_ValueError, "Error initializing mmap");
		}
	}

	// This probably needs to be cleaned up
	if(mmap_area->count > counter) {
		
		//printf("Missed %i sound updates", mmap_area->count-counter);
		counter = mmap_area->count;
		memcpy( data, ((void *)mmap_area) + sizeof( data_t ), 2048 );
		render_data = goom_update( data, 0, FXMODE, NULL, NULL);

		if(!render_data) {
			data_import_clean();
			RAISE(PyExc_ValueError, "Goom didn't give any result!");
		}
	}
	if(pysurf) {
		memcpy( pysurf->surf->pixels, render_data, width * height * sizeof(uint32_t) );
		return (PySurfaceObject*)pysurf;
	}
	RETURN_NONE;
}
Beispiel #8
0
static PyObject *
PyGoom_process(PyGoomObject *self, PyObject *args)
{
    int i, j;
    gint16 data[2][512];
    char *songtitle, *message;

    if (debug >= 4) {
        printf("*"); fflush(stdout);
    }
	if (!PyArg_ParseTuple(args, ":process")) {
		return NULL;
	}

    if (!self->surface) {
        return RAISE(PyExc_ValueError, "Surface not initialized");
    }

    if (self->mmap_area) {
        if (self->mmap_area->count != self->mmap_area_count) {
            if (debug >= 4) {
                printf("mmap_area->count=%llu, self->mmap_area_count=%llu\n", 
                    self->mmap_area->count, self->mmap_area_count);
            }
            if (debug >= 3) {
                printf("memcpy(data=%p, self->mmap_area=%p + sizeof(data_t)=%u, sizeof(gint16)=%u * 2 * 512)\n",
                    data, self->mmap_area, (unsigned)sizeof(data_t), (unsigned)sizeof(gint16));
            }
            self->mmap_area_count = self->mmap_area->count;
            //memcpy(data, self->mmap_area + sizeof(data_t), sizeof(gint16) * 2 * 512);
            memcpy(data, self->mmap_area + sizeof(data_t), sizeof(gint16) * 1 * 512);
        }
    }
    else {
        // generate some random data if export file is NULL
        for (i = 0; i < 2; i++) {
            for (j = 0; j < 512; j++) {
                data[i][j] = (gint16)rand();
            }
        }
    }

    songtitle = PyString_AsString(self->songtitle);
    if (songtitle && strcmp(songtitle, "") == 0) {
        songtitle = 0;
    } 
    message = PyString_AsString(self->message);
    if (message && strcmp(message, "") == 0) {
        message = 0;
    }
    if (songtitle || message) {
        if (debug >= 1) {
            printf ("songtitle=%s, message=%s\n", songtitle, message);
        }
    }
    
    self->render_data = goom_update(self->goominfo, data, self->fxmode, self->fps, songtitle, message);

    self->songtitle = PyString_FromString("");
    self->message = PyString_FromString("");

    if (!self->render_data) {
        return RAISE(PyExc_ValueError, "Goom didn't give any result!");
    }

    memcpy(self->surface->pixels, self->render_data, self->width * self->height * sizeof(uint32_t));
    // fast memcpy make very little differenc so lets not use it
    //fast_memcpy(self->surface->pixels, self->render_data, self->width * self->height * sizeof(uint32_t));

    return Py_BuildValue("O", PySurface_New(self->surface));
}
Beispiel #9
0
static GstFlowReturn
gst_goom_chain (GstPad * pad, GstBuffer * buffer)
{
  GstGoom *goom;
  GstFlowReturn ret;
  GstBuffer *outbuf = NULL;

  goom = GST_GOOM (gst_pad_get_parent (pad));
  if (goom->bps == 0) {
    ret = GST_FLOW_NOT_NEGOTIATED;
    goto beach;
  }

  /* If we don't have an output format yet, preallocate a buffer to try and
   * set one */
  if (GST_PAD_CAPS (goom->srcpad) == NULL) {
    ret = get_buffer (goom, &outbuf);
    if (ret != GST_FLOW_OK) {
      gst_buffer_unref (buffer);
      goto beach;
    }
  }

  /* don't try to combine samples from discont buffer */
  if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
    gst_adapter_clear (goom->adapter);
  }

  GST_DEBUG_OBJECT (goom,
      "Input buffer has %d samples, time=%" G_GUINT64_FORMAT,
      GST_BUFFER_SIZE (buffer) / goom->bps, GST_BUFFER_TIMESTAMP (buffer));

  /* Collect samples until we have enough for an output frame */
  gst_adapter_push (goom->adapter, buffer);

  ret = GST_FLOW_OK;

  while (TRUE) {
    const guint16 *data;
    gboolean need_skip;
    guchar *out_frame;
    gint i;
    guint avail, to_flush;
    guint64 dist, timestamp;

    avail = gst_adapter_available (goom->adapter);
    GST_DEBUG_OBJECT (goom, "avail now %u", avail);

    /* we need GOOM_SAMPLES to get a meaningful result from goom. */
    if (avail < (GOOM_SAMPLES * goom->bps))
      break;

    /* we also need enough samples to produce one frame at least */
    if (avail < goom->bpf)
      break;

    GST_DEBUG_OBJECT (goom, "processing buffer");

    /* get timestamp of the current adapter byte */
    timestamp = gst_adapter_prev_timestamp (goom->adapter, &dist);
    if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
      /* convert bytes to time */
      dist /= goom->bps;
      timestamp += gst_util_uint64_scale_int (dist, GST_SECOND, goom->rate);
    }

    if (timestamp != -1) {
      gint64 qostime;

      qostime = gst_segment_to_running_time (&goom->segment, GST_FORMAT_TIME,
          timestamp);
      qostime += goom->duration;

      GST_OBJECT_LOCK (goom);
      /* check for QoS, don't compute buffers that are known to be late */
      need_skip = goom->earliest_time != -1 && qostime <= goom->earliest_time;
      GST_OBJECT_UNLOCK (goom);

      if (need_skip) {
        GST_WARNING_OBJECT (goom,
            "QoS: skip ts: %" GST_TIME_FORMAT ", earliest: %" GST_TIME_FORMAT,
            GST_TIME_ARGS (qostime), GST_TIME_ARGS (goom->earliest_time));
        goto skip;
      }
    }

    /* get next GOOM_SAMPLES, we have at least this amount of samples */
    data =
        (const guint16 *) gst_adapter_peek (goom->adapter,
        GOOM_SAMPLES * goom->bps);

    if (goom->channels == 2) {
      for (i = 0; i < GOOM_SAMPLES; i++) {
        goom->datain[0][i] = *data++;
        goom->datain[1][i] = *data++;
      }
    } else {
      for (i = 0; i < GOOM_SAMPLES; i++) {
        goom->datain[0][i] = *data;
        goom->datain[1][i] = *data++;
      }
    }

    /* alloc a buffer if we don't have one yet, this happens
     * when we pushed a buffer in this while loop before */
    if (outbuf == NULL) {
      ret = get_buffer (goom, &outbuf);
      if (ret != GST_FLOW_OK) {
        goto beach;
      }
    }

    GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
    GST_BUFFER_DURATION (outbuf) = goom->duration;
    GST_BUFFER_SIZE (outbuf) = goom->outsize;

    out_frame = (guchar *) goom_update (goom->plugin, goom->datain, 0, 0);
    memcpy (GST_BUFFER_DATA (outbuf), out_frame, goom->outsize);

    GST_DEBUG ("Pushing frame with time=%" GST_TIME_FORMAT ", duration=%"
        GST_TIME_FORMAT, GST_TIME_ARGS (timestamp),
        GST_TIME_ARGS (goom->duration));

    ret = gst_pad_push (goom->srcpad, outbuf);
    outbuf = NULL;

  skip:
    /* Now flush the samples we needed for this frame, which might be more than
     * the samples we used (GOOM_SAMPLES). */
    to_flush = goom->bpf;

    GST_DEBUG_OBJECT (goom, "finished frame, flushing %u bytes from input",
        to_flush);
    gst_adapter_flush (goom->adapter, to_flush);

    if (ret != GST_FLOW_OK)
      break;
  }

  if (outbuf != NULL)
    gst_buffer_unref (outbuf);

beach:
  gst_object_unref (goom);

  return ret;
}
Beispiel #10
0
/*****************************************************************************
 * Thread:
 *****************************************************************************/
static void* Thread( vlc_object_t *p_this )
{
    goom_thread_t *p_thread = (goom_thread_t*)p_this;
    int width, height, speed;
    date_t i_pts;
    int16_t p_data[2][512];
    int i_data = 0, i_count = 0;
    PluginInfo *p_plugin_info;
    int canc = vlc_savecancel ();

    width = var_GetInteger( p_this, "goom-width" );
    height = var_GetInteger( p_this, "goom-height" );

    speed = var_CreateGetInteger( p_thread, "goom-speed" );
    speed = MAX_SPEED - speed;
    if( speed < 0 ) speed = 0;

    p_plugin_info = goom_init( width, height );

    while( vlc_object_alive (p_thread) )
    {
        uint32_t  *plane;
        picture_t *p_pic;

        /* goom_update is damn slow, so just copy data and release the lock */
        vlc_mutex_lock( &p_thread->lock );
        if( FillBuffer( (int16_t *)p_data, &i_data, &i_pts,
                        &p_thread->date, p_thread ) != VLC_SUCCESS )
            vlc_cond_wait( &p_thread->wait, &p_thread->lock );
        vlc_mutex_unlock( &p_thread->lock );

        /* Speed selection */
        if( speed && (++i_count % (speed+1)) ) continue;

        /* Frame dropping if necessary */
        if( date_Get( &i_pts ) + GOOM_DELAY <= mdate() ) continue;

        plane = goom_update( p_plugin_info, p_data, 0, 0.0,
                             p_thread->psz_title, NULL );

        free( p_thread->psz_title );
        p_thread->psz_title = NULL;

        while( !( p_pic = vout_GetPicture( p_thread->p_vout ) ) &&
               vlc_object_alive (p_thread) )
        {
            msleep( VOUT_OUTMEM_SLEEP );
        }

        if( p_pic == NULL ) break;

        memcpy( p_pic->p[0].p_pixels, plane, width * height * 4 );

        p_pic->date = date_Get( &i_pts ) + GOOM_DELAY;
        vout_PutPicture( p_thread->p_vout, p_pic );
    }

    goom_close( p_plugin_info );
    vlc_restorecancel (canc);
    return NULL;
}
void VideoVisualGoom::Draw(const QRect &area, MythPainter */*painter*/,
                           QPaintDevice */*device*/)
{
    if (m_disabled || !m_render || area.isEmpty())
        return;

    QMutexLocker lock(mutex());
    unsigned int* last = m_buffer;
    VisualNode *node = GetNode();
    if (node)
    {
        int numSamps = 512;
        if (node->length < 512)
            numSamps = node->length;

        signed short int data[2][512];
        int i= 0;
        for (; i < numSamps; i++)
        {
            data[0][i] = node->left[i];
            data[1][i] = node->right ? node->right[i] : data[0][i];
        }

        for (; i < 512; i++)
        {
            data[0][i] = 0;
            data[1][i] = 0;
        }

        m_buffer = goom_update(data, 0);
    }

#ifdef USING_OPENGL
    if ((m_render->Type() == kRenderOpenGL1) ||
        (m_render->Type() == kRenderOpenGL2) ||
        (m_render->Type() == kRenderOpenGL2ES))
    {
        MythRenderOpenGL *glrender =
                    static_cast<MythRenderOpenGL*>(m_render);
        if (!m_surface && glrender && m_buffer)
        {
            m_surface = glrender->CreateTexture(m_area.size(),
                                  glrender->GetFeatures() & kGLExtPBufObj, 0,
                                  GL_UNSIGNED_BYTE, GL_RGBA, GL_RGBA8,
                                  GL_LINEAR_MIPMAP_LINEAR);
        }

        if (m_surface && glrender && m_buffer)
        {
            if (m_buffer != last)
            {
                bool copy = glrender->GetFeatures() & kGLExtPBufObj;
                void* buf = glrender->GetTextureBuffer(m_surface, copy);
                if (copy)
                    memcpy(buf, m_buffer, m_area.width() * m_area.height() * 4);
                glrender->UpdateTexture(m_surface, (void*)m_buffer);
            }
            QRectF src(m_area);
            QRectF dst(area);
            glrender->DrawBitmap(&m_surface, 1, 0, &src, &dst, 0);
        }
        return;
    }
#endif

#ifdef USING_VDPAU
    if (m_render->Type() == kRenderVDPAU)
    {
        MythRenderVDPAU *render =
                    static_cast<MythRenderVDPAU*>(m_render);

        if (!m_surface && render)
            m_surface = render->CreateBitmapSurface(m_area.size());

        if (m_surface && render && m_buffer)
        {
            if (m_buffer != last)
            {
                void    *plane[1] = { m_buffer };
                uint32_t pitch[1] = { static_cast<uint32_t>(m_area.width() * 4) };
                render->UploadBitmap(m_surface, plane, pitch);
            }
            render->DrawBitmap(m_surface, 0, nullptr, nullptr, kVDPBlendNull, 255, 255, 255, 255);
        }
        return;
    }
#endif
}
Beispiel #12
0
static GstFlowReturn
gst_goom_chain (GstPad * pad, GstBuffer * buffer)
{
  GstGoom *goom;
  GstFlowReturn ret;
  GstBuffer *outbuf = NULL;

  goom = GST_GOOM (gst_pad_get_parent (pad));
    
  /* If we don't have an output format yet, preallocate a buffer to try and
   * set one */
  if (GST_PAD_CAPS (goom->srcpad) == NULL) {
    ret = get_buffer (goom, &outbuf);
    if (ret != GST_FLOW_OK) {
      gst_buffer_unref (buffer);
      goto beach;
    }
  }
  
  /* don't try to combine samples from discont buffer */
  if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
    gst_adapter_clear (goom->adapter);
    goom->next_ts = -1;
  }

  /* Match timestamps from the incoming audio */
  if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE)
    goom->next_ts = GST_BUFFER_TIMESTAMP (buffer);

  GST_DEBUG_OBJECT (goom,
      "Input buffer has %d samples, time=%" G_GUINT64_FORMAT,
      GST_BUFFER_SIZE (buffer) / goom->bps, GST_BUFFER_TIMESTAMP (buffer));

  /* Collect samples until we have enough for an output frame */
  gst_adapter_push (goom->adapter, buffer);

  ret = GST_FLOW_OK;

  while (TRUE) {
    const guint16 *data;
    gboolean need_skip;
    guchar *out_frame;
    gint i, c;
    guint avail, to_flush;
	
	Message m;

    avail = gst_adapter_available (goom->adapter);
    GST_DEBUG_OBJECT (goom, "avail now %u", avail);

    /* we need GOOM_SAMPLES to get a meaningful result from goom. */
    if (avail < (GOOM_SAMPLES * goom->bps))
      break;

    /* we also need enough samples to produce one frame at least */
    if (avail < goom->bpf)
      break;

    GST_DEBUG_OBJECT (goom, "processing buffer");

    if (goom->next_ts != -1) {
      gint64 qostime;

      qostime = gst_segment_to_running_time (&goom->segment, GST_FORMAT_TIME,
          goom->next_ts);

      GST_OBJECT_LOCK (goom);
      /* check for QoS, don't compute buffers that are known to be late */
      need_skip = goom->earliest_time != -1 && qostime <= goom->earliest_time;
      GST_OBJECT_UNLOCK (goom);

      if (need_skip) {
        GST_WARNING_OBJECT (goom,
            "QoS: skip ts: %" GST_TIME_FORMAT ", earliest: %" GST_TIME_FORMAT,
            GST_TIME_ARGS (qostime), GST_TIME_ARGS (goom->earliest_time));
        goto skip;
      }
    }

    /* get next GOOM_SAMPLES, we have at least this amount of samples */
    data =
        (const guint16 *) gst_adapter_peek (goom->adapter,
        GOOM_SAMPLES * goom->bps);

    if (goom->channels == 2) {
      for (i = 0; i < GOOM_SAMPLES; i++) {
        goom->datain[0][i] = *data++;
        goom->datain[1][i] = *data++;
      }
    } else {
      for (i = 0; i < GOOM_SAMPLES; i++) {
        goom->datain[0][i] = *data;
        goom->datain[1][i] = *data++;
      }
    }

    /* alloc a buffer if we don't have one yet, this happens
     * when we pushed a buffer in this while loop before */
    if (outbuf == NULL) {
      ret = get_buffer (goom, &outbuf);
      if (ret != GST_FLOW_OK) {
        goto beach;
      }
    }

    GST_BUFFER_TIMESTAMP (outbuf) = goom->next_ts;
    GST_BUFFER_DURATION (outbuf) = goom->duration;
    GST_BUFFER_SIZE (outbuf) = goom->outsize;

	//gst_spectrum_transform_ip(gstSpectrum,buffer);

	//print_spectrum_message(gstSpectrum);
	//readMessage(&m);

	//c = m.magnitude[0] + m.magnitude[1] + m.magnitude[2] + m.magnitude[3] + m.magnitude[4];
	//if (c != 0) {
		/*printf("\n\n [");
		for (i = 0; i < 5; i++)
			printf("%f $ ", m.magnitude[i]);
		printf("] \n\n");*/
		
		/*g_print ("Goom: %" GST_TIME_FORMAT ", message received: %" GST_TIME_FORMAT "\n",
			GST_TIME_ARGS (goom->next_ts), GST_TIME_ARGS (m.timestamp));*/
	//}

    out_frame = (guchar *) goom_update (goom->plugin, goom->datain, 0, 0);
    memcpy (GST_BUFFER_DATA (outbuf), out_frame, goom->outsize);

    GST_DEBUG ("Pushing frame with time=%" GST_TIME_FORMAT ", duration=%"
        GST_TIME_FORMAT, GST_TIME_ARGS (goom->next_ts),
        GST_TIME_ARGS (goom->duration));

    ret = gst_pad_push (goom->srcpad, outbuf);
    outbuf = NULL;

  skip:
    /* interpollate next timestamp */
    if (goom->next_ts != -1)
      goom->next_ts += goom->duration;

    /* Now flush the samples we needed for this frame, which might be more than
     * the samples we used (GOOM_SAMPLES). */
    to_flush = goom->bpf;

    GST_DEBUG_OBJECT (goom, "finished frame, flushing %u bytes from input",
        to_flush);
    gst_adapter_flush (goom->adapter, to_flush);

    if (ret != GST_FLOW_OK)
      break;
  }

  if (outbuf != NULL)
    gst_buffer_unref (outbuf);

beach:
  gst_object_unref (goom);

  return ret;
}
Beispiel #13
0
/*****************************************************************************
 * Thread:
 *****************************************************************************/
static void Thread( vlc_object_t *p_this )
{
    goom_thread_t *p_thread = (goom_thread_t*)p_this;
    vlc_value_t width, height, speed;
    audio_date_t i_pts;
    int16_t p_data[2][512];
    int i_data = 0, i_count = 0;
    PluginInfo *p_plugin_info;

    var_Get( p_this, "goom-width", &width );
    var_Get( p_this, "goom-height", &height );

    var_Create( p_thread, "goom-speed", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
    var_Get( p_thread, "goom-speed", &speed );
    speed.i_int = MAX_SPEED - speed.i_int;
    if( speed.i_int < 0 ) speed.i_int = 0;

    p_plugin_info = goom_init( width.i_int, height.i_int );

    while( !p_thread->b_die )
    {
        uint32_t  *plane;
        picture_t *p_pic;

        /* goom_update is damn slow, so just copy data and release the lock */
        vlc_mutex_lock( &p_thread->lock );
        if( FillBuffer( (int16_t *)p_data, &i_data, &i_pts,
                        &p_thread->date, p_thread ) != VLC_SUCCESS )
            vlc_cond_wait( &p_thread->wait, &p_thread->lock );
        vlc_mutex_unlock( &p_thread->lock );

        /* Speed selection */
        if( speed.i_int && (++i_count % (speed.i_int+1)) ) continue;

        /* Frame dropping if necessary */
        if( aout_DateGet( &i_pts ) + GOOM_DELAY <= mdate() ) continue;

        plane = goom_update( p_plugin_info, p_data, 0, 0.0,
                             p_thread->psz_title, NULL );

        if( p_thread->psz_title )
        {
            free( p_thread->psz_title );
            p_thread->psz_title = NULL;
        }

        while( !( p_pic = vout_CreatePicture( p_thread->p_vout, 0, 0, 0 ) ) &&
               !p_thread->b_die )
        {
            msleep( VOUT_OUTMEM_SLEEP );
        }

        if( p_pic == NULL ) break;

        memcpy( p_pic->p[0].p_pixels, plane, width.i_int * height.i_int * 4 );
        vout_DatePicture( p_thread->p_vout, p_pic,
                          aout_DateGet( &i_pts ) + GOOM_DELAY );
        vout_DisplayPicture( p_thread->p_vout, p_pic );
    }

    goom_close( p_plugin_info );
}