diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 2 | ||||
| -rw-r--r-- | src/frame.cc | 2 | ||||
| -rw-r--r-- | src/frame.h | 2 | ||||
| -rw-r--r-- | src/libfame_wrapper.cc | 4 | ||||
| -rw-r--r-- | src/liblame_wrapper.cc | 7 | ||||
| -rw-r--r-- | src/mov_encoder.cc | 67 | ||||
| -rw-r--r-- | src/mov_encoder.h | 6 | ||||
| -rw-r--r-- | src/mov_encoder_thread.cc | 98 | ||||
| -rw-r--r-- | src/mov_encoder_thread.h | 8 | ||||
| -rw-r--r-- | src/mov_encoder_writer.cc | 3 | ||||
| -rw-r--r-- | src/multiplexer.cc | 11 | ||||
| -rw-r--r-- | src/server.cc | 3 | 
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); | 
