/*
* Copyright(c) 2019 Intel Corporation
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at https://www.aomedia.org/license/software-license. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at https://www.aomedia.org/license/patent-license.
*/

#ifndef EbPictureDecision_h
#define EbPictureDecision_h

#include "EbDefinitions.h"
#include "EbPictureControlSet.h"
#include "EbSequenceControlSet.h"
#include "EbUtility.h"

/***************************************
 * Extern Function Declaration
 ***************************************/
EbErrorType  picture_decision_context_ctor(EbThreadContext   *thread_context_ptr,
                                           const EbEncHandle *enc_handle_ptr,
                                           uint8_t            scene_change_detection);
extern void *picture_decision_kernel(void *input_ptr);

void downsample_decimation_input_picture(PictureParentControlSet *pcs_ptr,
                                         EbPictureBufferDesc     *inputPaddedPicturePtr,
                                         EbPictureBufferDesc     *quarterDecimatedPicturePtr,
                                         EbPictureBufferDesc     *sixteenthDecimatedPicturePtr);

void pad_picture_to_multiple_of_min_blk_size_dimensions(SequenceControlSet  *scs_ptr,
                                                        EbPictureBufferDesc *input_picture_ptr);
void pad_picture_to_multiple_of_min_blk_size_dimensions_16bit(
    SequenceControlSet *scs_ptr, EbPictureBufferDesc *input_picture_ptr);
void picture_pre_processing_operations(PictureParentControlSet *pcs_ptr,
                                       SequenceControlSet      *scs_ptr);
void pad_picture_to_multiple_of_sb_dimensions(EbPictureBufferDesc *input_padded_picture_ptr);
void gathering_picture_statistics(SequenceControlSet *scs_ptr, PictureParentControlSet *pcs_ptr,
                                  EbPictureBufferDesc *input_padded_picture_ptr,
                                  EbPictureBufferDesc *sixteenth_decimated_picture_ptr);

void down_sample_chroma(EbPictureBufferDesc *input_picture_ptr,
                        EbPictureBufferDesc *outputPicturePtr);

Bool is_delayed_intra(PictureParentControlSet *pcs);

void svt_aom_set_dlf_controls(PictureParentControlSet *pcs_ptr, uint8_t dlf_level,
                              uint8_t bit_depth);

/**************************************
 * Context
 **************************************/
typedef struct PictureDecisionContext {
    EbDctor dctor;
    EbFifo *picture_analysis_results_input_fifo_ptr;
    EbFifo *picture_decision_results_output_fifo_ptr;
    EbFifo *me_fifo_ptr;

    Bool        reset_running_avg;
    int8_t      tf_motion_direction; // -1: invalid   0: horz  1: vert
    uint32_t ***prev_picture_histogram;
    uint64_t    prev_average_intensity_per_region[MAX_NUMBER_OF_REGIONS_IN_WIDTH]
                                              [MAX_NUMBER_OF_REGIONS_IN_HEIGHT];
    uint32_t **ahd_running_avg_cb;
    uint32_t **ahd_running_avg_cr;
    uint32_t **ahd_running_avg;
    Bool       is_scene_change_detected;
    int8_t     transition_detected; // -1: not computed
        // The signal transition_detected is set for only the RA case, and used to derive transition_present flag
        // If the scene change happens during a complete mini-GOP, then transition_present is set to 1
        // for only the next BASE. However, if the scene change happens during an incomplete mini-GOP
        // then transition_present is set to 1 for all P(s) until the next BASE as they would not take advantage of
        // the next BASE boost since they only use past reference frame(s)
        // When transition_present is set to 1, different action(s) will be taken to mimic an I_SLICE (decrease the QP, better INTRA search level,
        // shut depth-removal, ..). The QP action is not applied if a P.
    // Dynamic GOP
    uint32_t ttl_region_activity_cost[MAX_NUMBER_OF_REGIONS_IN_WIDTH]
                                     [MAX_NUMBER_OF_REGIONS_IN_HEIGHT];

    uint32_t total_number_of_mini_gops;

    uint32_t mini_gop_start_index[MINI_GOP_WINDOW_MAX_COUNT];
    uint32_t mini_gop_end_index[MINI_GOP_WINDOW_MAX_COUNT];
    uint32_t mini_gop_length[MINI_GOP_WINDOW_MAX_COUNT];
    uint32_t mini_gop_intra_count[MINI_GOP_WINDOW_MAX_COUNT];
    uint32_t mini_gop_idr_count[MINI_GOP_WINDOW_MAX_COUNT];
    uint32_t mini_gop_hierarchical_levels[MINI_GOP_WINDOW_MAX_COUNT];
    Bool     mini_gop_activity_array[MINI_GOP_MAX_COUNT];
    uint32_t mini_gop_region_activity_cost_array[MINI_GOP_MAX_COUNT][MAX_NUMBER_OF_REGIONS_IN_WIDTH]
                                                [MAX_NUMBER_OF_REGIONS_IN_HEIGHT];

    uint32_t mini_gop_group_faded_in_pictures_count[MINI_GOP_MAX_COUNT];
    uint32_t mini_gop_group_faded_out_pictures_count[MINI_GOP_MAX_COUNT];
    uint8_t  lay0_toggle; //3 way toggle 0->1->2
    uint8_t  lay1_toggle; //2 way toggle 0->1
    Bool mini_gop_toggle; //mini GOP toggling since last Key Frame  K-0-1-0-1-0-K-0-1-0-1-K-0-1.....
    uint8_t                  last_i_picture_sc_class0;
    uint8_t                  last_i_picture_sc_class1;
    uint8_t                  last_i_picture_sc_class2;
    uint64_t                 key_poc;
    uint8_t                  tf_level;
    uint32_t                 tf_pic_arr_cnt;
    PictureParentControlSet *tf_pic_array[1 << MAX_TEMPORAL_LAYERS];
    PictureParentControlSet *mg_pictures_array[1 << MAX_TEMPORAL_LAYERS];
    PictureParentControlSet *prev_delayed_intra; //Key frame or I of LDP short MG
    uint32_t                 mg_size; //number of active pictures in above array
    PictureParentControlSet *mg_pictures_array_disp_order[1 << MAX_TEMPORAL_LAYERS];

    int64_t mg_progress_id;

    int32_t last_i_noise_levels_log1p_fp16[MAX_MB_PLANE];
    double  last_i_noise_levels[MAX_MB_PLANE];

    // for switch frame feature
    uint32_t ref_order_hint[REF_FRAMES]; // spec 6.8.2
    uint64_t sframe_poc;
    int32_t  sframe_due; // The flag indicates whether the next ARF will be made an s-frame
} PictureDecisionContext;

#endif // EbPictureDecision_h
