/////////////////////////////////////////////////////////////////////////////
// Name:        mediatrc_ffmpeg.h
// Purpose:     FFMPEG Media Transcoder
// Author:      Alex Thuering
// Created:     26.04.2008
// RCS-ID:      $Id: mediatrc_ffmpeg.h,v 1.12 2009/06/15 17:59:16 ntalex Exp $
// Copyright:   (c) Alex Thuering
// Licence:     GPL
/////////////////////////////////////////////////////////////////////////////

#ifndef WX_FFMPEG_MEDIA_TRANSCODER_H
#define WX_FFMPEG_MEDIA_TRANSCODER_H

#include "mediatrc.h"
#include <stdint.h>
#include <math.h>

#define INT64_C(val) val##LL
#define UINT64_C(val) val##ULL
extern "C" {
#define __STDC_CONSTANT_MACROS
#define __STDC_LIMIT_MACROS
#ifdef HAVE_FFMPEG_AVUTIL_H
#include <avformat.h>
#include <swscale.h>
#else
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#endif
}

// select an input stream for an output stream
typedef struct AVStreamMap {
    int file_index;
    int stream_index;
    int sync_file_index;
    int sync_stream_index;
} AVStreamMap;

// select an input file for an output file
typedef struct AVMetaDataMap {
    int out_file;
    int in_file;
} AVMetaDataMap;

struct AVInputStream;
struct AVOutputStream;

#define MAX_FILES 20
#define MAX_STREAMS_ 20
#define CODEC_TYPE_COUNT (int) CODEC_TYPE_NB

class wxFfmpegMediaTranscoder : public wxMediaTranscoder {
public:
	wxFfmpegMediaTranscoder(int threadCount = 1);
	~wxFfmpegMediaTranscoder();
	/** Adds input file. */
	bool AddInputFile(const wxString& fileName, bool disableVideo = false,
			bool disableAudio = false, bool disableSubtitle = false);
	/** Sets output file and video/audio/subtitle formats. */
	bool SetOutputFile(const wxString& fileName, VideoFormat videoFormat, AudioFormat audioFormat,
			SubtitleFormat subtitleFormat, int videoBitrate = 6000, bool vbr = false,
			int audioBitrate = 224);
	/** Sets output file and video/audio/subtitle formats. */
	bool SetOutputFile(const wxString& fileName, VideoFormat videoFormat, wxArrayInt audioFormats,
			wxArrayInt subtitleFormats, int videoBitrate = 6000, bool vbr = false,
			int audioBitrate = 224);
	/** Starts transcoding. */
	bool Run(bool& canceled);
	/** Ends ttanscoding and closes all fiies. */
	void End();
	
private:
	void PrintError(const wxString& fileName, int err);
	bool AddVideoStream(AVFormatContext *oc, VideoFormat videoFormat, int bitrate, bool vbr);
	bool AddAudioStream(AVFormatContext *oc, AudioFormat audioFormat, int bitrate);
	bool AddSubtitleStream(AVFormatContext *oc, SubtitleFormat subtitleFormat);
	bool OutputPacket(AVInputStream *ist, int ist_index, AVOutputStream **ost_table,
			int nb_ostreams, const AVPacket *pkt, int bit_buffer_size, uint8_t* bit_buffer);
	bool WriteFrame(AVFormatContext *s, AVPacket *pkt, AVCodecContext *avctx,
			AVBitStreamFilterContext *bsfc);
	bool DoAudioOut(AVFormatContext *s, AVOutputStream *ost, AVInputStream *ist,
			unsigned char *buf, int size);
	bool DoVideoOut(AVFormatContext *s, AVOutputStream *ost, AVInputStream *ist,
			AVFrame *in_picture, int *frame_size, int bit_buffer_size, uint8_t* bit_buffer);
	bool DoSubtitleOut(AVFormatContext *s, AVOutputStream *ost, AVInputStream *ist,
			AVSubtitle *sub, int64_t pts);
	void PrintReport(AVFormatContext **output_files, AVOutputStream **ost_table,
			int nb_ostreams, int is_last_report);
    AVFormatContext *input_files[MAX_FILES];
    int64_t input_files_ts_offset[MAX_FILES];
	double input_files_ts_scale[MAX_FILES][MAX_STREAMS];
    int nb_input_files;

    AVFormatContext *output_files[MAX_FILES];
	AVCodec *output_codecs[MAX_FILES*MAX_STREAMS];
    int nb_output_files;
	int nb_ocodecs;

    AVStreamMap stream_maps[MAX_FILES*MAX_STREAMS];
	int nb_stream_maps;

    AVMetaDataMap meta_data_maps[MAX_FILES];
    int nb_meta_data_maps;

    int frame_width;
    int frame_height;
    float frame_aspect_ratio;
    PixelFormat frame_pix_fmt;
    SampleFormat audio_sample_fmt;
	int frame_padtop;
    int frame_padbottom;
    int frame_padleft;
    int frame_padright;
    int padcolor[3]; /* default to black */
    int frame_topBand;
    int frame_bottomBand;
    int frame_leftBand;
    int frame_rightBand;
    int max_frames[4];
    AVRational frame_rate;
    float video_qscale;
    uint16_t *intra_matrix;
    uint16_t *inter_matrix;
    const char *video_rc_override_string;
    int video_codec_tag;
    int same_quality;
    int do_deinterlace;
    int top_field_first;
    int me_threshold;
    int intra_dc_precision;
    int loop_input;
    int loop_output;
    int qp_hist;

    int intra_only;
    int audio_sample_rate;
    int64_t channel_layout;
    float audio_qscale;
    int audio_channels;
    int audio_codec_tag;
    char *audio_language;

    char *subtitle_language;
    int subtitle_codec_tag;

    float mux_preload;
    float mux_max_delay;

    //int64_t recording_time;
    int64_t start_time;
    int64_t rec_timestamp;
    int64_t input_ts_offset;
    int metadata_count;
    AVMetadataTag *metadata;
    int do_psnr;
    int do_pass;
    const char *pass_logfilename_prefix;
    int video_sync_method;
    int audio_sync_method;
    float audio_drift_threshold;
    int copy_ts;
    int opt_shortest; //
    int video_global_header;
    char *vstats_filename;
    FILE *vstats_file;
    int opt_programid;
    int copy_initial_nonkeyframes;

    int rate_emu;

    int  video_channel;
    char *video_standard;

    int audio_volume;

    int exit_on_error;
    int verbose;
    int thread_count;
    int q_pressed;
    int64_t video_size;
    int64_t audio_size;
    int64_t extra_size;
    int nb_frames_dup;
    int nb_frames_drop;
    int input_sync;
    uint64_t limit_filesize; //
	int force_fps;

    int pgmyuv_compatibility_hack;
    float dts_delta_threshold;

    unsigned int sws_flags;

    int64_t timer_start;

    AVBitStreamFilterContext *video_bitstream_filters;
    AVBitStreamFilterContext *audio_bitstream_filters;
    AVBitStreamFilterContext *subtitle_bitstream_filters;
    AVBitStreamFilterContext *bitstream_filters[MAX_FILES][MAX_STREAMS_];
};

#endif // WX_FFMPEG_MEDIA_TRANSCODER_H
