mirror of
https://github.com/dyne/FreeJ.git
synced 2026-06-16 12:59:33 +02:00
fixes to the audio collector and video encoder,
new add_audio method for video encoder, more updates and cleanups
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
Freej 0.9.x Experimental
|
||||
* new AudioJack() collector for realtime sound parametrization
|
||||
* new MouseController()
|
||||
* new ViMoContoller() for serial Video Mouse device
|
||||
* tons of bugfixes
|
||||
* JS garbage collection framework, rem_controller() and rem_layer()
|
||||
* new fps syncing per layer
|
||||
* Layer.start() .stop()
|
||||
* experimental ViewportLayer() using Xv extension
|
||||
AudioJack() collector for realtime sound parametrization
|
||||
WiiController() for bluetooth WiiMote device
|
||||
MouseController() for mouse pointer
|
||||
ViMoContoller() for serial Video Mouse device
|
||||
tons of bugfixes
|
||||
JS garbage collection framework, rem_controller() and rem_layer()
|
||||
new fps sync architecture to let layers go
|
||||
Layer.start() .stop()
|
||||
OpenGL viewport fixes
|
||||
experimental ViewportLayer() using Xv extension
|
||||
|
||||
FreeJ 0.9.1 BeTV - 26 Nov 2007
|
||||
New video encoder (ffmpeg2theora)
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
<div class="desc">
|
||||
This object collects audio from a <a
|
||||
href="http://www.jackaudio.org">Jack</a> source, it can be used to
|
||||
change parameter values based on the audio input.
|
||||
</div>
|
||||
change parameter values based on the audio input. </div>
|
||||
|
||||
<div class="desc">
|
||||
16 harmonics are provided using a fast fourier transform, returning
|
||||
|
||||
@@ -12,10 +12,12 @@
|
||||
/////// VIDEO ENCODER
|
||||
|
||||
/**
|
||||
This object compresses the video output of FreeJ (using the
|
||||
Ogg/Vorbis/Theora codec) and can be configured to save the
|
||||
compressed video in a file (playable later) or stream che
|
||||
compressed video on the internet for live playback (using icecast2)
|
||||
This object compresses the video output of FreeJ
|
||||
@class The Video Encoder compresses video to save in a file or
|
||||
stream on the net (using the Ogg/Vorbis/Theora codec) and can be
|
||||
configured to save the compressed video in a file (playable later)
|
||||
or stream che compressed video on the internet for live playback
|
||||
(using icecast2)
|
||||
|
||||
<div class="example">Example:
|
||||
|
||||
@@ -34,7 +36,6 @@
|
||||
// encoder.start_filesave("prova.ogg");
|
||||
</div>
|
||||
|
||||
@class The Video Encoder compresses video to save in a file or stream on the net
|
||||
@author Xiph.org, Kysucix, Jaromil
|
||||
@constructor
|
||||
@param {int} video_quality quality of the video compression, from 1 to 100.
|
||||
|
||||
+12
-3
@@ -3,13 +3,22 @@
|
||||
// also check the values (samplesize and samplerate) to match your conf
|
||||
// -jrml
|
||||
|
||||
H=640;
|
||||
H=800;
|
||||
M=H/128;
|
||||
W=H/(H/80);
|
||||
//W=600
|
||||
|
||||
set_resolution(W,H);
|
||||
|
||||
audio = new AudioJack("xine:out_l", 2048, 44100);
|
||||
|
||||
|
||||
|
||||
audio = new AudioJack("alsa_pcm:capture_1", 2048, 44100);
|
||||
|
||||
encoder = new VideoEncoder(10, 64000, 5, 24000);
|
||||
encoder.add_audio(audio);
|
||||
register_encoder(encoder);
|
||||
encoder.start_filesave("prova.ogg");
|
||||
|
||||
geo = new GeometryLayer();
|
||||
geo.activate(true);
|
||||
@@ -63,4 +72,4 @@ bang.frame = function() {
|
||||
}
|
||||
register_controller(bang);
|
||||
|
||||
gc();
|
||||
gc();
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// simple use of goom and audio
|
||||
// -jrml
|
||||
|
||||
audio = new AudioJack("xine:out_l", 2048, 44100);
|
||||
|
||||
goom = new GoomLayer();
|
||||
audio.add_output(goom);
|
||||
goom.start();
|
||||
add_layer(goom);
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -15,8 +15,7 @@ INCLUDES = -I$(top_srcdir)/src/include \
|
||||
-I$(top_srcdir)/lib/slw \
|
||||
-I$(top_srcdir)/lib/cwiid \
|
||||
-I/usr/include/slang \
|
||||
@XIPH_INCLUDE@ \
|
||||
@X11_LIBS@
|
||||
@XIPH_INCLUDE@
|
||||
|
||||
AM_CXXFLAGS = @SDL_CFLAGS@ @FT2_CFLAGS@ \
|
||||
-DPREFIX="\"$(prefix)\"" -DDATADIR="\"$(datadir)\""
|
||||
|
||||
+22
-13
@@ -78,10 +78,10 @@ void FFT::Impulse2Freq(float *imp, float *out)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AudioCollector::AudioCollector(const string &port, int BufferLength, unsigned int Samplerate, int FFTBuffers) :
|
||||
AudioCollector::AudioCollector(const string &port, int n_BufferLength, unsigned int n_Samplerate, int FFTBuffers) :
|
||||
m_Gain(1),
|
||||
m_SmoothingBias(1.2),
|
||||
m_FFT(BufferLength),
|
||||
m_FFT(n_BufferLength),
|
||||
m_FFTBuffers(FFTBuffers),
|
||||
m_JackBuffer(NULL),
|
||||
m_OSSBuffer(NULL),
|
||||
@@ -89,9 +89,9 @@ m_OneOverSHRT_MAX(1/(float)SHRT_MAX),
|
||||
m_Processing(false),
|
||||
m_ProcessPos(0)
|
||||
{
|
||||
m_BufferLength = BufferLength;
|
||||
m_Samplerate = Samplerate;
|
||||
m_BufferTime = m_BufferLength/(float)m_Samplerate;
|
||||
BufferLength = n_BufferLength;
|
||||
Samplerate = n_Samplerate;
|
||||
m_BufferTime = BufferLength/(float)Samplerate;
|
||||
|
||||
m_Buffer = (float*) jalloc(BufferLength * sizeof(float));
|
||||
memset(m_Buffer,0,BufferLength*sizeof(float));
|
||||
@@ -149,10 +149,10 @@ float *AudioCollector::GetFFT()
|
||||
{
|
||||
if (m_Processing)
|
||||
{
|
||||
if (m_ProcessPos+m_BufferLength<m_ProcessLength)
|
||||
if (m_ProcessPos+BufferLength<m_ProcessLength)
|
||||
{
|
||||
m_FFT.Impulse2Freq(m_ProcessBuffer+m_ProcessPos,m_FFTBuffer);
|
||||
m_ProcessPos+=m_BufferLength;
|
||||
m_ProcessPos+=BufferLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -165,7 +165,7 @@ float *AudioCollector::GetFFT()
|
||||
else
|
||||
{
|
||||
pthread_mutex_lock(m_Mutex);
|
||||
memcpy((void*)m_AudioBuffer,(void*)m_Buffer,m_BufferLength*sizeof(float));
|
||||
jmemcpy((void*)m_AudioBuffer,(void*)m_Buffer,BufferLength*sizeof(float));
|
||||
pthread_mutex_unlock(m_Mutex);
|
||||
|
||||
m_FFT.Impulse2Freq(m_AudioBuffer,m_FFTBuffer);
|
||||
@@ -191,7 +191,7 @@ float *AudioCollector::GetFFT()
|
||||
|
||||
return m_FFTOutput;
|
||||
}
|
||||
/*
|
||||
/*
|
||||
void AudioCollector::Process(const string &filename)
|
||||
{
|
||||
if (m_Processing) return;
|
||||
@@ -230,13 +230,22 @@ void AudioCollector::Process(const string &filename)
|
||||
|
||||
m_Processing=true;
|
||||
m_ProcessPos=0;
|
||||
}*/
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
void AudioCollector::get_audio(void *dest) {
|
||||
if (!pthread_mutex_trylock(m_Mutex))
|
||||
{
|
||||
jmemcpy(dest, (void*)m_Buffer, BufferLength*sizeof(float));
|
||||
pthread_mutex_unlock(m_Mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioCollector::AudioCallback_i(unsigned int Size)
|
||||
{
|
||||
if (Size<=m_BufferLength && !pthread_mutex_trylock(m_Mutex))
|
||||
if (Size<=BufferLength && !pthread_mutex_trylock(m_Mutex))
|
||||
{
|
||||
jmemcpy((void*)m_Buffer,(void*)m_JackBuffer,m_BufferLength*sizeof(float));
|
||||
jmemcpy((void*)m_Buffer,(void*)m_JackBuffer,BufferLength*sizeof(float));
|
||||
pthread_mutex_unlock(m_Mutex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,6 @@ JS(js_audio_jack_fft) {
|
||||
|
||||
void js_audio_jack_gc(JSContext *cx, JSObject *obj) {
|
||||
func("%s",__PRETTY_FUNCTION__);
|
||||
char excp_msg[MAX_ERR_MSG + 1];
|
||||
|
||||
AudioCollector *audio = (AudioCollector*)JS_GetPrivate(cx, obj);
|
||||
if(!audio) return;
|
||||
|
||||
+11
-8
@@ -151,11 +151,11 @@ bool Context::init(int wx, int hx, bool opengl, bool init_audio) {
|
||||
notice("initializing context environment", wx, hx);
|
||||
|
||||
// If selected use opengl as video output!
|
||||
#ifdef WITH_OPENGL
|
||||
if (opengl)
|
||||
screen = new SdlGlScreen();
|
||||
else
|
||||
#endif
|
||||
//#ifdef WITH_OPENGL
|
||||
// if (opengl)
|
||||
// screen = new SdlGlScreen();
|
||||
// else
|
||||
//#endif
|
||||
|
||||
screen = new SdlScreen();
|
||||
|
||||
@@ -199,8 +199,8 @@ bool Context::init(int wx, int hx, bool opengl, bool init_audio) {
|
||||
SDL_initFramerate(&FPS);
|
||||
SDL_setFramerate(&FPS, fps_speed);
|
||||
|
||||
if(init_audio)
|
||||
audio = new AudioCollector("alsa_pcm:capture_1", 2048, 44100);
|
||||
// if(init_audio)
|
||||
// audio = new AudioCollector("alsa_pcm:capture_1", 2048, 44100);
|
||||
|
||||
// initialize MLT
|
||||
// mlt_factory_init( NULL );
|
||||
@@ -486,11 +486,14 @@ void Context::add_encoder(VideoEncoder *enc) {
|
||||
func("%u:%s:%s",__LINE__,__FILE__,__FUNCTION__);
|
||||
if(enc->list) enc->rem();
|
||||
|
||||
enc->env = this;
|
||||
enc->init(this);
|
||||
|
||||
encoders.append(enc);
|
||||
|
||||
encoders.sel(0);
|
||||
|
||||
enc->sel(true);
|
||||
|
||||
func("encoder %s succesfully added", enc->name);
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,8 @@ public:
|
||||
bool IsProcessing() { return m_Processing; }
|
||||
float BufferTime() { return m_BufferTime; }
|
||||
|
||||
void get_audio(void *buffer);
|
||||
|
||||
unsigned int Samplerate;
|
||||
unsigned int BufferLength;
|
||||
|
||||
@@ -70,9 +72,7 @@ public:
|
||||
|
||||
float m_Gain;
|
||||
float m_SmoothingBias;
|
||||
unsigned int m_Samplerate;
|
||||
float m_BufferTime;
|
||||
unsigned int m_BufferLength;
|
||||
FFT m_FFT;
|
||||
pthread_mutex_t* m_Mutex;
|
||||
float *m_Buffer;
|
||||
|
||||
@@ -421,6 +421,7 @@ JS(txt_layer_calculate_size);
|
||||
#ifdef WITH_OGGTHEORA
|
||||
JS(vid_enc_start_filesave);
|
||||
JS(vid_enc_stop_filesave);
|
||||
JS(vid_enc_add_audio);
|
||||
// Shouter methods
|
||||
JS(start_stream);
|
||||
JS(stop_stream);
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include <config.h>
|
||||
#include <linklist.h>
|
||||
#include <video_encoder.h>
|
||||
#include <screen.h>
|
||||
#include <ccvt.h>
|
||||
|
||||
#ifdef WITH_OGGTHEORA
|
||||
@@ -58,7 +57,6 @@ class OggTheoraEncoder: public VideoEncoder {
|
||||
|
||||
int encode_frame();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
oggmux_info oggmux; // theorautils object
|
||||
@@ -82,7 +80,6 @@ class OggTheoraEncoder: public VideoEncoder {
|
||||
|
||||
unsigned char *yuvframe[2]; /* yuv 420 */
|
||||
|
||||
ViewPort *screen;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
* "$Id$"
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifdef WITH_OPENGL
|
||||
#ifndef __SDLGL_SCREEN_H__
|
||||
#define __SDLGL_SCREEN_H__
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <shout/shout.h>
|
||||
|
||||
class Context;
|
||||
class AudioCollector;
|
||||
|
||||
/**
|
||||
* Class describing the general interface of an encoder
|
||||
@@ -92,6 +93,8 @@ class VideoEncoder: public Entry, public JSyncThread {
|
||||
bool write_to_stream; ///< true if encoder should write to a stream
|
||||
|
||||
bool use_audio; ///< true if the encoded data should include also audio
|
||||
AudioCollector *audio; ///< holding the pointer to the @AudioCollector class
|
||||
float *audio_buf; ///< audio buffer (local copy for the encoder)
|
||||
|
||||
bool streaming; ///< set true when streaming by js start_stream()
|
||||
|
||||
@@ -101,7 +104,7 @@ class VideoEncoder: public Entry, public JSyncThread {
|
||||
|
||||
shout_t *ice;
|
||||
|
||||
|
||||
ViewPort *screen;
|
||||
|
||||
private:
|
||||
FILE *filedump_fd;
|
||||
|
||||
+1
-1
@@ -336,7 +336,7 @@ void rtc_close() {
|
||||
}
|
||||
#endif
|
||||
|
||||
void *(* jmemcpy)(void *to, const void *from, size_t len) = memcpy;
|
||||
void *(* jmemcpy)(void *to, const void *from, size_t len);
|
||||
|
||||
|
||||
bool filecheck(char *file) {
|
||||
|
||||
+28
-15
@@ -52,7 +52,9 @@ OggTheoraEncoder::OggTheoraEncoder()
|
||||
// enc_rgb24 = NULL;
|
||||
enc_y = enc_u = enc_v = NULL;
|
||||
|
||||
use_audio = true;
|
||||
use_audio = false;
|
||||
audio = NULL;
|
||||
audio_buf = NULL;
|
||||
|
||||
init_info(&oggmux);
|
||||
theora_comment_init(&oggmux.tc);
|
||||
@@ -74,6 +76,7 @@ OggTheoraEncoder::~OggTheoraEncoder() { // XXX TODO clear the memory !!
|
||||
if(enc_v) free(enc_v);
|
||||
if(enc_yuyv) free(enc_yuyv);
|
||||
|
||||
if(audio_buf) free(audio_buf);
|
||||
}
|
||||
|
||||
|
||||
@@ -89,17 +92,25 @@ bool OggTheoraEncoder::init (Context *_env) {
|
||||
oggmux.bytes_encoded = 0;
|
||||
|
||||
oggmux.audio_only = 0;
|
||||
if(use_audio && env->audio)
|
||||
|
||||
if(use_audio && audio) {
|
||||
|
||||
func("allocating encoder audio buffer of %u bytes",audio->BufferLength);
|
||||
audio_buf = (float*)calloc(audio->BufferLength, sizeof(float));
|
||||
|
||||
oggmux.video_only = 0;
|
||||
else {
|
||||
oggmux.sample_rate = audio->Samplerate;
|
||||
oggmux.channels = 1; // only 1 channel jack support for now
|
||||
oggmux.vorbis_quality = audio_quality / 100;
|
||||
oggmux.vorbis_bitrate = audio_bitrate;
|
||||
|
||||
} else {
|
||||
|
||||
oggmux.video_only = 1;
|
||||
use_audio = false;
|
||||
|
||||
}
|
||||
|
||||
oggmux.sample_rate = 44100;
|
||||
oggmux.channels = 1;
|
||||
oggmux.vorbis_quality = audio_quality / 100;
|
||||
oggmux.vorbis_bitrate = audio_bitrate;
|
||||
|
||||
/* Set up Theora encoder */
|
||||
|
||||
@@ -199,12 +210,13 @@ bool OggTheoraEncoder::feed_video() {
|
||||
(see mlt_frame.h in mltframework.org sourcecode)
|
||||
i can't tell as i don't have PPC, waiting for u mr.goil :)
|
||||
*/
|
||||
env->screen->lock();
|
||||
mlt_convert_rgb24a_to_yuv422((uint8_t*)env->screen->get_surface(),
|
||||
env->screen->w, env->screen->h,
|
||||
env->screen->w<<2, (uint8_t*)enc_yuyv, NULL);
|
||||
env->screen->unlock();
|
||||
|
||||
mlt_convert_rgb24a_to_yuv422((uint8_t*)screen->get_surface(),
|
||||
screen->w, screen->h,
|
||||
screen->w<<2, (uint8_t*)enc_yuyv, NULL);
|
||||
|
||||
ccvt_yuyv_420p(screen->w, screen->h, enc_yuyv, enc_y, enc_u, enc_v);
|
||||
ccvt_yuyv_420p(env->screen->w, env->screen->h, enc_yuyv, enc_y, enc_u, enc_v);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -242,15 +254,16 @@ int OggTheoraEncoder::encode_video( int end_of_stream) {
|
||||
int OggTheoraEncoder::encode_audio( int end_of_stream) {
|
||||
|
||||
// num = env->audio->framesperbuffer*env->audio->channels*sizeof(int16_t);
|
||||
|
||||
func("going to encode %u bytes of audio", audio->BufferLength);
|
||||
///// QUAAAA
|
||||
// oggmux_add_audio (oggmux_info *info, int16_t * readbuffer, int bytesread, int samplesread,int e_o_s);
|
||||
// oggmux_add_audio(&oggmux, env->audio->input,
|
||||
// read,
|
||||
// read / env->audio->channels /2,
|
||||
// end_of_stream );
|
||||
oggmux_add_audio_float(&oggmux, env->audio->GetAudioBuffer(),
|
||||
env->audio->BufferLength, end_of_stream);
|
||||
audio->get_audio(audio_buf);
|
||||
oggmux_add_audio_float(&oggmux, audio_buf,
|
||||
audio->BufferLength, end_of_stream);
|
||||
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -46,6 +46,7 @@ Plugger::Plugger() {
|
||||
addsearchdir("/usr/lib/freej");
|
||||
addsearchdir("/usr/local/lib/freej");
|
||||
addsearchdir("/opt/video/lib/freej");
|
||||
addsearchdir("/usr/lib/FreeFrame");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,10 @@
|
||||
* "$Id$"
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#ifdef WITH_OPENGL
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <SDL_syswm.h>
|
||||
@@ -26,7 +29,6 @@
|
||||
|
||||
#include <sdlgl_screen.h>
|
||||
#include <jutils.h>
|
||||
#include <config.h>
|
||||
|
||||
|
||||
|
||||
@@ -335,6 +337,12 @@ void SdlGlScreen::show() {
|
||||
notice("GL_TABLE_TOO_LARGE");
|
||||
}
|
||||
// notice("");
|
||||
int x_translation = 0;
|
||||
int y_translation = 0;
|
||||
int x_rotation = 0;
|
||||
int y_rotation = 0;
|
||||
int rotation = 0;
|
||||
int zoom = 0;
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
glGetError ();
|
||||
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ static double rint(double x)
|
||||
}
|
||||
|
||||
void init_info(oggmux_info *info) {
|
||||
info->with_skeleton = 0; /* skeleton is disabled by default */
|
||||
info->with_skeleton = 1; /* skeleton is disabled by default */
|
||||
info->frontend = 0; /*frontend mode*/
|
||||
info->videotime = 0;
|
||||
info->audiotime = 0;
|
||||
|
||||
@@ -38,6 +38,8 @@ JSFunctionSpec js_vid_enc_methods[] = {
|
||||
{ "start_stream", start_stream, 0},
|
||||
{ "stop_stream", stop_stream, 0},
|
||||
|
||||
{ "add_audio", vid_enc_add_audio, 1 },
|
||||
|
||||
{ "stream_host", stream_host, 1},
|
||||
{ "stream_port", stream_port, 1},
|
||||
{ "stream_mountpoint", stream_mount, 1},
|
||||
@@ -76,10 +78,8 @@ JS(js_vid_enc_constructor) {
|
||||
enc->audio_bitrate = JSVAL_TO_INT(argv[3]);
|
||||
|
||||
|
||||
if(!enc->init(env)) {
|
||||
error("JS::VideoEncoder : failed initialization");
|
||||
delete enc; return JS_FALSE;
|
||||
}
|
||||
// initialization is done with audio
|
||||
|
||||
if(!JS_SetPrivate(cx,obj,(void*)enc)) {
|
||||
error("JS::VideoEncoder : can't set the private value");
|
||||
delete enc; return JS_FALSE;
|
||||
@@ -88,6 +88,37 @@ JS(js_vid_enc_constructor) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS(vid_enc_add_audio) {
|
||||
func("%u:%s:%s",__LINE__,__FILE__,__FUNCTION__);
|
||||
|
||||
JS_CHECK_ARGC(1);
|
||||
js_is_instanceOf(&js_audio_jack_class, argv[0]);
|
||||
|
||||
JSObject *jsaudio;
|
||||
|
||||
jsaudio = JSVAL_TO_OBJECT(argv[0]);
|
||||
AudioCollector *audio =
|
||||
(AudioCollector*) JS_GetPrivate(cx, jsaudio);
|
||||
|
||||
|
||||
VideoEncoder *enc = (VideoEncoder*)JS_GetPrivate(cx, obj);
|
||||
if(!enc) {
|
||||
error("%u:%s:%s :: VideoEncoder core data is NULL",
|
||||
__LINE__,__FILE__,__FUNCTION__);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
enc->use_audio = true;
|
||||
enc->audio = audio;
|
||||
|
||||
if(!enc->init(env)) {
|
||||
error("JS::VideoEncoder : failed initialization");
|
||||
delete enc; return JS_FALSE;
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS(vid_enc_start_filesave) {
|
||||
func("%u:%s:%s",__LINE__,__FILE__,__FUNCTION__);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user