//------------------------------------------------------------------------------
//
//  Project:   Anonymizer
//
//             Brno University of Technology
//             Faculty of Information Technology
//
//------------------------------------------------------------------------------
//
//      This project was financially supported by project VG20102015006 funds
//           provided by Ministry of the Interior of the Czech republic.
//
//------------------------------------------------------------------------------
/*!

@file      avwriter.h
@brief     Header file
@details   Details
@authors   Martin Borek (mborekcz@gmail.com)
@authors   Filip Orsag (orsag@fit.vutbr.cz)
@date      2014-2015
@note      This project was supported by MV CR project VG20102015006.
@copyright BUT OPEN SOURCE LICENCE (see License.txt)

*/

#ifndef AVWRITER_H
#define AVWRITER_H

extern "C"{
	#include <ffmpeg/libavcodec/avcodec.h>
	#include <ffmpeg/libavformat/avformat.h>
	#include <ffmpeg/libswscale/swscale.h>

	#include <ffmpeg/libavutil/common.h>
	#include <ffmpeg/libavutil/imgutils.h>
	#include <ffmpeg/libavutil/mathematics.h>
	#include <ffmpeg/libavutil/samplefmt.h>


	#include <ffmpeg/libavutil/avassert.h>
	#include <ffmpeg/libavutil/channel_layout.h>
	#include <ffmpeg/libavutil/opt.h>
	#include <ffmpeg/libavutil/timestamp.h>
	#include <ffmpeg/libswresample/swresample.h>
}

#include "videoframe.h"

class AVWriter
{
public:
    AVWriter();
    ~AVWriter();

    /**
     * Initializes contexts, opens codecs and opens the output file for writing.
     * @param filename Output filename
     * @param inVideoStream Input video stream
     * @param inAudioStream Input audio stream
     * @param inFormatName Name of the input file format
     * @param inFileExtension Extension of the input file
     * @return True if initialization successful
     */
    bool initialize_output(std::string filename, AVStream const *inVideoStream, AVStream const *inAudioStream,
                           char const *inFormatName, std::string inFileExtension);

    /**
     * Correct closing of the output file.
     * @return  True if successful
     */
    bool close_output();

    /**
     * Writes the video frame to the output video stream.
     * @param frame Frame to be written
     * @return True if successful
     */
    bool write_video_frame(VideoFrame &frame);

    /**
     * Writes the audio packet to the output audio stream.
     * @param pkt Packet to be written
     * @return True if successful
     */
    bool write_audio_packet(AVPacket &pkt);

    /**
     * Writes all frames remaining in the encoder; emptying buffers.
     * @return True if successful
     */
    bool write_last_frames();

private:
    /**
     * Adds a new stream (either audio or video) for creating an output media file.
     * @param outputStream Output stream that is initialized by this function
     * @param inputStream Input stream; it's values are used for outputStream initialization
     * @return True if successful
     */
    bool add_stream(AVStream **outputStream, AVStream const *inputStream);

private:
    AVFormatContext *formatContext;
    AVStream *videoStream;
    AVStream *audioStream;

    const int outputFormat = AV_PIX_FMT_YUV420P;
};

#endif // AVWRITER_H
