/*
#  $Id$
# -----------------------------------------------------------------------------
#  The part of 'VideoNEXT MediaClient SDK'
# -----------------------------------------------------------------------------
#  Author: Petrov Maxim, 03/04/2009
#  Edited by:
#  QA by:
#  Copyright: videoNEXT LLC
# -----------------------------------------------------------------------------
*/

#ifndef VN_VIDEOFRAMECONSUMER_H
#define VN_VIDEOFRAMECONSUMER_H


extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/cpu.h"
#include "libavutil/imgutils.h"
#include "libavutil/pixfmt.h"
}

#include "liveMedia.hh"
#include "c_ptr.h"
#include "FrameConsumer.h"
#include "StreamStats.h"

namespace videonext { namespace media {

class VideoFrameConsumer: public FrameConsumer
{
public:
    static VideoFrameConsumer* createNew(AdaptiveUsageEnvironment& env,
                                         AudioVideoPlaybackController *controller,
                                         unsigned bufferSize,
                                         unsigned decoderType,
                                         PIXEL_FORMAT preferredPixelFormat,
                                         StreamInfo *streamInfo,
                                         bool isVideoTranscoded);

    virtual bool init();
    virtual void clear();

    virtual void addData(unsigned char* data, unsigned dataSize,
                         const struct timeval &presentationTime,
                         bool parseOurHeader = true, const std::string* pObjectsData = NULL);

    virtual void addExtraData(unsigned char* data, unsigned dataSize);


    static int getFrameType(uint8_t *data, unsigned size, AVCodecID codec);

protected:
    VideoFrameConsumer(AdaptiveUsageEnvironment& env,
                       AudioVideoPlaybackController  *controller,
                       unsigned bufferSize,
                       unsigned decoderType,
                       PIXEL_FORMAT preferredPixelFormat,
                       StreamInfo *streamInfo,
                       bool isVideoTranscoded);
   // called only by createNew()

    virtual ~VideoFrameConsumer();

protected:

   bool initVideoDecoder();
   void destroyVideoDecoder();
   void reloadVideoDecoder();

   /**
    * Decode and display video frame
    * @param cpVideoFrame
    */
   virtual void playFrame(CPMediaFrame &, bool show);

   virtual void setFrameType(CPMediaFrame &);

   void onNewFrame(CPMediaFrame &cpMediaFrame, bool show);
   void onNewBrokenFrame(CPMediaFrame &cpMediaFrame, bool show);

private:

    uint8_t* findHeader(uint8_t* data, unsigned dataSize);

private:

   AVCodecContext *fCodecCtx;
   AVCodec *fCodec;
   AVFrame **fPicture;
   AVFrame **fPictureDecoded;
   AVPacket fVideoPacket;

   struct SwsContext *fSwsCtx;

   /* for locking avcodec_open/close calls */
   static Mutex fCodecMutex;

   PIXEL_FORMAT fPreferredPixelFormat;

   uint8_t *fH264Header;
   unsigned fH264HeaderSize;

   uint8_t *fH264SEI;
   unsigned fH264SEISize;

   bool fIsVideoTranscoded;

   //
   unsigned long fLastDecodedFrameNum;

   int pictWidth;
   int pictHeight;
   AVPixelFormat pixFmt;

   unsigned char* fExternalBuffer_;
   FRAME_BUFFERS_NUM fExternalBuffersNumber_;
   int fExternalBuffersPosition_;

private:
    unsigned char *fExtradata;
    unsigned fExtradataSize;

    unsigned char *fRecorderExtradata;
    unsigned fRecorderExtradataSize;

private:
    float fDisplayAspectRatio;

private:
    StreamStats *fStreamStats;
};

}}

#endif
