/* 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_AVIREADNODE_LINUX_HPP
#define NMM_AVIREADNODE_LINUX_HPP NMM_AVIREADNODE_LINUX_HPP

#include "nmm/nmm_prefix.hpp"

#include "nmm/multimedia/GenericSourceNode.hpp"
#include "nmm/multimedia/ISyncResetImpl.hpp"
#include "nmm/plugins/file/interfaces/ISourceFileHandlerImpl.hpp"
#include "nmm/plugins/file/interfaces/ISeekableImpl.hpp"
#include "nmm/plugins/interfaces/IProgressImpl.hpp"

#include "visibility.hpp"

// do forward declaration of needed structs from avilib/avilib.h
struct avi_t;

namespace NMM {
  
  /**
   * AVIReadNode 
   */
  class DLLEXPORT AVIReadNode :
    public GenericSourceNode,
    public ISyncResetImpl,
    public ISourceFileHandlerImpl,
    public ISeekableImpl,
    public IProgressImpl
  {
    
  private:
    int             av_pos;             ///< position of video in file * 2 (count video and audio)
    int             av_offset;          ///< to which position (audio + video) did we seek?
    int             read_size;          ///< how large is the video frame we read
    string          file_name;          ///< our input filename
    bool            seeked;             ///< was a seek handled shortly?
    bool            seek_backwards;     ///< seek backwards?
    bool            end_of_file;        ///< EOF reached?
    bool            begin_of_file;      ///< are we currently at the beginning of the file
    bool            all_at_the_beginning; ///< flag to decide wheter to send BufferLabel event
    bool            send_progress;      ///< should the node send progress information?
    bool            send_format;         ///< should we send a setFormat-Event?
    ThreadMutex     file_name_mutex;
    ThreadMutex     seek_mutex;
    avi_t*          avi_file;           ///< struct from avilib, contains file handle
    int             width;              ///< Width of Video Frames
    int             height;             ///< Height of Video Frames
    int             num_frames;         ///< Number of Video Frames
    double          frame_rate;         ///< Video Framerate
    int             int_frame_rate;     ///< internal Framerate, integer representation
    const int       frame_rate_base;    ///< constant between frame_rate and int_frame_rate
    char*           video_compressor;   ///< Video Compressor String
    int             audio_channels;     ///< Number of audio channels
    int             audio_bits;         ///< Number of audio bits
    int             audio_format;       ///< Audio format, see avilib.h for formats
    int             audio_rate;         ///< Audio samplerate
    int             audio_bytes;        ///< total number of audio bytes in the file
    int             audio_bitrate;      ///< audio bitrate
    int             is_key_frame;       ///< flag for information: is the current frame a key frame?
    int             aud_buf_size;       ///< Buffer size for audio buffers
    const int       vid_buf_bound;      ///< Upper Bound for size of most video frames
    int             buffers_before_progress;
    int             buffers_progress;
    Buffer*         __current_buffer;   ///< stores the buffer buffer pointer if an key frame event is send
    bool            valid_audio;        ///< indicates if we send the first buffer, used to mark the first audiotimstamp as valid
    size_t          filesize;
    
    int             divisor;            ///< used for dividing av_pos (which counts video and audio). 1 if file contains no audio, 2 if file contains audio.
    
    virtual Result doInit();
    virtual Result doInitOutput();
    
    virtual Message* processBuffer(Buffer *);   ///< standard produceBuffer
    
  protected:

    // ISourceFileHandler interface
    virtual void setFilename(const string& name);
    virtual nmm_uint64 getFilesize();
    
    // ISeekable interface
    virtual nmm_bool hasPercentSeek() const;
    virtual void seekPercent(const Rational& percent);
    virtual void seekPercentTo(const Rational& percent);
    virtual nmm_bool hasBytesSeek() const;
    virtual void seekBytes(const nmm_int64& offset);
    virtual void seekBytesTo(const nmm_uint64& bytes);
    virtual nmm_bool hasTimeSeek() const;
    virtual void seekTime(const Interval& interval);
    virtual void seekTimeTo(const Time& time);
    
    // ISyncReset interface
    virtual Result syncReset();

    // IProgress interface
    virtual void sendProgressInformation(const nmm_bool& in);
    virtual void setProgressInterval(const nmm_int32& buffers);

  public:

    AVIReadNode(const char* name = "AVIReadNode",
		StreamQueue::Mode = StreamQueue::MODE_SUSPEND,
		int = StreamQueue::DEFAULT_SIZE); ///< Constructor
    virtual ~AVIReadNode();                        ///< Destructor
  };
  
}

#include "nmm/nmm_suffix.hpp"

#endif 

