//-- 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); } }
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; }
//-- 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; }
/***************************************************************************** * 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; }
// 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)); }
// 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; }
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)); }
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; }
/***************************************************************************** * 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 }
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; }
/***************************************************************************** * 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 ); }