/* Network-Integrated Multimedia Middleware (NMM)
 * http://www.motama.com/nmm.html
 *  
 * Copyright (C) 2006-2007
 * Motama GmbH, Saarbruecken, Germany
 * http://www.motama.com
 *  
 * This file is part of NMM. 
 * 
 * NMM 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; only version 2 of the License.      
 * 
 * NMM 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 NMM; if not, write to the Free Software Foundation,    
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */


#ifndef _NMM_FFMPEGENCODENODE_HPP_
#define _NMM_FFMPEGENCODENODE_HPP_ _NMM_FFMPEGENCODENODE_HPP_

#include "nmm/nmm_prefix.hpp"

#include <sys/time.h>

#include "nmm/multimedia/GenericProcessorNode.hpp"
#include "nmm/multimedia/interfaces/ITrackImpl.hpp"
#include "nmm/plugins/interfaces/IEncodeImpl.hpp"
#include "nmm/plugins/interfaces/IEncodeStatsImpl.hpp"

namespace NMM {

  /**
   * This class takes YUV-Video-frames and converts
   * them to encoded frames by using the FFMpeg-library from
   * http://ffmpeg.sourceforge.net/
   *
   * This Node has one Input Stream and one Output Stream.
   */
  class FFMpegEncodeNode :
    public GenericProcessorNode,
    public ITrackImpl,
    public IEncodeImpl,
    public IEncodeStatsImpl
  {
 private:
    class FFMpegHandle;
    
    FFMpegHandle* ffmpeg;      ///< class containing all avcodec relevant stuff
    int height;                ///< height of the frames
    int width;                 ///< width of the frames
    float aspect_ratio;        ///< width of the frames
    float framerate;	         ///< the frame rate of the sequence to be encoded
    long bitrate;	             ///< the bitrate of the target encoded stream
    int gop_size;              ///< The size of one Group of Pictures
    int qmin;                  ///< min qscale
    int qmax;                  ///< max qscale
    int max_qdiff;             ///< max qscale difference between frames
    float qblur;               ///< amount of qscale smoothing over time (0.0-1.0)
    float qcompress;           ///< amount of qscale change between easy & hard scenes (0.0-1.0)
    int me_method;             ///< ME algorithm used for video coding
    int avframe_size;          ///< size of the Y-Plane of an image
    int out_size;              ///< the output size of an encoded frame
    string compressor;         ///< Name of Compressor(fourcc code)
    int enc_buf_size;          ///< the default size for an encoded buffer

    int frame_count;           ///< count of frames that are encoded
    struct timeval tv;         ///< remember time to calculate frames per second
    struct timezone tz;        ///< timezone
    int startsec;              ///< the second we started
    int neededsecs;            ///< second since start
    float encfps;              ///< average frames per second
    
    Buffer* last_buffer;       ///< Buffer to remember if e key_frame-Event is sent
    
    bool send_frame_count;     ///< send frame counts
    int last_frame_count;      ///< last frame count an event was sent
    
    ThreadMutex ffmpeg_mutex;  ///< Thread-Mutex
    
    typedef std::map<std::string, int> CodecMap;
    typedef CodecMap::iterator CodecIterator;    
    typedef CodecMap::const_iterator CodecConstIterator;
    
    CodecMap codecs;       ///< FourCC codes of all available codecs, mapped to codec IDs
    std::string __default_codec; ///< FourCC code of default codec

// for testing        
//     bool bitrate_changed;
//     int output_frames;
//     int discard_frames;
//     RcOverride * __rc_override;
    
  public:
    FFMpegEncodeNode(const char* name = "FFMpegEncodeNode",
                     StreamQueue::Mode qmode = StreamQueue::MODE_SUSPEND,
                     int qsize = StreamQueue::DEFAULT_SIZE);
    
    ~FFMpegEncodeNode();
    
  protected:
    /* GenericNode */
    virtual Result doInit();
    virtual Result doInitOutput();
    virtual Result doActivate();
    virtual Result doDeactivate();
    virtual Result doStart();
    virtual Message* processBuffer(Buffer*);
    
    /* ITrackImpl */
    virtual Result started(const Interval& overall_duration);
    virtual Result startTrack(const string&);
    virtual Result endTrack();
    virtual Result finished();
    
    /* IFormatChangeImpl */
    //virtual Result setFormat(const Format&);

    /* IEncodeImpl */
    virtual void setQuality(const nmm_float&);
    virtual void setBitrate(const nmm_int32&);
    virtual nmm_float getQuality();
    virtual nmm_int32 getBitrate();
    
    /* IEncodeStatsImpl */
    virtual void sendFrameCount(const nmm_bool&);
    
  private:
    Result setSize(int width, int height);
    Result openCodec();
    
    void detectAllCodecs();
    void addCodec(const std::string& fourcc, int id);
  };

}

#include "nmm/nmm_suffix.hpp"

#endif //_NMM_FFMPEGENCODENODE_HPP_
