/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/***************************************************************************
 *            mov_encoder.cc
 *
 *  Sat Feb 19 14:13:19 CET 2005
 *  Copyright  2005 Bent Bisballe
 *  deva@aasimon.org
 ****************************************************************************/

/*
 * Originally from:
 * RTVideoRec Realtime video recoder and encoder for Linux
 *
 * Copyright (C) 2004  B. Stultiens
 * Copyright (C) 2004  Koen Otter and Glenn van der Meyden
 */

/*
 *    This file is part of MIaV.
 *
 *    MIaV is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    MIaV is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with MIaV; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
 */
#include "mov_encoder.h"

#include <errno.h>

// For nice
#include <unistd.h>

#include "miav_config.h"

#include "libfame_wrapper.h"

MovEncoder::MovEncoder(volatile bool *r, sem_t *r_sem,
                       ThreadSafeQueueFIFO *in,
                       ThreadSafeQueuePriority *video_out,
                       ThreadSafeQueuePriority *audio_out,
                       Info *i)
{
  info = i;
  info->info("MovEncoder");

  running = r;

  // Queues
  inputqueue = in;
  video_output_queue = video_out;
  audio_output_queue = audio_out;

  read_sem = r_sem;
}

MovEncoder::~MovEncoder()
{
  info->info("~MovEncoder");
}


// this runs in a thread
void MovEncoder::thread_main()
{
  info->info("MovEncoder::run");

  // Run with slightly lower priority than MovEncoderWriter AND AudioEncoder
  nice(2);

  FrameVector *item;
  Frame *in_frame;
  Frame *out_v_frame;
  Frame *out_a_frame;

  LibFAMEWrapper fame(info);

  // Process until running == false and the queue is empty
  while(*running) {

    item = inputqueue->pop();

    if(item) {
      for(unsigned int cnt = 0; cnt < item->size(); cnt++) {
        in_frame = item->at(cnt);

        // Check for end of stream
        if(in_frame->endOfFrameStream == true) {
          info->info("endOfFrameStream in MovEncoder");

          // Signal to stop running
          *running = false;

          // Kick them sleepy ones so they get the message.
          int threads = MIaV::config->readInt("encoding_threads") - 1; // -1 cause we only need the others!
          for(int cnt = 0; cnt < threads; cnt++) {
            inputqueue->push(NULL);
          }
        }

        // Encode video
        out_v_frame = fame.encode(in_frame);
        out_v_frame->number = in_frame->number;
        out_v_frame->endOfFrameStream = in_frame->endOfFrameStream;
    
        // Create audio frame
        out_a_frame = in_frame;
 
        video_output_queue->push(out_v_frame);
        audio_output_queue->push(out_a_frame);
      }

      delete item;

      item = NULL;

      // Kick reader
      sem_post(read_sem);
    }
  }

  info->info("MovEncoder::stop");
}






















































/*

// this runs in a thread
void MovEncoder::thread_main()
{
  info->info("MovEncoder::run");
  //  static volatile int test = 0;
#ifndef NEW_QUEUE
  int v_outsize = 0;
  int a_outsize = 0;
#endif
  int insize = 0;

  // Run with slightly lower priority than MovEncoderWriter AND AudioEncoder
  nice(3);

  FrameVector *item;
  Frame *in_frame;
  Frame *out_v_frame;
  Frame *out_a_frame;

  LibFAMEWrapper fame(info);

  // Process until running == false and the queue is empty
  while(*running) {
    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

    if(item) {
      for(unsigned int cnt = 0; cnt < item->size(); cnt++) {
        in_frame = item->at(cnt);

        // Check for end of stream
        if(in_frame->endOfFrameStream == true) {
          info->info("endOfFrameStream in MovEncoder");

          // Signal to stop running
          *running = false;

          // Kick them sleepy ones so they get the message.
          int threads = MIaV::config->readInt("encoding_threads");
          for(int cnt = 0; cnt < threads; cnt++) sem_post(input_sem);
        }
        // Encode video
        out_v_frame = fame.encode(in_frame);
        out_v_frame->number = in_frame->number;
        out_v_frame->endOfFrameStream = in_frame->endOfFrameStream;
    
        // Create audio frame
        out_a_frame = in_frame;
 
#ifdef NEW_QUEUE        
        video_output_queue->push(out_v_frame);
        audio_output_queue->push(out_a_frame);
#else
        // 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 audio encoder
        sem_post(audio_output_sem);
#endif
      }

      delete item;
      item = NULL;

      // Kick reader
      sem_post(read_sem);
    }
  }
  
  //info->info("Input pool size: %d, video output pool size: %d, audio output pool size: %d", 
  //           insize, v_outsize, a_outsize);
  

#ifndef NEW_QUEUE
  // Kick audio encoder
  sem_post(audio_output_sem);

  // Kick multiplexer (video)
  sem_post(video_output_sem);
#endif

  info->info("MovEncoder::stop");
}
*/