diff options
| -rw-r--r-- | qt/.gitignore | 11 | ||||
| -rw-r--r-- | qt/Qfreej.pro | 2 | ||||
| -rw-r--r-- | qt/QqWidget.cpp | 12 | ||||
| -rw-r--r-- | qt/QqWidget.h | 5 | ||||
| -rw-r--r-- | qt/TODO | 19 | ||||
| -rw-r--r-- | qt/qJackClient.cpp | 16 | ||||
| -rw-r--r-- | qt/qJackClient.h | 2 | ||||
| -rw-r--r-- | qt/qfreej.cpp | 5 | ||||
| -rw-r--r-- | qt/qfreej.h | 1 | ||||
| -rw-r--r-- | src/fps.cpp | 8 | ||||
| -rw-r--r-- | src/include/fps.h | 6 | ||||
| -rw-r--r-- | src/include/layer.h | 2 | ||||
| -rw-r--r-- | src/include/theorautils.h | 2 | ||||
| -rw-r--r-- | src/include/video_encoder.h | 2 | ||||
| -rw-r--r-- | src/include/video_layer.h | 2 | ||||
| -rw-r--r-- | src/theorautils.cpp | 95 | ||||
| -rw-r--r-- | src/v4l2_layer.cpp | 2 | ||||
| -rw-r--r-- | src/video_encoder.cpp | 10 | ||||
| -rw-r--r-- | src/video_layer.cpp | 4 |
19 files changed, 124 insertions, 82 deletions
diff --git a/qt/.gitignore b/qt/.gitignore index ef7f961..28c373b 100644 --- a/qt/.gitignore +++ b/qt/.gitignore @@ -1,4 +1,5 @@ tmp/* +*.swp toto* thedaytrip_512kb.* Qfreej.pro.user.2.1pre1 @@ -29,24 +30,16 @@ dump.* dump_t.* capture_client capture_client.* -aaa.avi atime.3gp film.mp4 -film2.avi -film_mono.avi -film_org.avi -kury_s.avi -kury_s_mono.avi *.o qfreej_s git_doc.txt Qfreej.pro.user Qfreej.pro.user.1.3 moc_* -kury.avi -term.avi ui_qfreej.h *.ods TODO.txt -atruc.avi Video/* +*.avi diff --git a/qt/Qfreej.pro b/qt/Qfreej.pro index 0d71763..89c29ea 100644 --- a/qt/Qfreej.pro +++ b/qt/Qfreej.pro @@ -35,7 +35,7 @@ SOURCES += main.cpp \ qLogging.h #FORMS += qfreej.ui CONFIG += qt debug -LIBS += -lfreej +LIBS += -L../src/.libs -lfreej INCLUDEPATH += ../ \ /usr/include/SDL \ ../lib/sdl_ttf \ diff --git a/qt/QqWidget.cpp b/qt/QqWidget.cpp index c346d87..b86ee6c 100644 --- a/qt/QqWidget.cpp +++ b/qt/QqWidget.cpp @@ -43,7 +43,7 @@ QqWidget::QqWidget(Context *freej, QqTabWidget* tabWidget, Qfreej* qfreej, QStri fakeView = NULL; fakeLay = NULL; ctx = NULL; - actualFps = normalFps = 0; + actualFps = normalFps = fpsP = 0; qLayer = freej->open((char*)fichier.toStdString().c_str(), 0, 0); // hey, this already init and open the layer !! if(qLayer) { @@ -63,6 +63,7 @@ QqWidget::QqWidget(Context *freej, QqTabWidget* tabWidget, Qfreej* qfreej, QStri qLayer->fps.set(qLayer->frame_rate); normalFps = qLayer->frame_rate; actualFps = qLayer->frame_rate; + fpsP = 100; qDebug() << "--- actualFps :" << actualFps; // } tabWidget->addTab(this, qLayer->get_filename()); @@ -119,9 +120,9 @@ QqWidget::QqWidget(Context *freej, QqTabWidget* tabWidget, Qfreej* qfreej, QStri slowFps = new QSlider(this); slowFps->setOrientation(Qt::Vertical); connect(slowFps, SIGNAL(sliderMoved(int)), this, SLOT(changeFps(int))); - slowFps->setRange(1, (normalFps*2)); + slowFps->setRange(2, 100); slowFps->setToolTip("speed control (grey: normal speed, red: higher or lower)"); - slowFps->setValue(normalFps); + slowFps->setValue(50); slowFps->setSliderDown(true); slowFps->setStyleSheet("background: grey"); layoutH->addWidget(slowFps); @@ -537,9 +538,10 @@ void QqWidget::changeFps(int val) { if (qLayer) { - if (val != actualFps) + if (val != 50) { - qLayer->fps.set(val); + actualFps = ((float)val / 50.0) * normalFps; + qLayer->fps.set(actualFps); slowFps->setStyleSheet("background: red"); } else diff --git a/qt/QqWidget.h b/qt/QqWidget.h index 7ab0b0c..59e5f12 100644 --- a/qt/QqWidget.h +++ b/qt/QqWidget.h @@ -57,8 +57,9 @@ private: QPushButton *textButton; QPushButton *slowButton; QSlider *slowFps; - int normalFps; - int actualFps; + float normalFps; + float actualFps; + int fpsP; QPushButton *playButton; bool isPlaying; QComboBox *fontSizeBox; @@ -1,21 +1,22 @@ //move main window in accordance with the size //resize ViewPort in accordance to the biggest layer .... (not sure it is good thing) //be able to record all marked opened layers with the same quality .... a challenge :) -//see to use Linklist.completion to add blit, filters and generators //devide the fake size window by two .... not sure :) //insert STRING filters parameters //add a x:x ratio button, resizing to the closest width and lenght to obtain this ratio //create a console for messages comming from func() warning() notice() act(). see Logger class //see to integrate ogg skeleton config on the graphic interface -//there is the amount of delay between audio and video if you open a video before creating +//there is a delay between audio and video if you open a video before creating the QJackClient of the time you waited to open the QJackClient .... see if a fix possible or needed. //Jack server sample rate and buffer size is hard coded for the moment, provide a way to put it manualy //try to fix sound problem issue when opening several VideoLayer with audio -//add the capability to have a config file..... important :) -//if resizing the wiewport when the layer is bigger, you need to just touch the layer size to display it correctly -//why qfreej doesn't install with the AUR packages +//add the capability to keep the actual config in a file..... important :) +//if resizing the wiewport when the layer is bigger, you just need to touch the layer size to display it correctly //see if possible to manage an audio layer -//be able to change v4l2 resolution from the graphic interface -//see why sound delay increases on video during streaming -//see why sound stops after a whyle when streaming .... have to deconnect jack ports and connect back -//need do adjust stream bitrate value. +//be able to change v4l2 resolution from the graphic interface and to disable it for some bad v4l2 devices +//try to suppress the drift taken when applying an effect +//streaming a/v, when stopping audio, the stream is corrupted and the client stops (oggmux_flush) +//needs to launch QJackClient before start streaming when you want audio. +//needs to re-launch streaming when disconnect and reconnect the jack input port +//try to see why there is around 100 us more in between each call to the fps class (40100 instead od 40000 for 25fps) +//merge with mastr branch ..... mainly for qt config modif
\ No newline at end of file diff --git a/qt/qJackClient.cpp b/qt/qJackClient.cpp index 7078e6e..1ff8d5f 100644 --- a/qt/qJackClient.cpp +++ b/qt/qJackClient.cpp @@ -29,6 +29,7 @@ QJackClient::QJackClient(Qfreej *qfreej) : QWidget() QJackClient::~QJackClient() { + if (m_Qfreej->getQEnc()) delete (m_Qfreej->getQEnc()); if (m_JackIsOn && m_Jack) m_Jack->Detach(); m_Jack = NULL; m_Qfreej->resetQJack(); @@ -71,14 +72,15 @@ bool QJackClient::init() m_Coef->setEnabled(false); layoutG->addWidget(m_Coef, 2, 0, 1, 2); m_Coef->setToolTip("sets the Mix coefficient between Jack Input and Video Layer output"); - + + //not used m_SampleRate = new QLineEdit; - connect (m_SampleRate, SIGNAL(returnPressed()), this, SLOT(chgSampleRate())); +// connect (m_SampleRate, SIGNAL(returnPressed()), this, SLOT(chgSampleRate())); m_SampleRate->setValidator(new QIntValidator(m_SampleRate)); m_SampleRate->setText("48000"); //default Jackd sample rate m_SampleRate->setEnabled(false); // m_Jack->m_SampleRate = 48000; //not necessary as it is donne in AudioCollector constructor - + // QLabel *vSampleRate = new QLabel("J SampleRate :"); layoutG->addWidget(vSampleRate, 3, 0); layoutG->addWidget(m_SampleRate, 3, 1); @@ -166,10 +168,10 @@ void QJackClient::addInput() } } -void QJackClient::chgSampleRate() -{ - m_Jack->m_SampleRate = m_SampleRate->text().toInt(); -} +// void QJackClient::chgSampleRate() +// { +// m_Jack->m_SampleRate = m_SampleRate->text().toInt(); +// } int QJackClient::getSampleRate() { diff --git a/qt/qJackClient.h b/qt/qJackClient.h index 4f005a2..9180445 100644 --- a/qt/qJackClient.h +++ b/qt/qJackClient.h @@ -25,7 +25,7 @@ public: public slots: void addInput(); void addOutput(); - void chgSampleRate(); +// void chgSampleRate(); void chgSamples(); void changeMixCoef(int); diff --git a/qt/qfreej.cpp b/qt/qfreej.cpp index a92de91..858ff16 100644 --- a/qt/qfreej.cpp +++ b/qt/qfreej.cpp @@ -241,6 +241,11 @@ OggTheoraEncoder *Qfreej::getEnc() return (NULL); } +QEncoder *Qfreej::getQEnc() +{ + return(m_Enc); +} + void Qfreej::addTextLayer() { QqWidget *aWidget = new QqWidget(freej, tabWidget, this); diff --git a/qt/qfreej.h b/qt/qfreej.h index 9f747ae..cc726f6 100644 --- a/qt/qfreej.h +++ b/qt/qfreej.h @@ -39,6 +39,7 @@ public: QJackClient *getQjack(); Context *getFreej(); OggTheoraEncoder *getEnc(); + QEncoder *getQEnc(); void resetEnc(); void resetQJack(); diff --git a/src/fps.cpp b/src/fps.cpp index bfd2f16..289051b 100644 --- a/src/fps.cpp +++ b/src/fps.cpp @@ -58,7 +58,7 @@ FPS::~FPS() { error("error destroying POSIX thread feed attribute"); } -void FPS::init(int rate) { +void FPS::init(float rate) { this->set(25); @@ -110,12 +110,12 @@ void FPS::calc() { } -int FPS::get() { +float FPS::get() { return (_fps ? fpsd.sum / fpsd.n : 0 ); } -int FPS::set(int rate) { - func("FPS set to %u",rate); +float FPS::set(float rate) { + func("FPS set to %f",rate); if (rate < 0) // invalid return fps_old; diff --git a/src/include/fps.h b/src/include/fps.h index ae790cb..1338a91 100644 --- a/src/include/fps.h +++ b/src/include/fps.h @@ -29,10 +29,10 @@ class FPS { FPS(); ~FPS(); - void init(int rate); + void init(float rate); - int get(); - int set(int rate); + float get(); + float set(float rate); void calc(); void delay(); void select_sleep(long usec); diff --git a/src/include/layer.h b/src/include/layer.h index 15d30aa..77e0da6 100644 --- a/src/include/layer.h +++ b/src/include/layer.h @@ -213,7 +213,7 @@ class Layer: public Entry, public JSyncThread { unsigned int textureID; ///< opengl texture id - int frame_rate; ///< value set by implemented layer type + float frame_rate; ///< value set by implemented layer type protected: diff --git a/src/include/theorautils.h b/src/include/theorautils.h index fa9eb71..4cc1a65 100644 --- a/src/include/theorautils.h +++ b/src/include/theorautils.h @@ -21,7 +21,7 @@ #define _F2T_THEORAUTILS_H_ #include <config.h> - +#include <samplerate.h> #include <stdint.h> #include <theora/theora.h> #include <vorbis/codec.h> diff --git a/src/include/video_encoder.h b/src/include/video_encoder.h index 5070345..2e1e6ee 100644 --- a/src/include/video_encoder.h +++ b/src/include/video_encoder.h @@ -126,7 +126,7 @@ class VideoEncoder: public Entry, public JSyncThread { // char encbuf[1024*128]; // char encbuf[1024*2096]; char *encbuf; - struct timeval m_ActualTime, m_OldTime; + struct timeval m_ActualTime, m_OldTime/*, fpsCheck, fpsCheckLast*/; double m_StreamRate; int m_Streamed; double m_ElapsedTime; diff --git a/src/include/video_layer.h b/src/include/video_layer.h index 48118f3..37ddea9 100644 --- a/src/include/video_layer.h +++ b/src/include/video_layer.h @@ -157,7 +157,7 @@ class VideoLayer: public Layer { double mark_out; /** dropping frames variables */ int user_play_speed; /** play speed to be visualized to the user */ - int play_speed; /** real speed */ + float play_speed; /** real speed */ int play_speed_control; diff --git a/src/theorautils.cpp b/src/theorautils.cpp index dec9077..44ab7a7 100644 --- a/src/theorautils.cpp +++ b/src/theorautils.cpp @@ -25,7 +25,7 @@ #include <stdlib.h> #include <unistd.h> #include <string.h> -#include <time.h> +#include <sys/time.h> #include <iostream> @@ -72,7 +72,7 @@ static double rint(double x) void init_info(oggmux_info *info) { info->audio_only = 0; - info->with_skeleton = 0; /* skeleton is enabled by default */ + info->with_skeleton = 1; /* skeleton is enabled by default */ info->frontend = NULL; /*frontend mode*/ info->videotime = 0; info->audiotime = 0; @@ -279,17 +279,25 @@ void *timer_start(void) return (void *)start; } - +int sampleError; +SRC_STATE *src_state; +SRC_DATA *src_data; +double ratio, averageR; +double *sampleOut, samplesA; void oggmux_init (oggmux_info *info){ ogg_page og; ogg_packet op; TIMER *timer; - + src_state = NULL; + src_data = NULL; + ratio = 1.0; + averageR = 1.0; + samplesA = 1.0; + sampleOut = NULL; + /* yayness. Set up Ogg output stream */ srand (time (NULL)); -/* if (ogg_stream_init (&info->vo, rand ()) == -1)*/ - if(!info->audio_only){ ogg_stream_init (&info->to, rand ()); /* oops, add one ot the above */ @@ -312,7 +320,12 @@ void oggmux_init (oggmux_info *info){ std::cerr << "-------- ogg_stream_init -- failed !!" << std::endl; return; } - + if (!(src_state = src_new (0, info->channels, &sampleError))) { + std::cerr << "--- error initialysing the SRC_STATE :" << src_strerror (sampleError) << std::endl; + } + else { + src_data = (SRC_DATA *)malloc(sizeof(SRC_DATA)); + } vorbis_info_init (&info->vi);// if (!(info->vorbis_quality >= -0.1) || !(info->vorbis_quality <= 1.0)) info->vorbis_quality = 0.5; //if quality has a wrong value, sets to 0.5 @@ -572,7 +585,6 @@ void oggmux_init (oggmux_info *info){ if (info->with_skeleton) { add_fisbone_packet (info); while (1) { - std::cerr << "------- with_skeleton !!!!" << std::endl; int result = ogg_stream_flush (&info->so, &og); //3 with_skeleton if (result < 0) { /* can't get here */ @@ -666,6 +678,7 @@ void oggmux_add_video (oggmux_info *info, yuv_buffer *yuv, int e_o_s){ } } + /** * adds audio samples to encoding sink * @param buffer pointer to buffer @@ -676,6 +689,7 @@ void oggmux_add_video (oggmux_info *info, yuv_buffer *yuv, int e_o_s){ void oggmux_add_audio (oggmux_info *info, float * buffer, int bytes, int samples, int e_o_s){ ogg_packet op; float *ptr = buffer; + float *sampleOut = NULL; int i,j, c, count = 0; float **vorbis_buffer; @@ -684,18 +698,32 @@ void oggmux_add_audio (oggmux_info *info, float * buffer, int bytes, int samples if(e_o_s) vorbis_analysis_wrote (&info->vd, 0); } - else{ - vorbis_buffer = vorbis_analysis_buffer (&info->vd, samples); //samples = rv/(channels*sizeof(float)) + else{ //resample code + sampleOut = (float *)realloc(sampleOut, ((samples * info->channels * sizeof(float)) \ + + (1.2 * ((samples * info->channels * sizeof(float)))))); + memset(src_data, 0, sizeof(SRC_DATA)); + src_data->data_in = buffer; + src_data->input_frames = (long)samples; + src_data->data_out = sampleOut; + src_data->output_frames = (long)((double)samples * 1.1); + if (ratio > 1.1 || ratio < 0.9) + ratio = 1.0; + src_data->src_ratio = ratio; + src_data->end_of_input = 0; + if (int processError = src_process (src_state, src_data)) { + std::cerr << "--- resample error :" << src_strerror (processError) << std::endl; + } + + vorbis_buffer = vorbis_analysis_buffer (&info->vd, src_data->output_frames_gen); //samples = rv/(channels*sizeof(float)) for (j=0; j < info->channels; j++) { - for (i=0, c=0; i < samples; i++, c+=info->channels) + for (i=0, c=0; i < src_data->output_frames_gen ; i++, c+=info->channels) { - vorbis_buffer[j][i] = buffer[c+j]; + vorbis_buffer[j][i] = sampleOut[c+j]; } } - vorbis_analysis_wrote (&info->vd, samples); + vorbis_analysis_wrote (&info->vd, src_data->output_frames_gen); } - //for the moment same as encode.c int ret; while((ret = vorbis_analysis_blockout (&info->vd, &info->vb)) == 1){ //idem /* analysis, assume we want to use bitrate management */ @@ -716,7 +744,6 @@ void oggmux_add_audio (oggmux_info *info, float * buffer, int bytes, int samples else if (bet && OV_EIMPL) std::cerr << std::endl << "vorbis_analysis_blockout : Unimplemented; \ not supported by this version of the library." << std::endl << std::flush; - } if (ret && OV_EINVAL) std::cerr << std::endl << "vorbis_analysis_blockout :Invalid parameters." << std::endl << std::flush; @@ -919,6 +946,14 @@ static int find_best_valid_kate_page(oggmux_info *info) return best; } +double _fabs (double val) +{ + if (val >= 0) + return (val); + else + return (-val); +} + void oggmux_flush (oggmux_info *info, int e_o_s) { int len; @@ -930,13 +965,7 @@ void oggmux_flush (oggmux_info *info, int e_o_s) while(1) { /* Get pages for both streams, if not already present, and if available.*/ if(!info->audio_only && !info->videopage_valid) { - // this way seeking is much better, - // not sure if 23 packets is a good value. it works though int v_next=0; -/* if (info->v_pkg>22 && ogg_stream_flush(&info->to, &og) > 0) { -// std::cerr << "--1--" << std::endl << std::flush; - v_next=1; - }*/ if(ogg_stream_pageout(&info->to, &og) > 0) { //2 v_next=1; } @@ -958,22 +987,14 @@ void oggmux_flush (oggmux_info *info, int e_o_s) { std::cerr << "the given theora granulepos is invalid" << std::endl << std::flush; } -// std::cerr << "Theora time :" << info->videotime << std::endl << std::flush; } } } if(!info->video_only && !info->audiopage_valid) { - // this way seeking is much better, - // not sure if 23 packets is a good value. it works though int a_next=0; -// if(info->a_pkg>22 && ogg_stream_flush(&info->vo, &og) > 0) { if(ogg_stream_pageout(&info->vo, &og) > 0) { a_next=1; } -/* else if(ogg_stream_pageout(&info->vo, &og) > 0) { -// std::cerr << "--v1--" << std::endl << std::flush; - a_next=1; - }*/ if(a_next) { len = og.header_len + og.body_len; if(info->audiopage_buffer_length < len) { @@ -990,6 +1011,22 @@ void oggmux_flush (oggmux_info *info, int e_o_s) ogg_page_granulepos(&og)); if (info->audiotime == -1) std::cerr << "the given vorbis granulepos is invalid" << std::endl << std::flush; + else { + samplesA++; + ratio = ((info->videotime - info->audiotime) / 60.0 )+ averageR; + averageR = (ratio + (averageR * (samplesA - 1))) / samplesA; +// std::cerr << "ratio :" << ratio << " averageR :" << averageR; + if (ratio > (averageR * 1.01)) { + ratio = averageR * 1.01; +// std::cerr << " resampled at:" << ratio << std::endl; + } + else if (ratio < (averageR * 0.99)) { + ratio = averageR * 0.99; +// std::cerr << " resampled at:" << ratio << std::endl; + } +// else +// std::cerr << " resampled at:" << ratio << std::endl; + } } // std::cerr << "Vorbis time :" << info->audiotime << std::endl << std::flush; } diff --git a/src/v4l2_layer.cpp b/src/v4l2_layer.cpp index b65dc97..352322c 100644 --- a/src/v4l2_layer.cpp +++ b/src/v4l2_layer.cpp @@ -129,7 +129,7 @@ bool V4L2CamLayer::open(const char *devfile) { return (false); } -// memset(&format, 0, sizeof format); +///////////// does not work with my ricoh and the uvcvideo module .... just comment out if needed format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; format.fmt.pix.width = 352; format.fmt.pix.height = 288; diff --git a/src/video_encoder.cpp b/src/video_encoder.cpp index 21b5e51..45cfbd5 100644 --- a/src/video_encoder.cpp +++ b/src/video_encoder.cpp @@ -96,7 +96,6 @@ VideoEncoder::VideoEncoder() fps = new FPS(); fps->init(25); // default FPS - // initialize the encoded data pipe // TODO: set the size to width * height * 4 * nframes (3-4) ringbuffer = ringbuffer_create(1048*2096); @@ -202,11 +201,9 @@ void VideoEncoder::thread_loop() { " tv_usec :" << fps->start_tv.tv_usec << " \r" << std::endl; return; } - //gettimeofday(&actual_time,NULL); fps->calc(); //without this the thread_loop is called nearly two times more and fps->delay(); //stream speed is too slow - //std::cout << "actual_time.tv_sec :" << actual_time.tv_sec << \ - " tv_usec :" << actual_time.tv_usec << " \r" << std::endl; + screen->lock(); switch(screen->get_pixel_format()) { @@ -260,7 +257,10 @@ void VideoEncoder::thread_loop() { fwrite(encbuf, 1, encnum, filedump_fd); if(write_to_stream) { -// shout_sync(ice); //no sound when commented out !! +/* int wait_ms; + wait_ms = shout_delay(ice); + std::cerr << "---- shout delay :" << wait_ms << std::endl;*/ + shout_sync(ice); if( shout_send(ice, (const unsigned char*)encbuf, encnum) != SHOUTERR_SUCCESS) { error("shout_send: %s", shout_get_error(ice)); diff --git a/src/video_layer.cpp b/src/video_layer.cpp index cfa0348..ba275ff 100644 --- a/src/video_layer.cpp +++ b/src/video_layer.cpp @@ -252,7 +252,7 @@ bool VideoLayer::open(const char *file) { /* this saves only file without full path! */ set_filename (file); - act ("%s (codec: %s) has resolution %dx%d and framerate %d", + act ("%s (codec: %s) has resolution %dx%d and framerate %f", get_filename(), video_codec->name, video_codec_ctx->width, video_codec_ctx->height, frame_rate); @@ -317,7 +317,7 @@ bool VideoLayer::open(const char *file) { geo.init(video_codec_ctx->width, video_codec_ctx->height, 32); func("VideoLayer :: w[%u] h[%u] size[%u]", geo.w, geo.h, geo.bytesize); - func("VideoLayer :: frame_rate[%d]",frame_rate); + func("VideoLayer :: frame_rate[%f]",frame_rate); // initialize picture if( new_picture(rgba_picture) < 0) { |

