summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfred <fred@home.lan>2011-03-31 21:53:12 (GMT)
committer fred <fred@home.lan>2011-03-31 21:53:12 (GMT)
commit1632c0b13159e846aafe49a7d8c7b39304fc2013 (patch)
treedfc0bb1fbc85f42d7859cff72bc3bb62033132d1
parentbfca90554d5bc27c56a9d410120adaad45ccbb1b (diff)
Sync Audio with video, re-sampling audio according to the drift
- in oggmux_init, initialised the SRC_DATA struct. In oggmux_add_audio, resample with src_process function. In oggmux_flush, calculate the ratio in accordance with difference between vorbis and theora. There is some work to do to avoid sound distortion :)
-rw-r--r--qt/TODO2
-rw-r--r--qt/qJackClient.cpp3
-rw-r--r--src/include/theorautils.h2
-rw-r--r--src/include/video_encoder.h2
-rw-r--r--src/theorautils.cpp78
-rw-r--r--src/video_encoder.cpp9
6 files changed, 58 insertions, 38 deletions
diff --git a/qt/TODO b/qt/TODO
index ecdc454..08120df 100644
--- a/qt/TODO
+++ b/qt/TODO
@@ -15,6 +15,6 @@ the QJackClient of the time you waited to open the QJackClient .... see if a fix
//if resizing the wiewport when the layer is bigger, you just need to touch the layer size to display it correctly
//why qfreej doesn't install with the AUR packages
//see if possible to manage an audio layer
-//be able to change v4l2 resolution from the graphic interface
+//be able to change v4l2 resolution from the graphic interface and to disable it for some bad v4l2 devices
//see why sound delay increases on video during streaming (sound slower than video ... or video too fast)
//see why sound coming from the jack input stops after a whyle when streaming .... have to deconnect jack ports and reconnect
diff --git a/qt/qJackClient.cpp b/qt/qJackClient.cpp
index 6a2f9a3..901e385 100644
--- a/qt/qJackClient.cpp
+++ b/qt/qJackClient.cpp
@@ -49,8 +49,7 @@ bool QJackClient::init()
return (false);
}
- m_audio = new AudioCollector(1024, 48192, m_Jack); //48240 seems to be a good value in my config
-// m_audio = new AudioCollector(1024, 48000, m_Jack);
+ m_audio = new AudioCollector(1024, 48000, m_Jack);
m_Jack->isEncoded(false);
m_Enc = m_Qfreej->getEnc();
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/theorautils.cpp b/src/theorautils.cpp
index a27e6c4..32f12dc 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>
@@ -279,17 +279,23 @@ void *timer_start(void)
return (void *)start;
}
-
+int sampleError;
+SRC_STATE *src_state;
+SRC_DATA *src_data;
+double ratio;
+double *sampleOut;
void oggmux_init (oggmux_info *info){
ogg_page og;
ogg_packet op;
TIMER *timer;
-
+ src_state = NULL;
+ src_data = NULL;
+ ratio = 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 +318,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
@@ -665,6 +676,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
@@ -675,6 +687,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;
@@ -683,18 +696,29 @@ 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)) + 1000));
+ 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);
+ src_data->src_ratio = ratio; //48000.0 / 48500.0;
+ 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 */
@@ -715,7 +739,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;
@@ -918,6 +941,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;
@@ -929,13 +960,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;
}
@@ -957,22 +982,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) {
@@ -989,6 +1006,13 @@ 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 {
+ ratio = ((info->videotime - info->audiotime) / 10.0) + 1.0;
+ if (ratio > 1.05)
+ ratio = 1.05;
+ else if (ratio <= 0.95)
+ ratio = 0.95;
+ }
}
// std::cerr << "Vorbis time :" << info->audiotime << std::endl << std::flush;
}
diff --git a/src/video_encoder.cpp b/src/video_encoder.cpp
index c3ac432..dafe817 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,9 +257,9 @@ void VideoEncoder::thread_loop() {
fwrite(encbuf, 1, encnum, filedump_fd);
if(write_to_stream) {
- int wait_ms;
+/* int wait_ms;
wait_ms = shout_delay(ice);
- std::cerr << "---- shout delay :" << wait_ms << std::endl;
+ std::cerr << "---- shout delay :" << wait_ms << std::endl;*/
// shout_sync(ice); //no sound when commented out !!
if( shout_send(ice, (const unsigned char*)encbuf, encnum)
!= SHOUTERR_SUCCESS) {