From a9cf2906964fe16d82b9ce5b7ee880740ba45f2f Mon Sep 17 00:00:00 2001 From: Jaromil Date: Sat, 3 May 2008 20:10:28 +0200 Subject: [PATCH] fixes to the audio collector and video encoder, new add_audio method for video encoder, more updates and cleanups --- ChangeLog | 18 ++++++++------ doc/scripting/AudioCollector.js | 3 +-- doc/scripting/VideoEncoder.js | 11 +++++---- scripts/audio_test.js | 15 +++++++++--- scripts/goom.js | 12 +++++++++ src/Makefile.am | 3 +-- src/audio_collector.cpp | 35 +++++++++++++++++---------- src/audio_collector_js.cpp | 1 - src/context.cpp | 19 +++++++++------ src/include/audio_collector.h | 4 +-- src/include/jsparser_data.h | 1 + src/include/oggtheora_encoder.h | 3 --- src/include/sdlgl_screen.h | 3 +++ src/include/video_encoder.h | 5 +++- src/jutils.cpp | 2 +- src/oggtheora_encoder.cpp | 43 +++++++++++++++++++++------------ src/plugger.cpp | 1 + src/sdlgl_screen.cpp | 10 +++++++- src/theorautils.cpp | 2 +- src/video_encoder_js.cpp | 39 +++++++++++++++++++++++++++--- 20 files changed, 160 insertions(+), 70 deletions(-) create mode 100644 scripts/goom.js diff --git a/ChangeLog b/ChangeLog index 5178f812..6c911a91 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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) diff --git a/doc/scripting/AudioCollector.js b/doc/scripting/AudioCollector.js index 41fd805a..e839240a 100644 --- a/doc/scripting/AudioCollector.js +++ b/doc/scripting/AudioCollector.js @@ -19,8 +19,7 @@
This object collects audio from a Jack source, it can be used to - change parameter values based on the audio input. -
+ change parameter values based on the audio input.
16 harmonics are provided using a fast fourier transform, returning diff --git a/doc/scripting/VideoEncoder.js b/doc/scripting/VideoEncoder.js index 6eeb5a30..b0d583b6 100644 --- a/doc/scripting/VideoEncoder.js +++ b/doc/scripting/VideoEncoder.js @@ -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)
Example: @@ -34,7 +36,6 @@ // encoder.start_filesave("prova.ogg");
- @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. diff --git a/scripts/audio_test.js b/scripts/audio_test.js index dc2a0273..40f006e0 100644 --- a/scripts/audio_test.js +++ b/scripts/audio_test.js @@ -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(); \ No newline at end of file +gc(); diff --git a/scripts/goom.js b/scripts/goom.js new file mode 100644 index 00000000..c1e0f1b4 --- /dev/null +++ b/scripts/goom.js @@ -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); + + + diff --git a/src/Makefile.am b/src/Makefile.am index 2a75dac4..595c6304 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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)\"" diff --git a/src/audio_collector.cpp b/src/audio_collector.cpp index bec7d884..918f1677 100644 --- a/src/audio_collector.cpp +++ b/src/audio_collector.cpp @@ -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_BufferLengthlist) enc->rem(); - enc->env = this; + enc->init(this); encoders.append(enc); + encoders.sel(0); + enc->sel(true); + func("encoder %s succesfully added", enc->name); } diff --git a/src/include/audio_collector.h b/src/include/audio_collector.h index 0913a569..4964affc 100644 --- a/src/include/audio_collector.h +++ b/src/include/audio_collector.h @@ -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; diff --git a/src/include/jsparser_data.h b/src/include/jsparser_data.h index 768ad4e7..351392e8 100644 --- a/src/include/jsparser_data.h +++ b/src/include/jsparser_data.h @@ -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); diff --git a/src/include/oggtheora_encoder.h b/src/include/oggtheora_encoder.h index b0bd6e12..ee351ed1 100644 --- a/src/include/oggtheora_encoder.h +++ b/src/include/oggtheora_encoder.h @@ -26,7 +26,6 @@ #include #include #include -#include #include #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; }; diff --git a/src/include/sdlgl_screen.h b/src/include/sdlgl_screen.h index cd582563..190410b8 100644 --- a/src/include/sdlgl_screen.h +++ b/src/include/sdlgl_screen.h @@ -18,6 +18,9 @@ * "$Id$" * */ + +#include + #ifdef WITH_OPENGL #ifndef __SDLGL_SCREEN_H__ #define __SDLGL_SCREEN_H__ diff --git a/src/include/video_encoder.h b/src/include/video_encoder.h index 0a5b9ff0..09c2a9c1 100644 --- a/src/include/video_encoder.h +++ b/src/include/video_encoder.h @@ -38,6 +38,7 @@ #include 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; diff --git a/src/jutils.cpp b/src/jutils.cpp index bdf0c9a1..cd24ebf4 100644 --- a/src/jutils.cpp +++ b/src/jutils.cpp @@ -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) { diff --git a/src/oggtheora_encoder.cpp b/src/oggtheora_encoder.cpp index 41cf79d0..ee4b06bc 100644 --- a/src/oggtheora_encoder.cpp +++ b/src/oggtheora_encoder.cpp @@ -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; diff --git a/src/plugger.cpp b/src/plugger.cpp index 0b7dec4f..903e392c 100644 --- a/src/plugger.cpp +++ b/src/plugger.cpp @@ -46,6 +46,7 @@ Plugger::Plugger() { addsearchdir("/usr/lib/freej"); addsearchdir("/usr/local/lib/freej"); addsearchdir("/opt/video/lib/freej"); + addsearchdir("/usr/lib/FreeFrame"); } diff --git a/src/sdlgl_screen.cpp b/src/sdlgl_screen.cpp index ca13031f..ea8134ed 100644 --- a/src/sdlgl_screen.cpp +++ b/src/sdlgl_screen.cpp @@ -18,7 +18,10 @@ * "$Id$" * */ + +#include #ifdef WITH_OPENGL + #include #include #include @@ -26,7 +29,6 @@ #include #include -#include @@ -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 (); diff --git a/src/theorautils.cpp b/src/theorautils.cpp index c7994f01..18259d52 100644 --- a/src/theorautils.cpp +++ b/src/theorautils.cpp @@ -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; diff --git a/src/video_encoder_js.cpp b/src/video_encoder_js.cpp index 0be5792f..e94a937e 100644 --- a/src/video_encoder_js.cpp +++ b/src/video_encoder_js.cpp @@ -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__);