summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am2
-rw-r--r--src/frame.cc2
-rw-r--r--src/frame.h2
-rw-r--r--src/libfame_wrapper.cc4
-rw-r--r--src/liblame_wrapper.cc7
-rw-r--r--src/mov_encoder.cc67
-rw-r--r--src/mov_encoder.h6
-rw-r--r--src/mov_encoder_thread.cc98
-rw-r--r--src/mov_encoder_thread.h8
-rw-r--r--src/mov_encoder_writer.cc3
-rw-r--r--src/multiplexer.cc11
-rw-r--r--src/server.cc3
12 files changed, 146 insertions, 67 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 8494cf1..38bc2d5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,6 +7,7 @@ bin_PROGRAMS = miav
miav_SOURCES = $(shell if [ $QT_CXXFLAGS ] ; then ../tools/MocList cc; fi ) \
aboutwindow.cc \
+ audio_encoder.cc \
camera.cc \
cprquerydialog.cc \
daemon.cc \
@@ -44,6 +45,7 @@ miav_SOURCES = $(shell if [ $QT_CXXFLAGS ] ; then ../tools/MocList cc; fi ) \
EXTRA_DIST = \
aboutwindow.h \
+ audio_encoder.h \
camera.h \
cprquerydialog.h \
daemon.h \
diff --git a/src/frame.cc b/src/frame.cc
index cc53d62..b216164 100644
--- a/src/frame.cc
+++ b/src/frame.cc
@@ -32,6 +32,8 @@
#include <memory.h>
#include <stdlib.h>
+Frame *endOfFrameStream = NULL;// = (Frame*)0xffffffff;
+
Frame::Frame(unsigned char *d, int sz)
{
if(sz) data = new unsigned char[sz];
diff --git a/src/frame.h b/src/frame.h
index 18425ab..17de4fa 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -69,4 +69,6 @@ typedef std::priority_queue< Frame*,
std::vector<Frame*>,
frame_priority<Frame*> > FramePriorityQueue;
+extern Frame *endOfFrameStream;
+
#endif/*__FRAME_H__*/
diff --git a/src/libfame_wrapper.cc b/src/libfame_wrapper.cc
index 5c71154..a663df6 100644
--- a/src/libfame_wrapper.cc
+++ b/src/libfame_wrapper.cc
@@ -97,10 +97,10 @@ LibFAMEWrapper::LibFAMEWrapper(Info *i)
fame_par.coding = config->readString("frame_sequence")->c_str();
// quality is a percentage, which controls compression versus quality.
- fame_par.quality = config->readInt("frame_quality");
+ fame_par.quality = config->readInt("video_quality");
// Bitrate
- fame_par.bitrate = 150000; // video bitrate in bytes pr second (0=VBR)
+ fame_par.bitrate = config->readInt("video_bitrate") * 1000; // video bitrate in bytes pr second (0=VBR)
// slices_per_frame is the number of frame slices per frame. More slices provide
// better error recovery. There must be at least one slice per frame, and at most
diff --git a/src/liblame_wrapper.cc b/src/liblame_wrapper.cc
index 87b2f11..c72c2dc 100644
--- a/src/liblame_wrapper.cc
+++ b/src/liblame_wrapper.cc
@@ -222,7 +222,7 @@ Frame *LibLAMEWrapper::encode(Frame *dvframe)
mp3buf_size - val); // number of valid octets in this stream
*/
- info->info("VAL: %d - FLUSH_SZ: %d - TOTAL: %d", val, flush_sz, (val + flush_sz));
+ // info->info("VAL: %d - FLUSH_SZ: %d - TOTAL: %d", val, flush_sz, (val + flush_sz));
audio_frame->size = val + flush_sz;
@@ -265,5 +265,10 @@ Frame *LibLAMEWrapper::encode(Frame *dvframe)
(float)(config->readInt("mp3_bitrate") * 1000)/(float)(audio_frame->bitrate));
*/
+ /*
+ FILE* fp = fopen("/tmp/audiotest.mp3", "a");
+ fwrite(audio_frame->data, audio_frame->size, 1, fp);
+ fclose(fp);
+ */
return audio_frame;
}
diff --git a/src/mov_encoder.cc b/src/mov_encoder.cc
index 118a338..9212e5a 100644
--- a/src/mov_encoder.cc
+++ b/src/mov_encoder.cc
@@ -43,7 +43,7 @@
#include "debug.h"
-MovEncoder::MovEncoder(sem_t *r_sem,
+MovEncoder::MovEncoder(volatile bool *r, sem_t *r_sem,
FrameVectorQueue *in, sem_t *in_sem, pthread_mutex_t *in_mutex,
FramePriorityQueue *v_out, pthread_mutex_t *v_out_mutex, sem_t *v_out_sem,
FramePriorityQueue *a_out, pthread_mutex_t *a_out_mutex, sem_t *a_out_sem,
@@ -52,7 +52,7 @@ MovEncoder::MovEncoder(sem_t *r_sem,
info = i;
info->info("MovEncoder");
- running = true;
+ running = r;
// Queues
inputqueue = in;
@@ -86,8 +86,8 @@ void MovEncoder::thread_main()
int a_outsize = 0;
int insize = 0;
- // Run with slightly lower priority than MovEncoderWriter
- nice(1);
+ // Run with slightly lower priority than MovEncoderWriter AND AudioEncoder
+ nice(2);
FrameVector *item;
Frame *in_frame;
@@ -95,23 +95,16 @@ void MovEncoder::thread_main()
Frame *out_a_frame;
LibFAMEWrapper fame(info);
- // LibLAMEWrapper lame(info);
- // Make a new instance for every frame sequence (usually 5) to ensure no
- // frame dependencies are broken when running multithreaded.
- LibLAMEWrapper lame(info);
-
- while(running) {
+ // Process until running == false and the queue is empty
+ while(*running || ((*running == false) && (insize > 0))) {
sem_wait(input_sem);
-
// Lock inout mutex
pthread_mutex_lock(input_mutex);
item = inputqueue->front();
inputqueue->pop();
-
insize = inputqueue->size();
-
pthread_mutex_unlock(input_mutex);
// Unlock input mutex
@@ -119,45 +112,45 @@ void MovEncoder::thread_main()
for(unsigned int cnt = 0; cnt < item->size(); cnt++) {
in_frame = item->at(cnt);
- // Encode video
- //out_v_frame = new Frame(in_frame->data, in_frame->size);
- //out_v_frame->number = in_frame->number;
- out_v_frame = fame.encode(in_frame);
- out_v_frame->number = in_frame->number;
-
- // Encode audio
- //out_a_frame = new Frame(in_frame->data, in_frame->size);
- //out_a_frame->number = in_frame->number;
- out_a_frame = lame.encode(in_frame);
- out_a_frame->number = in_frame->number;
-
- // Last frame - we need to close LAME
- // if(cnt == item->size() - 1) out_a_frame = lame.close(out_a_frame);
-
- delete in_frame;
-
+ // Check for end of stream
+ if(in_frame == endOfFrameStream) {
+ info->info("endOfFrameStream in MovEncoder");
+
+ out_v_frame = in_frame;
+
+ // Stop running
+ *running = false;
+ } else {
+ // Encode video
+ out_v_frame = fame.encode(in_frame);
+ out_v_frame->number = in_frame->number;
+ }
+ // Create audio frame
+ out_a_frame = in_frame;
+
// Lock output mutex
pthread_mutex_lock(video_output_mutex);
video_outputqueue->push(out_v_frame);
v_outsize = video_outputqueue->size();
pthread_mutex_unlock(video_output_mutex);
// Unlock output mutex
-
+
// Kick multiplexer (video)
sem_post(video_output_sem);
-
+
// Lock output mutex
pthread_mutex_lock(audio_output_mutex);
audio_outputqueue->push(out_a_frame);
a_outsize = audio_outputqueue->size();
pthread_mutex_unlock(audio_output_mutex);
// Unlock output mutex
-
- // Kick multiplexer (audio)
+
+ // Kick audio encoder
sem_post(audio_output_sem);
}
delete item;
+ item = NULL;
test++;
if(test % (25 * 24) == 0)
@@ -169,7 +162,11 @@ void MovEncoder::thread_main()
}
}
- // Kick multiplexer (audio)
+ info->info("Input pool size: %d, video output pool size: %d, audio output pool size: %d",
+ insize, v_outsize, a_outsize);
+
+
+ // Kick audio encoder
sem_post(audio_output_sem);
// Kick multiplexer (video)
diff --git a/src/mov_encoder.h b/src/mov_encoder.h
index 6862c84..8488008 100644
--- a/src/mov_encoder.h
+++ b/src/mov_encoder.h
@@ -49,11 +49,11 @@ using namespace std;
#include "info.h"
#include "libfame_wrapper.h"
-#include "liblame_wrapper.h"
+//#include "liblame_wrapper.h"
class MovEncoder : public Thread {
public:
- MovEncoder(sem_t *r_sem,
+ MovEncoder(volatile bool *r, sem_t *r_sem,
FrameVectorQueue *in, sem_t *in_sem, pthread_mutex_t *in_mutex,
FramePriorityQueue *v_out, pthread_mutex_t *v_out_mutex, sem_t *v_out_sem,
FramePriorityQueue *a_out, pthread_mutex_t *a_out_mutex, sem_t *a_out_sem,
@@ -62,7 +62,7 @@ public:
void thread_main();
- volatile bool running;
+ volatile bool *running;
private:
// LibFAMEWrapper *fame;
diff --git a/src/mov_encoder_thread.cc b/src/mov_encoder_thread.cc
index dc3581d..4562ec9 100644
--- a/src/mov_encoder_thread.cc
+++ b/src/mov_encoder_thread.cc
@@ -37,11 +37,13 @@ MovEncoderThread::MovEncoderThread(const char *cpr, Info *i)
// Queues
inputqueue = new FrameVectorQueue();
video_outputqueue = new FramePriorityQueue();
+ audio_inputqueue = new FramePriorityQueue();
audio_outputqueue = new FramePriorityQueue();
// Queue mutexes
pthread_mutex_init (&input_mutex, NULL);
pthread_mutex_init (&video_output_mutex, NULL);
+ pthread_mutex_init (&audio_input_mutex, NULL);
pthread_mutex_init (&audio_output_mutex, NULL);
block = new FrameVector();
@@ -55,39 +57,83 @@ MovEncoderThread::MovEncoderThread(const char *cpr, Info *i)
// Thread stuff
sem_init(&in_sem, 0, 0);
sem_init(&video_out_sem, 0, 0);
+ sem_init(&audio_in_sem, 0, 0);
sem_init(&audio_out_sem, 0, 0);
sem_init(&read_sem, 0, 0);
+ movencodersrunning = true;
+
for(int cnt = 0; cnt < threads; cnt++) sem_post(&read_sem);
+ // Create the video encoders
+ for(int cnt = 0; cnt < threads; cnt++) {
+ MovEncoder *movenc =
+ new MovEncoder(&movencodersrunning, &read_sem,
+ inputqueue, &in_sem, &input_mutex,
+ video_outputqueue, &video_output_mutex, &video_out_sem,
+ audio_inputqueue, &audio_input_mutex, &audio_in_sem,
+ info);
+ movenc->run();
+ encs.push_back(movenc);
+ }
+
+ // Create the audio encoder
+ audioenc = new AudioEncoder(audio_inputqueue, &audio_input_mutex, &audio_in_sem,
+ audio_outputqueue, &audio_output_mutex, &audio_out_sem,
+ info);
+ audioenc->run();
+
+ // Create the multiplexer
writer = new MovEncoderWriter(cpr,
video_outputqueue, &video_output_mutex, &video_out_sem,
audio_outputqueue, &audio_output_mutex, &audio_out_sem,
info);
writer->run();
- for(int cnt = 0; cnt < threads; cnt++) {
- MovEncoder *movenc = new MovEncoder(&read_sem,
- inputqueue, &in_sem, &input_mutex,
- video_outputqueue, &video_output_mutex, &video_out_sem,
- audio_outputqueue, &audio_output_mutex, &audio_out_sem,
- info);
- movenc->run();
- encs.push_back(movenc);
- }
-
frame_number = 0;
}
+#include <unistd.h>
MovEncoderThread::~MovEncoderThread()
{
info->info("~MovEncoderThread");
+ // Push end of stream frame to the queue.
+ num_frames_in_block = block->size() + 1; // Make the next frame fill out the block.
+ encode(endOfFrameStream);
+
+ info->info("Posted endOfFrameStream");
+
+ // First we destroy the movie encoders
+ for(int cnt = 0; cnt < threads; cnt++) sem_post(&in_sem); // Kick them
+ for(int cnt = 0; cnt < threads; cnt++) {
+ encs[cnt]->wait_stop(); // Wait for it to stop
+ delete encs[cnt]; // Delete it
+ }
+
+ info->info("Deleted the movie encoders");
+
+ // Then we destroy the audio encoder
+ sem_post(&audio_in_sem); // Kick it
+ audioenc->wait_stop(); // Wait for it to stop.
+ delete audioenc; // delete the audio encoder
+
+ info->info("Deleted the audio encoder");
+
+ // Finally we destroy the writer.
+ sem_post(&video_out_sem); // Kick it to make it stop.
+ sem_post(&audio_out_sem); // Kick it to make it stop.
+ writer->wait_stop(); // Wait for it to stop.
+ delete writer; // delete the writer (end thereby close the file)
+
+ info->info("Deleted the writer");
+
+ /*
// These should not be deleted here... its done elsewhere.
// inputqueue = NULL;
- sem_post(&video_out_sem);
- sem_post(&audio_out_sem);
+ // sem_post(&video_out_sem);
+ // sem_post(&audio_out_sem);
// Tell the encoding threads to stop.
for(int cnt = 0; cnt < threads; cnt++) {
@@ -107,6 +153,18 @@ MovEncoderThread::~MovEncoderThread()
delete encs[cnt];
}
+ // Tell the audio encoder to stop
+ audioenc->running = false;
+
+ // Kick it to make it stop.
+ sem_post(&audio_in_sem);
+
+ // Wait for it to stop.
+ audioenc->wait_stop();
+
+ // delete the audio encoder
+ delete audioenc;
+
// Tell the writer to stop
writer->running = false;
@@ -119,12 +177,16 @@ MovEncoderThread::~MovEncoderThread()
// delete the writer (end thereby close the file)
delete writer;
-
+ */
// Destroy the semaphores.
sem_destroy(&in_sem);
sem_destroy(&video_out_sem);
+ sem_destroy(&audio_in_sem);
sem_destroy(&audio_out_sem);
sem_destroy(&read_sem);
+
+
+ info->info("MovEncoderThread done deinitializing.");
}
void MovEncoderThread::encode(Frame* frame)
@@ -141,11 +203,6 @@ void MovEncoderThread::encode(Frame* frame)
// Switch frame
if(block->size() == num_frames_in_block) {
// Wait until a free encoder.
- /*
- int val;
- sem_getvalue(&read_sem, &val);
- fprintf(stderr, "Sem Value: %d\n", val); fflush(stderr);
- */
sem_wait(&read_sem);
// Lock input mutex
@@ -154,11 +211,6 @@ void MovEncoderThread::encode(Frame* frame)
pthread_mutex_unlock(&input_mutex);
// Unlock input mutex
- // fprintf(stderr, "Frame vector [%d-%d] pushed\n",
- // block->at(0)->number,
- // block->at(block->size() - 1)->number);
- fflush(stderr);
-
// Kick encoders
sem_post(&in_sem);
diff --git a/src/mov_encoder_thread.h b/src/mov_encoder_thread.h
index 5684edf..e3fba27 100644
--- a/src/mov_encoder_thread.h
+++ b/src/mov_encoder_thread.h
@@ -37,6 +37,7 @@
using namespace std;
#include "mov_encoder.h"
+#include "audio_encoder.h"
#include "mov_encoder_writer.h"
#include "info.h"
@@ -53,20 +54,25 @@ private:
FrameVectorQueue *inputqueue;
FramePriorityQueue *video_outputqueue;
+ FramePriorityQueue *audio_inputqueue;
FramePriorityQueue *audio_outputqueue;
FrameVector *block;
//thread stuff
sem_t in_sem;
sem_t video_out_sem;
+ sem_t audio_in_sem;
sem_t audio_out_sem;
sem_t read_sem;
pthread_mutex_t input_mutex;
pthread_mutex_t video_output_mutex;
+ pthread_mutex_t audio_input_mutex;
pthread_mutex_t audio_output_mutex;
+ volatile bool movencodersrunning;
+
// Used for encoder switching
unsigned int frame_number;
@@ -75,6 +81,8 @@ private:
MovEncoderWriter *writer;
// pthread_t* writer_tid;
+ AudioEncoder* audioenc;
+
int threads;
vector<MovEncoder*> encs;
// vector<pthread_t*> tids;
diff --git a/src/mov_encoder_writer.cc b/src/mov_encoder_writer.cc
index bc9302a..83530ac 100644
--- a/src/mov_encoder_writer.cc
+++ b/src/mov_encoder_writer.cc
@@ -93,9 +93,6 @@ MovEncoderWriter::MovEncoderWriter(const char* cpr,
audio_frame_number = 0;
running = true;
-
- // empty_timecode_struc(&SCR);
- // timestamp = 0.0;
}
MovEncoderWriter::~MovEncoderWriter()
diff --git a/src/multiplexer.cc b/src/multiplexer.cc
index a94c150..323b33c 100644
--- a/src/multiplexer.cc
+++ b/src/multiplexer.cc
@@ -125,21 +125,31 @@ int Multiplexer::read_stream(char *buf, unsigned int size, StreamType type)
// Lock output mutex
pthread_mutex_lock( mutex[type] );
tmpframe = queue[type]->top();
+
if(tmpframe && tmpframe->number == frame_number[type] ) {
queue[type]->pop();
frame[type] = tmpframe;
frame_number[type]++;
read[type] = 0;
}
+ /*
if(*running == false && frame[type] == NULL) {
pthread_mutex_unlock( mutex[type] );
//info->info("Bailed out early %d!", copied);
return copied;
}
+ */
+
pthread_mutex_unlock( mutex[type] );
// Unlock output mutex
}
+ // check for end of stream
+ if( frame[type] == endOfFrameStream ) {
+ info->info("endOfFrameStream in Multiplexer %s-stream.", type==TYPE_VIDEO?"video\0":"audio\0");
+ return copied;
+ }
+
// If a frame exists in the buffer copy it to the output buffer
// (No frame ocurres when *running is set to false)
if( frame[type] ) {
@@ -455,6 +465,7 @@ void Multiplexer::multiplex()
char buf[1024];
do {
frmsz = read_stream(buf, sizeof(buf), BYPASS);
+ info->info("Wrote %d bytes", frmsz);
file->Write(buf, frmsz);
} while(frmsz == sizeof(buf));
return;
diff --git a/src/server.cc b/src/server.cc
index bdca907..892b2e9 100644
--- a/src/server.cc
+++ b/src/server.cc
@@ -56,6 +56,9 @@
void newConnection(Socket *socket, Info *info)
{
+ // We need to create the end of stream frame.
+ if(endOfFrameStream == NULL) endOfFrameStream = new Frame(NULL, 1);
+
char cpr[256];
bool hasCpr = false;
ServerStatus status(info);