CWG-E023 (SDP extension)

Extend SDP from intra frames to inter frames.
diff --git a/apps/aomenc.c b/apps/aomenc.c
index feb7a46..5e5a200 100644
--- a/apps/aomenc.c
+++ b/apps/aomenc.c
@@ -39,6 +39,9 @@
 #include "common/stream_iter.h"
 #include "common/tools_common.h"
 #include "common/warnings.h"
+#if CONFIG_EXTENDED_SDP
+#include "av1/common/blockd.h"
+#endif  // CONFIG_EXTENDED_SDP
 
 #if CONFIG_WEBM_IO
 #include "common/webmenc.h"
diff --git a/av1/common/av1_common_int.h b/av1/common/av1_common_int.h
index 5183035..54cf83a 100644
--- a/av1/common/av1_common_int.h
+++ b/av1/common/av1_common_int.h
@@ -1967,6 +1967,16 @@
          cm->current_frame.frame_type == INTRA_ONLY_FRAME;
 }
 
+#if CONFIG_EXTENDED_SDP
+// Check whether this is chroma component of an intra region in inter frame
+static INLINE int is_inter_sdp_chroma(const AV1_COMMON *const cm,
+                                      REGION_TYPE cur_region_type,
+                                      TREE_TYPE cur_tree_type) {
+  return !frame_is_intra_only(cm) && cur_region_type == INTRA_REGION &&
+         cur_tree_type == CHROMA_PART;
+}
+#endif  // CONFIG_EXTENDED_SDP
+
 static INLINE int frame_is_sframe(const AV1_COMMON *cm) {
   return cm->current_frame.frame_type == S_FRAME;
 }
@@ -2575,6 +2585,24 @@
 #endif  // CONFIG_EXT_RECUR_PARTITIONS
 }
 
+#if CONFIG_EXTENDED_SDP
+static INLINE int get_intra_region_context(BLOCK_SIZE bsize) {
+  const int width = block_size_wide[bsize];
+  const int height = block_size_high[bsize];
+  const int num_samples = width * height;
+  if (num_samples <= 64)
+    return 0;
+  else if (num_samples <= 128)
+    return 1;
+  else if (num_samples <= 256)
+    return 2;
+  else if (num_samples <= 512)
+    return 3;
+  else
+    return 4;
+}
+#endif  // CONFIG_EXTENDED_SDP
+
 #if CONFIG_BLOCK_256
 /*!\brief Returns the context used by \ref PARTITION_SPLIT. */
 static INLINE int square_split_context(const MACROBLOCKD *xd, int mi_row,
@@ -2672,6 +2700,7 @@
   }
   av1_zero_array(above_contexts->partition[0][tile_row] + mi_col_start,
                  aligned_width);
+
   if (num_planes > 1) {
     if (above_contexts->partition[1][tile_row] &&
         above_contexts->partition[2][tile_row]) {
diff --git a/av1/common/av1_loopfilter.c b/av1/common/av1_loopfilter.c
index 2c0fbc2..17dcc75 100644
--- a/av1/common/av1_loopfilter.c
+++ b/av1/common/av1_loopfilter.c
@@ -521,6 +521,8 @@
   params->filter_length = 0;
 
   TREE_TYPE tree_type = SHARED_PART;
+
+#if !CONFIG_EXTENDED_SDP
   const bool is_sdp_eligible = frame_is_intra_only(cm) &&
                                !cm->seq_params.monochrome &&
                                cm->seq_params.enable_sdp;
@@ -528,6 +530,7 @@
     tree_type = (plane == AOM_PLANE_Y) ? LUMA_PART : CHROMA_PART;
   }
   const int plane_type = is_sdp_eligible && plane > 0;
+#endif  // !CONFIG_EXTENDED_SDP
 
   // no deblocking is required
   const uint32_t width = plane_ptr->dst.width;
@@ -553,6 +556,16 @@
   // it not set up.
   if (mbmi == NULL) return TX_INVALID;
 
+#if CONFIG_EXTENDED_SDP
+  const bool is_sdp_eligible = cm->seq_params.enable_sdp &&
+                               !cm->seq_params.monochrome &&
+                               mbmi->region_type == INTRA_REGION;
+  if (is_sdp_eligible) {
+    tree_type = (plane == AOM_PLANE_Y) ? LUMA_PART : CHROMA_PART;
+  }
+  const int plane_type = is_sdp_eligible && plane > 0;
+#endif  // CONFIG_EXTENDED_SDP
+
 #if CONFIG_LF_SUB_PU
   TX_SIZE ts = get_transform_size(xd, mi[0], edge_dir, mi_row, mi_col, plane,
                                   tree_type, plane_ptr);
@@ -595,9 +608,28 @@
           const int pv_col =
               (VERT_EDGE == edge_dir) ? (mi_col - (1 << scale_horz)) : (mi_col);
 
+#if CONFIG_EXTENDED_SDP
+          TREE_TYPE prev_tree_type = SHARED_PART;
+          const bool is_prev_sdp_eligible =
+              cm->seq_params.enable_sdp && !cm->seq_params.monochrome &&
+              mi_prev->region_type == INTRA_REGION;
+          // With SDP in inter frames, the tree type of current block can be
+          // different with previous block, so we can't copy the tree type of
+          // current block to previous block, and we need to fetch the tree type
+          // of a previous block.
+          if (is_prev_sdp_eligible) {
+            prev_tree_type = (plane == AOM_PLANE_Y) ? LUMA_PART : CHROMA_PART;
+          }
+          const TX_SIZE pv_ts =
+              get_transform_size(xd, mi_prev, edge_dir, pv_row, pv_col, plane,
+                                 prev_tree_type, plane_ptr);
+#else
+
           const TX_SIZE pv_ts =
               get_transform_size(xd, mi_prev, edge_dir, pv_row, pv_col, plane,
                                  tree_type, plane_ptr);
+#endif  // CONFIG_EXTENDED_SDP
+
           const uint32_t pv_q =
               av1_get_filter_q(&cm->lf_info, edge_dir, plane, mi_prev);
           const uint32_t pv_side =
diff --git a/av1/common/blockd.h b/av1/common/blockd.h
index 204d7c4..835d34a 100644
--- a/av1/common/blockd.h
+++ b/av1/common/blockd.h
@@ -430,6 +430,10 @@
   /*! \brief The partition type of the current coding block. */
   PARTITION_TYPE partition;
   /*! \brief The prediction mode used */
+#if CONFIG_EXTENDED_SDP
+  /*! \brief The region type used for the current block. */
+  REGION_TYPE region_type;
+#endif  // CONFIG_EXTENDED_SDP
   PREDICTION_MODE mode;
   /*! \brief The JMVD scaling mode for the current coding block. The supported
    *  scale modes for JOINT_NEWMV mode is 0, 1, 2, 3, and 4. The supported scale
@@ -746,6 +750,12 @@
   struct PARTITION_TREE *sub_tree[4];
   /*! \brief The partition type used to split the current block. */
   PARTITION_TYPE partition;
+#if CONFIG_EXTENDED_SDP
+  /*! \brief The region type used for the current block. */
+  REGION_TYPE region_type;
+  /*! \brief Whethe SDP is allowed for one block in inter frame. */
+  int inter_sdp_allowed_flag;
+#endif  // CONFIG_EXTENDED_SDP
   /*! \brief Block size of the current block. */
   BLOCK_SIZE bsize;
   /*! \brief Whether the chroma block info is ready. */
@@ -1363,6 +1373,61 @@
   info->bsize_base = bsize;
 }
 
+#if CONFIG_EXTENDED_SDP
+static INLINE int is_bsize_allowed_for_inter_sdp(BLOCK_SIZE bsize,
+                                                 PARTITION_TYPE partition) {
+  const int bw = block_size_wide[bsize];
+  const int bh = block_size_high[bsize];
+  return bw <= 32 && bh <= 32 && bw >= 8 && bh >= 8 &&
+         partition < PARTITION_HORZ_4A;
+}
+// Decide whether SDP is allowed for one block in inter frame.
+static INLINE int is_inter_sdp_allowed(BLOCK_SIZE parent_bsize,
+                                       PARTITION_TYPE parent_partition) {
+  const int bw = block_size_wide[parent_bsize];
+  const int bh = block_size_high[parent_bsize];
+  // Check if block width/height is less than 4.
+  const int bw_gt_4 = bw > 4;
+  const int bh_gt_4 = bh > 4;
+  // Check if half block width/height is less than 8.
+  const int hbw_gt_4 = bw > 8;
+  const int hbh_gt_4 = bh > 8;
+#if CONFIG_EXT_RECUR_PARTITIONS
+  // Check if quarter block width/height is less than 16.
+  const int qbw_gt_4 = bw > 16;
+  const int qbh_gt_4 = bh > 16;
+#endif  // !CONFIG_UNEVEN_4WAY || CONFIG_EXT_RECUR_PARTITIONS
+  // Check if one-eighth block width/height is less than 32.
+  const int ebw_gt_4 = bw > 32;
+  const int ebh_gt_4 = bh > 32;
+  switch (parent_partition) {
+    case PARTITION_NONE: return 1;
+    case PARTITION_HORZ: return bw_gt_4 && hbh_gt_4;
+    case PARTITION_VERT: return hbw_gt_4 && bh_gt_4;
+    case PARTITION_SPLIT: return hbw_gt_4 && hbh_gt_4;
+#if CONFIG_EXT_RECUR_PARTITIONS
+    case PARTITION_HORZ_4A:
+    case PARTITION_HORZ_4B: return bw_gt_4 && ebh_gt_4;
+    case PARTITION_VERT_4A:
+    case PARTITION_VERT_4B: return ebw_gt_4 && bh_gt_4;
+    case PARTITION_HORZ_3: return hbw_gt_4 && qbh_gt_4;
+    case PARTITION_VERT_3: return qbw_gt_4 && hbh_gt_4;
+#else   // CONFIG_EXT_RECUR_PARTITIONS
+    case PARTITION_HORZ_A:
+    case PARTITION_HORZ_B:
+    case PARTITION_VERT_A:
+    case PARTITION_VERT_B: return hbw_less_than_4 || hbh_less_than_4;
+    case PARTITION_HORZ_4: return bw_less_than_4 || qbh_less_than_4;
+    case PARTITION_VERT_4: return qbw_less_than_4 || bh_less_than_4;
+#endif  // CONFIG_EXT_RECUR_PARTITIONS
+    default:
+      assert(0 && "Invalid partition type!");
+      return 0;
+      break;
+  }
+}
+#endif  // CONFIG_EXTENDED_SDP
+
 // Decide whether a block needs coding multiple chroma coding blocks in it at
 // once to get around sub-4x4 coding.
 static INLINE int have_nz_chroma_ref_offset(BLOCK_SIZE bsize,
@@ -2334,6 +2399,7 @@
    * This is a pointer into 'left_txfm_context_buffer'.
    */
   TXFM_CONTEXT *left_txfm_context;
+
   /*!
    * left_txfm_context_buffer[i] is the left transform context for ith mi_row
    * in this *superblock*.
diff --git a/av1/common/entropy.c b/av1/common/entropy.c
index 85b7241..5c8d60a 100644
--- a/av1/common/entropy.c
+++ b/av1/common/entropy.c
@@ -387,6 +387,12 @@
   RESET_CDF_COUNTER(fc->uv_mode_cdf[1], UV_INTRA_MODES);
 #endif  // CONFIG_UV_CFL
 
+#if CONFIG_EXTENDED_SDP
+  for (int i = 0; i < INTER_SDP_BSIZE_GROUP; i++) {
+    RESET_CDF_COUNTER(fc->region_type_cdf[i], REGION_TYPES);
+  }
+#endif  // CONFIG_EXTENDED_SDP
+
 #if CONFIG_EXT_RECUR_PARTITIONS
   for (int plane_index = 0; plane_index < PARTITION_STRUCTURE_NUM;
        plane_index++) {
diff --git a/av1/common/entropymode.c b/av1/common/entropymode.c
index 99629fb..279bfad 100644
--- a/av1/common/entropymode.c
+++ b/av1/common/entropymode.c
@@ -454,6 +454,22 @@
                     9875, 10521, 29048) } }
     };
 #endif  // CONFIG_AIMC
+
+#if CONFIG_EXTENDED_SDP
+static aom_cdf_prob default_region_type_cdf[INTER_SDP_BSIZE_GROUP]
+                                           [CDF_SIZE(REGION_TYPES)] = {
+                                             // w * h <= 64
+                                             { AOM_CDF2(16384), 0 },
+                                             // w * h <= 128
+                                             { AOM_CDF2(16384), 0 },
+                                             // w * h <= 256
+                                             { AOM_CDF2(16384), 0 },
+                                             // w * h <= 512
+                                             { AOM_CDF2(16384), 0 },
+                                             // w * h <= 1024
+                                             { AOM_CDF2(16384), 0 }
+                                           };
+#endif  // CONFIG_EXTENDED_SDP
 #if CONFIG_EXT_RECUR_PARTITIONS
 // clang-format off
 #if CONFIG_FLEX_PARTITION
@@ -7324,6 +7340,9 @@
   av1_copy(fc->filter_dir_cdf, default_filter_dir_cdf);
 #endif  // CONFIG_ENABLE_MHCCP
   av1_copy(fc->switchable_interp_cdf, default_switchable_interp_cdf);
+#if CONFIG_EXTENDED_SDP
+  av1_copy(fc->region_type_cdf, default_region_type_cdf);
+#endif  // CONFIG_EXTENDED_SDP
 #if CONFIG_EXT_RECUR_PARTITIONS
   av1_copy(fc->do_split_cdf, default_do_split_cdf);
 #if CONFIG_BLOCK_256
diff --git a/av1/common/entropymode.h b/av1/common/entropymode.h
index f8c15e4..1e8de90 100644
--- a/av1/common/entropymode.h
+++ b/av1/common/entropymode.h
@@ -537,6 +537,10 @@
 #endif  // CONFIG_BLOCK_256
   aom_cdf_prob rect_type_cdf[PARTITION_STRUCTURE_NUM][PARTITION_CONTEXTS]
                             [CDF_SIZE(2)];
+#if CONFIG_EXTENDED_SDP
+  aom_cdf_prob region_type_cdf[INTER_SDP_BSIZE_GROUP][CDF_SIZE(REGION_TYPES)];
+#endif  // CONFIG_EXTENDED_SDP
+
   aom_cdf_prob do_ext_partition_cdf[PARTITION_STRUCTURE_NUM][NUM_RECT_PARTS]
                                    [PARTITION_CONTEXTS][CDF_SIZE(2)];
   aom_cdf_prob do_uneven_4way_partition_cdf[PARTITION_STRUCTURE_NUM]
diff --git a/av1/common/enums.h b/av1/common/enums.h
index 3fdca21..a959da6 100644
--- a/av1/common/enums.h
+++ b/av1/common/enums.h
@@ -355,6 +355,14 @@
   TREES_TYPES,
 } UENUM1BYTE(TREE_TYPE);
 
+#if CONFIG_EXTENDED_SDP
+enum {
+  INTRA_REGION = 0,
+  MIXED_INTER_INTRA_REGION = 1,
+  REGION_TYPES = 2,
+} UENUM1BYTE(REGION_TYPE);
+#endif  // CONFIG_EXTENDED_SDP
+
 #if CONFIG_BLOCK_256
 // 4X4, 8X8, 16X16, 32X32, 64X64, 128X128, 256X256
 #define SQR_BLOCK_SIZES 7
@@ -479,6 +487,13 @@
 #define PARTITION_BLOCK_SIZES 5
 #endif  // CONFIG_EXT_RECUR_PARTITIONS
 
+#if CONFIG_EXTENDED_SDP
+// Extended SDP is only allowed for block samples >= 64 and <= 1024. The allowed
+// block size group is 64, 128, 256, 512, 1024, so the number of block size
+// group is 5 in total.
+#define INTER_SDP_BSIZE_GROUP 5
+#endif  // CONFIG_EXTENDED_SDP
+
 #define PARTITION_CONTEXTS (PARTITION_BLOCK_SIZES * PARTITION_PLOFFSET)
 
 // block transform size
@@ -1146,6 +1161,10 @@
 #endif  // CONFIG_NEW_TX_PARTITION
 typedef uint16_t TXFM_CONTEXT;
 
+#if CONFIG_EXTENDED_SDP
+typedef uint8_t INTRA_REGION_CONTEXT;
+#endif  // CONFIG_EXTENDED_SDP
+
 #define TIP_CONTEXTS 3
 
 #define INTER_REFS_PER_FRAME 7
diff --git a/av1/common/reconintra.h b/av1/common/reconintra.h
index 8f10cf3..16a5c27 100644
--- a/av1/common/reconintra.h
+++ b/av1/common/reconintra.h
@@ -99,12 +99,25 @@
   return bsize >= BLOCK_8X8;
 }
 
-static INLINE int av1_allow_intrabc(const AV1_COMMON *const cm) {
+static INLINE int av1_allow_intrabc(const AV1_COMMON *const cm,
+                                    const MACROBLOCKD *const xd) {
+#if CONFIG_EXTENDED_SDP
+  int cur_region_type = MIXED_INTER_INTRA_REGION;
+  if (xd->mi != NULL) cur_region_type = xd->mi[0]->region_type;
+#endif
 #if CONFIG_IBC_SR_EXT
   return (frame_is_intra_only(cm) || cm->features.allow_local_intrabc) &&
+#if CONFIG_EXTENDED_SDP
+         xd->tree_type != CHROMA_PART &&
+         (frame_is_intra_only(cm) || cur_region_type != INTRA_REGION) &&
+#endif  // CONFIG_EXTENDED_SDP
          cm->features.allow_screen_content_tools && cm->features.allow_intrabc;
 #else
   return frame_is_intra_only(cm) && cm->features.allow_screen_content_tools &&
+#if CONFIG_EXTENDED_SDP
+         xd->tree_type != CHROMA_PART &&
+         xd->mi[0]->region_type != INTRA_REGION &&
+#endif  // CONFIG_EXTENDED_SDP
          cm->features.allow_intrabc;
 #endif  // CONFIG_IBC_SR_EXT
 }
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 9662d7d..c54b4c6 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -1252,6 +1252,10 @@
   set_offsets(cm, xd, bsize, mi_row, mi_col, bw, bh, x_mis, y_mis, parent,
               index);
   xd->mi[0]->partition = partition;
+#if CONFIG_EXTENDED_SDP
+  // set region_type for each mbmi
+  xd->mi[0]->region_type = parent->region_type;
+#endif  // CONFIG_EXTENDED_SDP
   av1_read_mode_info(pbi, dcb, r, x_mis, y_mis);
 
 #if CONFIG_EXT_RECUR_PARTITIONS
@@ -1354,7 +1358,7 @@
 
 #if CONFIG_MORPH_PRED
   if (mbmi->morph_pred) {
-    assert(av1_allow_intrabc(cm));
+    assert(av1_allow_intrabc(cm, xd));
     assert(is_intrabc_block(mbmi, xd->tree_type));
     av1_build_morph_pred(cm, xd, bsize, mi_row, mi_col);
   }
@@ -2295,6 +2299,7 @@
   AV1_COMMON *cm = &pbi->common;
   const int num_planes = av1_num_planes(cm);
   MB_MODE_INFO *mbmi = xd->mi[0];
+
   int inter_block_tx = is_inter_block(mbmi, xd->tree_type) ||
                        is_intrabc_block(mbmi, xd->tree_type);
   if (xd->tree_type != CHROMA_PART) {
@@ -2711,6 +2716,18 @@
                                                      parse_decode_block };
   const int is_sb_root = bsize == cm->sb_size;
 
+#if CONFIG_EXTENDED_SDP
+  if (is_sb_root) {
+    if (!frame_is_intra_only(cm)) {
+      ptree->region_type = MIXED_INTER_INTRA_REGION;
+      ptree->inter_sdp_allowed_flag = 1;
+    } else {
+      ptree->region_type = INTRA_REGION;
+      ptree->inter_sdp_allowed_flag = 0;
+    }
+  }
+#endif  // CONFIG_EXTENDED_SDP
+
   if (parse_decode_flag & 1) {
     if (is_sb_root) {
       set_sb_mv_precision(sbi, pbi);
@@ -2767,6 +2784,30 @@
 
     ptree->partition = partition;
 
+#if CONFIG_EXTENDED_SDP
+    if (!is_sb_root && parent) {
+      if (parent->inter_sdp_allowed_flag == 1)
+        ptree->inter_sdp_allowed_flag =
+            is_inter_sdp_allowed(parent->bsize, parent->partition);
+      else
+        ptree->inter_sdp_allowed_flag = 0;
+      if (!frame_is_intra_only(cm) && ptree->partition &&
+          parent->region_type != INTRA_REGION &&
+          ptree->inter_sdp_allowed_flag &&
+          is_bsize_allowed_for_inter_sdp(bsize, ptree->partition)) {
+        const int ctx = get_intra_region_context(bsize);
+        ptree->region_type =
+            aom_read_symbol(reader, xd->tile_ctx->region_type_cdf[ctx],
+                            REGION_TYPES, ACCT_INFO("region_type"));
+        if (ptree->region_type == INTRA_REGION) xd->tree_type = LUMA_PART;
+      } else if (!frame_is_intra_only(cm)) {
+        ptree->region_type = parent->region_type;
+      } else {
+        ptree->region_type = INTRA_REGION;
+      }
+    }
+#endif  // CONFIG_EXTENDED_SDP
+
     switch (partition) {
 #if CONFIG_EXT_RECUR_PARTITIONS
       case PARTITION_HORZ_4A:
@@ -3031,6 +3072,21 @@
     default: assert(0 && "Invalid partition type");
   }
 
+#if CONFIG_EXTENDED_SDP
+  PARTITION_TREE *parent = ptree->parent;
+  if (!is_sb_root && parent) {
+    if (!frame_is_intra_only(cm) && !cm->seq_params.monochrome &&
+        ptree->partition && parent->region_type != INTRA_REGION &&
+        ptree->region_type == INTRA_REGION) {
+      // decode chroma part in one intra region
+      xd->tree_type = CHROMA_PART;
+      DEC_BLOCK(mi_row, mi_col, bsize, 0);
+      // reset back to shared part
+      xd->tree_type = SHARED_PART;
+    }
+  }
+#endif  // CONFIG_EXTENDED_SDP
+
 #undef DEC_PARTITION
 #undef DEC_BLOCK
 #undef DEC_BLOCK_EPT_ARG
@@ -8411,7 +8467,7 @@
       (uint32_t)aom_rb_bytes_read(rb);  // Size of the uncompressed header
   YV12_BUFFER_CONFIG *new_fb = &cm->cur_frame->buf;
   xd->cur_buf = new_fb;
-  if (av1_allow_intrabc(cm) && xd->tree_type != CHROMA_PART) {
+  if (av1_allow_intrabc(cm, xd) && xd->tree_type != CHROMA_PART) {
     av1_setup_scale_factors_for_frame(
         &cm->sf_identity, xd->cur_buf->y_crop_width, xd->cur_buf->y_crop_height,
         xd->cur_buf->y_crop_width, xd->cur_buf->y_crop_height);
diff --git a/av1/decoder/decodemv.c b/av1/decoder/decodemv.c
index 62d2ae1..af72c4e 100644
--- a/av1/decoder/decodemv.c
+++ b/av1/decoder/decodemv.c
@@ -888,7 +888,10 @@
                                  aom_reader *r, int skip) {
   struct segmentation *const seg = &cm->seg;
   if (!seg->enabled) return 0;  // Default for disabled segmentation
-  assert(seg->update_map && !seg->temporal_update);
+#if CONFIG_EXTENDED_SDP
+  if (frame_is_intra_only(cm))
+#endif  // CONFIG_EXTENDED_SDP
+    assert(seg->update_map && !seg->temporal_update);
 
   const CommonModeInfoParams *const mi_params = &cm->mi_params;
   const int mi_row = xd->mi_row;
@@ -1888,7 +1891,11 @@
 
   FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
 
-  if (seg->segid_preskip)
+  if (seg->segid_preskip
+#if CONFIG_EXTENDED_SDP
+      && !(!frame_is_intra_only(cm) && xd->tree_type == CHROMA_PART)
+#endif  // CONFIG_EXTENDED_SDP
+  )
     mbmi->segment_id = read_intra_segment_id(cm, xd, bsize, r, 0);
 
 #if CONFIG_SKIP_MODE_ENHANCEMENT
@@ -1899,7 +1906,7 @@
 #endif  // CONFIG_MORPH_PRED
 
 #if CONFIG_SKIP_TXFM_OPT
-  if (av1_allow_intrabc(cm) && xd->tree_type != CHROMA_PART) {
+  if (av1_allow_intrabc(cm, xd) && xd->tree_type != CHROMA_PART) {
 #if CONFIG_NEW_CONTEXT_MODELING
     mbmi->use_intrabc[0] = 0;
     mbmi->use_intrabc[1] = 0;
@@ -1923,10 +1930,18 @@
       read_skip_txfm(cm, xd, mbmi->segment_id, r);
 #endif  // CONFIG_SKIP_TXFM_OPT
 
-  if (!seg->segid_preskip)
+  if (!seg->segid_preskip
+#if CONFIG_EXTENDED_SDP
+      && !(!frame_is_intra_only(cm) && xd->tree_type == CHROMA_PART)
+#endif  // CONFIG_EXTENDED_SDP
+  )
     mbmi->segment_id = read_intra_segment_id(
         cm, xd, bsize, r, mbmi->skip_txfm[xd->tree_type == CHROMA_PART]);
 
+#if CONFIG_EXTENDED_SDP
+  mbmi->seg_id_predicted = 0;
+#endif  // CONFIG_EXTENDED_SDP
+
   if (xd->tree_type != CHROMA_PART) read_cdef(cm, r, xd);
 
 #if CONFIG_CCSO
@@ -1958,7 +1973,7 @@
   xd->left_txfm_context =
       xd->left_txfm_context_buffer + (mi_row & MAX_MIB_MASK);
 #endif  // !CONFIG_TX_PARTITION_CTX
-  if (av1_allow_intrabc(cm) && xd->tree_type != CHROMA_PART) {
+  if (av1_allow_intrabc(cm, xd) && xd->tree_type != CHROMA_PART) {
     read_intrabc_info(cm, dcb, r);
     if (is_intrabc_block(mbmi, xd->tree_type)) {
 #if CONFIG_LOSSLESS_DPCM
@@ -4309,7 +4324,6 @@
 #endif  // CONFIG_REFINEMV
 
   mbmi->segment_id = read_inter_segment_id(cm, xd, 1, r);
-
   mbmi->skip_mode = read_skip_mode(cm, xd, mbmi->segment_id, r);
 
   mbmi->fsc_mode[PLANE_TYPE_Y] = 0;
@@ -4336,7 +4350,8 @@
   }
 
 #if CONFIG_IBC_SR_EXT
-  if (!inter_block && av1_allow_intrabc(cm) && xd->tree_type != CHROMA_PART) {
+  if (!inter_block && av1_allow_intrabc(cm, xd) &&
+      xd->tree_type != CHROMA_PART) {
 #if CONFIG_NEW_CONTEXT_MODELING
     mbmi->use_intrabc[0] = 0;
     mbmi->use_intrabc[1] = 0;
@@ -4408,7 +4423,8 @@
 #endif  // !CONFIG_TX_PARTITION_CTX
 
 #if CONFIG_IBC_SR_EXT
-  if (!inter_block && av1_allow_intrabc(cm) && xd->tree_type != CHROMA_PART) {
+  if (!inter_block && av1_allow_intrabc(cm, xd) &&
+      xd->tree_type != CHROMA_PART) {
     mbmi->ref_frame[0] = INTRA_FRAME;
     mbmi->ref_frame[1] = NONE_FRAME;
     mbmi->palette_mode_info.palette_size[0] = 0;
@@ -4465,7 +4481,11 @@
   if (xd->tree_type == SHARED_PART)
     mi->sb_type[PLANE_TYPE_UV] = mi->sb_type[PLANE_TYPE_Y];
 
-  if (frame_is_intra_only(cm)) {
+  if (frame_is_intra_only(cm)
+#if CONFIG_EXTENDED_SDP
+      || mi->region_type == INTRA_REGION
+#endif  // CONFIG_EXTENDED_SDP
+  ) {
     read_intra_frame_mode_info(cm, dcb, r);
 #if CONFIG_IBC_BV_IMPROVEMENT
     if (cm->seq_params.enable_refmvbank) {
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 4e82142..68a55ec 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -2410,7 +2410,6 @@
   int ref;
 
   write_inter_segment_id(cpi, w, seg, segp, 0, 1);
-
   write_skip_mode(cm, xd, segment_id, mbmi, w);
 
 #if CONFIG_SKIP_TXFM_OPT
@@ -2418,7 +2417,8 @@
     write_is_inter(cm, xd, mbmi->segment_id, w, is_inter);
 
 #if CONFIG_IBC_SR_EXT
-    if (!is_inter && av1_allow_intrabc(cm) && xd->tree_type != CHROMA_PART) {
+    if (!is_inter && av1_allow_intrabc(cm, xd) &&
+        xd->tree_type != CHROMA_PART) {
       const int use_intrabc = is_intrabc_block(mbmi, xd->tree_type);
       if (xd->tree_type == CHROMA_PART) assert(use_intrabc == 0);
 #if CONFIG_NEW_CONTEXT_MODELING
@@ -2517,7 +2517,7 @@
 #endif  // !CONFIG_SKIP_TXFM_OPT
 
 #if CONFIG_IBC_SR_EXT
-  if (!is_inter && av1_allow_intrabc(cm) && xd->tree_type != CHROMA_PART) {
+  if (!is_inter && av1_allow_intrabc(cm, xd) && xd->tree_type != CHROMA_PART) {
     write_intrabc_info(
 #if CONFIG_IBC_BV_IMPROVEMENT && CONFIG_IBC_MAX_DRL
         cm->features.max_bvp_drl_bits,
@@ -3101,11 +3101,15 @@
   struct segmentation_probs *const segp = &ec_ctx->seg;
   const MB_MODE_INFO *const mbmi = xd->mi[0];
 
-  if (seg->segid_preskip && seg->update_map)
+  if (seg->segid_preskip && seg->update_map
+#if CONFIG_EXTENDED_SDP
+      && !(!frame_is_intra_only(cm) && xd->tree_type == CHROMA_PART)
+#endif  // CONFIG_EXTENDED_SDP
+  )
     write_segment_id(cpi, mbmi, w, seg, segp, 0);
 
 #if CONFIG_SKIP_TXFM_OPT
-  if (av1_allow_intrabc(cm) && xd->tree_type != CHROMA_PART) {
+  if (av1_allow_intrabc(cm, xd) && xd->tree_type != CHROMA_PART) {
     const int use_intrabc = is_intrabc_block(mbmi, xd->tree_type);
     if (xd->tree_type == CHROMA_PART) assert(use_intrabc == 0);
 #if CONFIG_NEW_CONTEXT_MODELING
@@ -3123,7 +3127,11 @@
 #else
   const int skip = write_skip(cm, xd, mbmi->segment_id, mbmi, w);
 #endif  // CONFIG_SKIP_TXFM_OPT
-  if (!seg->segid_preskip && seg->update_map)
+  if (!seg->segid_preskip && seg->update_map
+#if CONFIG_EXTENDED_SDP
+      && !(!frame_is_intra_only(cm) && xd->tree_type == CHROMA_PART)
+#endif  // CONFIG_EXTENDED_SDP
+  )
     write_segment_id(cpi, mbmi, w, seg, segp, skip);
 
   if (xd->tree_type != CHROMA_PART) write_cdef(cm, xd, w, skip);
@@ -3140,8 +3148,7 @@
 #endif
 
   write_delta_q_params(cpi, skip, w);
-
-  if (av1_allow_intrabc(cm) && xd->tree_type != CHROMA_PART) {
+  if (av1_allow_intrabc(cm, xd) && xd->tree_type != CHROMA_PART) {
     write_intrabc_info(
 #if CONFIG_IBC_BV_IMPROVEMENT && CONFIG_IBC_MAX_DRL
         cm->features.max_bvp_drl_bits,
@@ -3252,7 +3259,11 @@
   MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;
   MB_MODE_INFO *m = xd->mi[0];
 
-  if (frame_is_intra_only(cm)) {
+  if (frame_is_intra_only(cm)
+#if CONFIG_EXTENDED_SDP
+      || m->region_type == INTRA_REGION
+#endif  // CONFIG_EXTENDED_SDP
+  ) {
     write_mb_modes_kf(cpi, xd, cpi->td.mb.mbmi_ext_frame, w);
   } else {
     // has_subpel_mv_component needs the ref frame buffers set up to look
@@ -3713,6 +3724,21 @@
 #else
   write_partition(cm, xd, mi_row, mi_col, partition, bsize, w);
 #endif  // CONFIG_EXT_RECUR_PARTITIONS
+#if CONFIG_EXTENDED_SDP
+  const int is_sb_root = bsize == cm->sb_size;
+  PARTITION_TREE *parent = ptree->parent;
+  if (!is_sb_root && !frame_is_intra_only(cm) && parent && partition &&
+      parent->region_type != INTRA_REGION && ptree->inter_sdp_allowed_flag &&
+      is_bsize_allowed_for_inter_sdp(bsize, ptree->partition)) {
+    const int ctx = get_intra_region_context(bsize);
+    assert(xd->tree_type != CHROMA_PART);
+    aom_write_symbol(w, ptree->region_type, xd->tile_ctx->region_type_cdf[ctx],
+                     REGION_TYPES);
+    if (ptree->region_type == INTRA_REGION) {
+      xd->tree_type = LUMA_PART;
+    }
+  }
+#endif  // CONFIG_EXTENDED_SDP
   switch (partition) {
     case PARTITION_NONE:
       write_modes_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
@@ -3921,6 +3947,17 @@
 #endif  // CONFIG_EXT_RECUR_PARTITIONS
     default: assert(0); break;
   }
+#if CONFIG_EXTENDED_SDP
+  if (!is_sb_root && !frame_is_intra_only(cm) && !cm->seq_params.monochrome &&
+      parent && partition && parent->region_type != INTRA_REGION &&
+      ptree->region_type == INTRA_REGION) {
+    // run chroma part in luma region
+    xd->tree_type = CHROMA_PART;
+    write_modes_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
+    // reset back to shared part
+    xd->tree_type = SHARED_PART;
+  }
+#endif  // CONFIG_EXTENDED_SDP
 
   // update partition context
   update_ext_partition_context(xd, mi_row, mi_col, subsize, bsize, partition);
diff --git a/av1/encoder/block.h b/av1/encoder/block.h
index 5ff0559..4165df3 100644
--- a/av1/encoder/block.h
+++ b/av1/encoder/block.h
@@ -835,6 +835,10 @@
    * \name Partition Costs
    ****************************************************************************/
   /**@{*/
+#if CONFIG_EXTENDED_SDP
+  //! Cost for coding the region type.
+  int region_type_cost[INTER_SDP_BSIZE_GROUP][REGION_TYPES];
+#endif  // CONFIG_EXTENDED_SDP
 #if CONFIG_EXT_RECUR_PARTITIONS
   /*! Cost for sending split token. */
   int do_split_cost[PARTITION_STRUCTURE_NUM][PARTITION_CONTEXTS][2];
diff --git a/av1/encoder/context_tree.c b/av1/encoder/context_tree.c
index ddcb0d7..75f0307 100644
--- a/av1/encoder/context_tree.c
+++ b/av1/encoder/context_tree.c
@@ -224,6 +224,18 @@
   pc_tree->parent = parent;
   pc_tree->index = index;
   pc_tree->partitioning = PARTITION_NONE;
+#if CONFIG_EXTENDED_SDP
+  if (parent) {
+    pc_tree->region_type = parent->region_type;
+    if (parent->inter_sdp_allowed_flag == 1)
+      pc_tree->inter_sdp_allowed_flag =
+          is_inter_sdp_allowed(parent->block_size, parent_partition);
+    else
+      pc_tree->inter_sdp_allowed_flag = 0;
+  } else {
+    pc_tree->inter_sdp_allowed_flag = 1;
+  }
+#endif  // CONFIG_EXTENDED_SDP
   pc_tree->block_size = bsize;
   pc_tree->is_last_subblock = is_last;
   av1_invalid_rd_stats(&pc_tree->rd_cost);
@@ -236,8 +248,49 @@
                       parent ? &parent->chroma_ref_info : NULL,
                       parent ? parent->block_size : BLOCK_INVALID,
                       parent_partition, subsampling_x, subsampling_y);
-
+#if CONFIG_EXTENDED_SDP
+  pc_tree->none[INTRA_REGION] = NULL;
+  pc_tree->none[MIXED_INTER_INTRA_REGION] = NULL;
+  pc_tree->none_chroma = NULL;
+#else
   pc_tree->none = NULL;
+#endif  // CONFIG_EXTENDED_SDP
+#if CONFIG_EXTENDED_SDP
+  for (REGION_TYPE cur_region_type = INTRA_REGION;
+       cur_region_type < REGION_TYPES; ++cur_region_type) {
+    for (int i = 0; i < 2; ++i) {
+      pc_tree->horizontal[cur_region_type][i] = NULL;
+      pc_tree->vertical[cur_region_type][i] = NULL;
+    }
+#if CONFIG_EXT_RECUR_PARTITIONS
+    for (int i = 0; i < 4; ++i) {
+      pc_tree->horizontal4a[cur_region_type][i] = NULL;
+      pc_tree->horizontal4b[cur_region_type][i] = NULL;
+      pc_tree->vertical4a[cur_region_type][i] = NULL;
+      pc_tree->vertical4b[cur_region_type][i] = NULL;
+    }
+    for (int i = 0; i < 4; ++i) {
+      pc_tree->horizontal3[cur_region_type][i] = NULL;
+      pc_tree->vertical3[cur_region_type][i] = NULL;
+    }
+#else
+    for (int i = 0; i < 3; ++i) {
+      pc_tree->horizontala[cur_region_type][i] = NULL;
+      pc_tree->horizontalb[cur_region_type][i] = NULL;
+      pc_tree->verticala[cur_region_type][i] = NULL;
+      pc_tree->verticalb[cur_region_type][i] = NULL;
+    }
+#endif  // CONFIG_EXT_RECUR_PARTITIONS
+    for (int i = 0; i < 4; ++i) {
+#if !CONFIG_EXT_RECUR_PARTITIONS
+      pc_tree->horizontal4[cur_region_type][i] = NULL;
+      pc_tree->vertical4[cur_region_type][i] = NULL;
+#endif  // !CONFIG_EXT_RECUR_PARTITIONS
+      pc_tree->split[cur_region_type][i] = NULL;
+    }
+  }
+
+#else  // CONFIG_EXTENDED_SDP
   for (int i = 0; i < 2; ++i) {
     pc_tree->horizontal[i] = NULL;
     pc_tree->vertical[i] = NULL;
@@ -268,7 +321,7 @@
 #endif  // !CONFIG_EXT_RECUR_PARTITIONS
     pc_tree->split[i] = NULL;
   }
-
+#endif  // CONFIG_EXTENDED_SDP
   return pc_tree;
 }
 
@@ -284,9 +337,135 @@
 
   const PARTITION_TYPE partition = pc_tree->partitioning;
 
+#if CONFIG_EXTENDED_SDP
+  PC_TREE *parent = pc_tree->parent;
+  if (!keep_none &&
+      (!keep_best || (pc_tree->region_type != INTRA_REGION ||
+                      (parent && parent->region_type == INTRA_REGION))))
+    FREE_PMC_NODE(pc_tree->none_chroma);
+
+  for (int cur_region_type = INTRA_REGION; cur_region_type < REGION_TYPES;
+       ++cur_region_type) {
+    if (!keep_none && (!keep_best || (partition != PARTITION_NONE)))
+      FREE_PMC_NODE(pc_tree->none[cur_region_type]);
+
+    for (int i = 0; i < 2; ++i) {
+#if CONFIG_EXT_RECUR_PARTITIONS
+      if ((!keep_best || (partition != PARTITION_HORZ) ||
+           (cur_region_type != pc_tree->region_type)) &&
+          pc_tree->horizontal[cur_region_type][i] != NULL) {
+        av1_free_pc_tree_recursive(pc_tree->horizontal[cur_region_type][i],
+                                   num_planes, 0, 0);
+        pc_tree->horizontal[cur_region_type][i] = NULL;
+      }
+      if ((!keep_best || (partition != PARTITION_VERT) ||
+           (cur_region_type != pc_tree->region_type)) &&
+          pc_tree->vertical[cur_region_type][i] != NULL) {
+        av1_free_pc_tree_recursive(pc_tree->vertical[cur_region_type][i],
+                                   num_planes, 0, 0);
+        pc_tree->vertical[cur_region_type][i] = NULL;
+      }
+#else
+      if (!keep_best || (partition != PARTITION_HORZ))
+        FREE_PMC_NODE(pc_tree->horizontal[cur_region_type][i]);
+      if (!keep_best || (partition != PARTITION_VERT))
+        FREE_PMC_NODE(pc_tree->vertical[cur_region_type][i]);
+#endif  // CONFIG_EXT_RECUR_PARTITIONS
+    }
+#if CONFIG_EXT_RECUR_PARTITIONS
+
+    if (!keep_best || (partition != PARTITION_HORZ_4A) ||
+        (cur_region_type != pc_tree->region_type)) {
+      for (int i = 0; i < 4; ++i) {
+        if (pc_tree->horizontal4a[cur_region_type][i] != NULL) {
+          av1_free_pc_tree_recursive(pc_tree->horizontal4a[cur_region_type][i],
+                                     num_planes, 0, 0);
+          pc_tree->horizontal4a[cur_region_type][i] = NULL;
+        }
+      }
+    }
+
+    if (!keep_best || (partition != PARTITION_HORZ_4B) ||
+        (cur_region_type != pc_tree->region_type)) {
+      for (int i = 0; i < 4; ++i) {
+        if (pc_tree->horizontal4b[cur_region_type][i] != NULL) {
+          av1_free_pc_tree_recursive(pc_tree->horizontal4b[cur_region_type][i],
+                                     num_planes, 0, 0);
+          pc_tree->horizontal4b[cur_region_type][i] = NULL;
+        }
+      }
+    }
+
+    if (!keep_best || (partition != PARTITION_VERT_4A) ||
+        (cur_region_type != pc_tree->region_type)) {
+      for (int i = 0; i < 4; ++i) {
+        if (pc_tree->vertical4a[cur_region_type][i] != NULL) {
+          av1_free_pc_tree_recursive(pc_tree->vertical4a[cur_region_type][i],
+                                     num_planes, 0, 0);
+          pc_tree->vertical4a[cur_region_type][i] = NULL;
+        }
+      }
+    }
+
+    if (!keep_best || (partition != PARTITION_VERT_4B) ||
+        (cur_region_type != pc_tree->region_type)) {
+      for (int i = 0; i < 4; ++i) {
+        if (pc_tree->vertical4b[cur_region_type][i] != NULL) {
+          av1_free_pc_tree_recursive(pc_tree->vertical4b[cur_region_type][i],
+                                     num_planes, 0, 0);
+          pc_tree->vertical4b[cur_region_type][i] = NULL;
+        }
+      }
+    }
+    for (int i = 0; i < 4; ++i) {
+      if ((!keep_best || (partition != PARTITION_HORZ_3) ||
+           (cur_region_type != pc_tree->region_type)) &&
+          pc_tree->horizontal3[cur_region_type][i] != NULL) {
+        av1_free_pc_tree_recursive(pc_tree->horizontal3[cur_region_type][i],
+                                   num_planes, 0, 0);
+        pc_tree->horizontal3[cur_region_type][i] = NULL;
+      }
+      if ((!keep_best || (partition != PARTITION_VERT_3) ||
+           (cur_region_type != pc_tree->region_type)) &&
+          pc_tree->vertical3[cur_region_type][i] != NULL) {
+        av1_free_pc_tree_recursive(pc_tree->vertical3[cur_region_type][i],
+                                   num_planes, 0, 0);
+        pc_tree->vertical3[cur_region_type][i] = NULL;
+      }
+    }
+#else
+    for (int i = 0; i < 3; ++i) {
+      if (!keep_best || (partition != PARTITION_HORZ_A))
+        FREE_PMC_NODE(pc_tree->horizontala[cur_region_type][i]);
+      if (!keep_best || (partition != PARTITION_HORZ_B))
+        FREE_PMC_NODE(pc_tree->horizontalb[cur_region_type][i]);
+      if (!keep_best || (partition != PARTITION_VERT_A))
+        FREE_PMC_NODE(pc_tree->verticala[cur_region_type][i]);
+      if (!keep_best || (partition != PARTITION_VERT_B))
+        FREE_PMC_NODE(pc_tree->verticalb[cur_region_type][i]);
+    }
+    for (int i = 0; i < 4; ++i) {
+      if (!keep_best || (partition != PARTITION_HORZ_4))
+        FREE_PMC_NODE(pc_tree->horizontal4[cur_region_type][i]);
+      if (!keep_best || (partition != PARTITION_VERT_4))
+        FREE_PMC_NODE(pc_tree->vertical4[cur_region_type][i]);
+    }
+#endif  // CONFIG_EXT_RECUR_PARTITIONS
+
+    if (!keep_best || (partition != PARTITION_SPLIT) ||
+        (cur_region_type != pc_tree->region_type)) {
+      for (int i = 0; i < 4; ++i) {
+        if (pc_tree->split[cur_region_type][i] != NULL) {
+          av1_free_pc_tree_recursive(pc_tree->split[cur_region_type][i],
+                                     num_planes, 0, 0);
+          pc_tree->split[cur_region_type][i] = NULL;
+        }
+      }
+    }
+  }    // region type index
+#else  // CONFIG_EXTENDED_SDP
   if (!keep_none && (!keep_best || (partition != PARTITION_NONE)))
     FREE_PMC_NODE(pc_tree->none);
-
   for (int i = 0; i < 2; ++i) {
 #if CONFIG_EXT_RECUR_PARTITIONS
     if ((!keep_best || (partition != PARTITION_HORZ)) &&
@@ -381,7 +560,7 @@
       }
     }
   }
-
+#endif  // CONFIG_EXTENDED_SDP
   if (!keep_best && !keep_none) aom_free(pc_tree);
 }
 
@@ -393,6 +572,11 @@
   // Copy the best partition type. For basic information like bsize and index,
   // we assume they have been set properly when initializing the dst PC_TREE
   dst->partitioning = src->partitioning;
+#if CONFIG_EXTENDED_SDP
+  dst->region_type = src->region_type;
+  dst->inter_sdp_allowed_flag = src->inter_sdp_allowed_flag;
+  REGION_TYPE cur_region_type = src->region_type;
+#endif  // CONFIG_EXTENDED_SDP
   dst->rd_cost = src->rd_cost;
   dst->none_rd = src->none_rd;
   dst->skippable = src->skippable;
@@ -402,9 +586,46 @@
   const int mi_row = src->mi_row;
   const int mi_col = src->mi_col;
 
+#if CONFIG_EXTENDED_SDP
+  PC_TREE *src_parent = src->parent;
+  if ((src->region_type == INTRA_REGION &&
+       (src_parent && src_parent->region_type == MIXED_INTER_INTRA_REGION))) {
+    if (dst->none_chroma) av1_free_pmc(dst->none_chroma, num_planes);
+    dst->none_chroma = NULL;
+    if (src->none_chroma) {
+      dst->none_chroma =
+          av1_alloc_pmc(cm, tree_type, mi_row, mi_col, bsize, dst,
+                        PARTITION_NONE, 0, ss_x, ss_y, shared_bufs);
+      av1_copy_tree_context(dst->none_chroma, src->none_chroma);
+    }
+  }
+#endif  // CONFIG_EXTENDED_SDP
+
   switch (src->partitioning) {
     // PARTITION_NONE
     case PARTITION_NONE:
+#if CONFIG_EXTENDED_SDP
+      if (dst->none[cur_region_type])
+        av1_free_pmc(dst->none[cur_region_type], num_planes);
+      dst->none[cur_region_type] = NULL;
+      if (src->none[cur_region_type]) {
+        dst->none[cur_region_type] =
+            av1_alloc_pmc(cm, tree_type, mi_row, mi_col, bsize, dst,
+                          PARTITION_NONE, 0, ss_x, ss_y, shared_bufs);
+        av1_copy_tree_context(dst->none[cur_region_type],
+                              src->none[cur_region_type]);
+#if CONFIG_MVP_IMPROVEMENT
+        if (is_inter_block(&src->none[cur_region_type]->mic, xd->tree_type)) {
+#if WARP_CU_BANK
+          av1_update_warp_param_bank(cm, xd, &dst->none[cur_region_type]->mic);
+#endif  // WARP_CU_BANK
+          if (cm->seq_params.enable_refmvbank) {
+            av1_update_ref_mv_bank(cm, xd, &dst->none[cur_region_type]->mic);
+          }
+        }
+#endif  // CONFIG_MVP_IMPROVEMENT
+      }
+#else
       if (dst->none) av1_free_pmc(dst->none, num_planes);
       dst->none = NULL;
       if (src->none) {
@@ -422,11 +643,30 @@
         }
 #endif  // CONFIG_MVP_IMPROVEMENT
       }
+#endif  // CONFIG_EXTENDED_SDP
       break;
     // PARTITION_SPLIT
     case PARTITION_SPLIT:
       if (is_partition_valid(bsize, PARTITION_SPLIT)) {
         for (int i = 0; i < 4; ++i) {
+#if CONFIG_EXTENDED_SDP
+          if (dst->split[cur_region_type][i]) {
+            av1_free_pc_tree_recursive(dst->split[cur_region_type][i],
+                                       num_planes, 0, 0);
+            dst->split[cur_region_type][i] = NULL;
+          }
+          if (src->split[cur_region_type][i]) {
+            const int x_idx = (i & 1) * (mi_size_wide[bsize] >> 1);
+            const int y_idx = (i >> 1) * (mi_size_high[bsize] >> 1);
+            dst->split[cur_region_type][i] = av1_alloc_pc_tree_node(
+                tree_type, mi_row + y_idx, mi_col + x_idx, subsize, dst,
+                PARTITION_SPLIT, i, i == 3, ss_x, ss_y);
+            av1_copy_pc_tree_recursive(xd, cm, dst->split[cur_region_type][i],
+                                       src->split[cur_region_type][i], ss_x,
+                                       ss_y, shared_bufs, tree_type,
+                                       num_planes);
+          }
+#else   // CONFIG_EXTENDED_SDP
           if (dst->split[i]) {
             av1_free_pc_tree_recursive(dst->split[i], num_planes, 0, 0);
             dst->split[i] = NULL;
@@ -441,6 +681,7 @@
                                        ss_x, ss_y, shared_bufs, tree_type,
                                        num_planes);
           }
+#endif  // CONFIG_EXTENDED_SDP
         }
       }
       break;
@@ -448,6 +689,23 @@
     case PARTITION_HORZ:
       if (is_partition_valid(bsize, PARTITION_HORZ)) {
         for (int i = 0; i < 2; ++i) {
+#if CONFIG_EXTENDED_SDP
+          if (dst->horizontal[cur_region_type][i]) {
+            av1_free_pc_tree_recursive(dst->horizontal[cur_region_type][i],
+                                       num_planes, 0, 0);
+            dst->horizontal[cur_region_type][i] = NULL;
+          }
+          if (src->horizontal[cur_region_type][i]) {
+            const int this_mi_row = mi_row + i * (mi_size_high[bsize] >> 1);
+            dst->horizontal[cur_region_type][i] = av1_alloc_pc_tree_node(
+                tree_type, this_mi_row, mi_col, subsize, dst, PARTITION_HORZ, i,
+                i == 1, ss_x, ss_y);
+            av1_copy_pc_tree_recursive(
+                xd, cm, dst->horizontal[cur_region_type][i],
+                src->horizontal[cur_region_type][i], ss_x, ss_y, shared_bufs,
+                tree_type, num_planes);
+          }
+#else
           if (dst->horizontal[i]) {
             av1_free_pc_tree_recursive(dst->horizontal[i], num_planes, 0, 0);
             dst->horizontal[i] = NULL;
@@ -461,6 +719,7 @@
                                        src->horizontal[i], ss_x, ss_y,
                                        shared_bufs, tree_type, num_planes);
           }
+#endif  // CONFIG_EXTENDED_SDP
         }
       }
       break;
@@ -468,6 +727,23 @@
     case PARTITION_VERT:
       if (is_partition_valid(bsize, PARTITION_VERT)) {
         for (int i = 0; i < 2; ++i) {
+#if CONFIG_EXTENDED_SDP
+          if (dst->vertical[cur_region_type][i]) {
+            av1_free_pc_tree_recursive(dst->vertical[cur_region_type][i],
+                                       num_planes, 0, 0);
+            dst->vertical[cur_region_type][i] = NULL;
+          }
+          if (src->vertical[cur_region_type][i]) {
+            const int this_mi_col = mi_col + i * (mi_size_wide[bsize] >> 1);
+            dst->vertical[cur_region_type][i] = av1_alloc_pc_tree_node(
+                tree_type, mi_row, this_mi_col, subsize, dst, PARTITION_VERT, i,
+                i == 1, ss_x, ss_y);
+            av1_copy_pc_tree_recursive(
+                xd, cm, dst->vertical[cur_region_type][i],
+                src->vertical[cur_region_type][i], ss_x, ss_y, shared_bufs,
+                tree_type, num_planes);
+          }
+#else
           if (dst->vertical[i]) {
             av1_free_pc_tree_recursive(dst->vertical[i], num_planes, 0, 0);
             dst->vertical[i] = NULL;
@@ -481,6 +757,7 @@
                                        src->vertical[i], ss_x, ss_y,
                                        shared_bufs, tree_type, num_planes);
           }
+#endif  // CONFIG_EXTENDED_SDP
         }
       }
       break;
@@ -497,6 +774,22 @@
         const BLOCK_SIZE subsizes[4] = { subsize, bsize_med, bsize_big,
                                          subsize };
         for (int i = 0; i < 4; ++i) {
+#if CONFIG_EXTENDED_SDP
+          if (dst->horizontal4a[cur_region_type][i]) {
+            av1_free_pc_tree_recursive(dst->horizontal4a[cur_region_type][i],
+                                       num_planes, 0, 0);
+            dst->horizontal4a[cur_region_type][i] = NULL;
+          }
+          if (src->horizontal4a[cur_region_type][i]) {
+            dst->horizontal4a[cur_region_type][i] = av1_alloc_pc_tree_node(
+                tree_type, mi_rows[i], mi_col, subsizes[i], dst,
+                PARTITION_HORZ_4A, i, i == 3, ss_x, ss_y);
+            av1_copy_pc_tree_recursive(
+                xd, cm, dst->horizontal4a[cur_region_type][i],
+                src->horizontal4a[cur_region_type][i], ss_x, ss_y, shared_bufs,
+                tree_type, num_planes);
+          }
+#else
           if (dst->horizontal4a[i]) {
             av1_free_pc_tree_recursive(dst->horizontal4a[i], num_planes, 0, 0);
             dst->horizontal4a[i] = NULL;
@@ -509,6 +802,7 @@
                                        src->horizontal4a[i], ss_x, ss_y,
                                        shared_bufs, tree_type, num_planes);
           }
+#endif  // CONFIG_EXTENDED_SDP
         }
       }
       break;
@@ -525,6 +819,22 @@
         const BLOCK_SIZE subsizes[4] = { subsize, bsize_big, bsize_med,
                                          subsize };
         for (int i = 0; i < 4; ++i) {
+#if CONFIG_EXTENDED_SDP
+          if (dst->horizontal4b[cur_region_type][i]) {
+            av1_free_pc_tree_recursive(dst->horizontal4b[cur_region_type][i],
+                                       num_planes, 0, 0);
+            dst->horizontal4b[cur_region_type][i] = NULL;
+          }
+          if (src->horizontal4b[cur_region_type][i]) {
+            dst->horizontal4b[cur_region_type][i] = av1_alloc_pc_tree_node(
+                tree_type, mi_rows[i], mi_col, subsizes[i], dst,
+                PARTITION_HORZ_4B, i, i == 3, ss_x, ss_y);
+            av1_copy_pc_tree_recursive(
+                xd, cm, dst->horizontal4b[cur_region_type][i],
+                src->horizontal4b[cur_region_type][i], ss_x, ss_y, shared_bufs,
+                tree_type, num_planes);
+          }
+#else   // CONFIG_EXTENDED_SDP
           if (dst->horizontal4b[i]) {
             av1_free_pc_tree_recursive(dst->horizontal4b[i], num_planes, 0, 0);
             dst->horizontal4b[i] = NULL;
@@ -537,6 +847,7 @@
                                        src->horizontal4b[i], ss_x, ss_y,
                                        shared_bufs, tree_type, num_planes);
           }
+#endif  // CONFIG_EXTENDED_SDP
         }
       }
       break;
@@ -553,6 +864,22 @@
         const BLOCK_SIZE subsizes[4] = { subsize, bsize_med, bsize_big,
                                          subsize };
         for (int i = 0; i < 4; ++i) {
+#if CONFIG_EXTENDED_SDP
+          if (dst->vertical4a[cur_region_type][i]) {
+            av1_free_pc_tree_recursive(dst->vertical4a[cur_region_type][i],
+                                       num_planes, 0, 0);
+            dst->vertical4a[cur_region_type][i] = NULL;
+          }
+          if (src->vertical4a[cur_region_type][i]) {
+            dst->vertical4a[cur_region_type][i] = av1_alloc_pc_tree_node(
+                tree_type, mi_row, mi_cols[i], subsizes[i], dst,
+                PARTITION_VERT_4A, i, i == 3, ss_x, ss_y);
+            av1_copy_pc_tree_recursive(
+                xd, cm, dst->vertical4a[cur_region_type][i],
+                src->vertical4a[cur_region_type][i], ss_x, ss_y, shared_bufs,
+                tree_type, num_planes);
+          }
+#else   // CONFIG_EXTENDED_SDP
           if (dst->vertical4a[i]) {
             av1_free_pc_tree_recursive(dst->vertical4a[i], num_planes, 0, 0);
             dst->vertical4a[i] = NULL;
@@ -565,6 +892,7 @@
                                        src->vertical4a[i], ss_x, ss_y,
                                        shared_bufs, tree_type, num_planes);
           }
+#endif  // CONFIG_EXTENDED_SDP
         }
       }
       break;
@@ -581,6 +909,22 @@
         const BLOCK_SIZE subsizes[4] = { subsize, bsize_big, bsize_med,
                                          subsize };
         for (int i = 0; i < 4; ++i) {
+#if CONFIG_EXTENDED_SDP
+          if (dst->vertical4b[cur_region_type][i]) {
+            av1_free_pc_tree_recursive(dst->vertical4b[cur_region_type][i],
+                                       num_planes, 0, 0);
+            dst->vertical4b[cur_region_type][i] = NULL;
+          }
+          if (src->vertical4b[cur_region_type][i]) {
+            dst->vertical4b[cur_region_type][i] = av1_alloc_pc_tree_node(
+                tree_type, mi_row, mi_cols[i], subsizes[i], dst,
+                PARTITION_VERT_4B, i, i == 3, ss_x, ss_y);
+            av1_copy_pc_tree_recursive(
+                xd, cm, dst->vertical4b[cur_region_type][i],
+                src->vertical4b[cur_region_type][i], ss_x, ss_y, shared_bufs,
+                tree_type, num_planes);
+          }
+#else   // CONFIG_EXTENDED_SDP
           if (dst->vertical4b[i]) {
             av1_free_pc_tree_recursive(dst->vertical4b[i], num_planes, 0, 0);
             dst->vertical4b[i] = NULL;
@@ -593,6 +937,7 @@
                                        src->vertical4b[i], ss_x, ss_y,
                                        shared_bufs, tree_type, num_planes);
           }
+#endif  // CONFIG_EXTENDED_SDP
         }
       }
       break;
@@ -607,7 +952,22 @@
               get_h_partition_offset_mi_row(bsize, i, PARTITION_HORZ_3);
           const int offset_mc =
               get_h_partition_offset_mi_col(bsize, i, PARTITION_HORZ_3);
-
+#if CONFIG_EXTENDED_SDP
+          if (dst->horizontal3[cur_region_type][i]) {
+            av1_free_pc_tree_recursive(dst->horizontal3[cur_region_type][i],
+                                       num_planes, 0, 0);
+            dst->horizontal3[cur_region_type][i] = NULL;
+          }
+          if (src->horizontal3[cur_region_type][i]) {
+            dst->horizontal3[cur_region_type][i] = av1_alloc_pc_tree_node(
+                tree_type, mi_row + offset_mr, mi_col + offset_mc, this_subsize,
+                dst, PARTITION_HORZ_3, i, i == 3, ss_x, ss_y);
+            av1_copy_pc_tree_recursive(
+                xd, cm, dst->horizontal3[cur_region_type][i],
+                src->horizontal3[cur_region_type][i], ss_x, ss_y, shared_bufs,
+                tree_type, num_planes);
+          }
+#else   // CONFIG_EXTENDED_SDP
           if (dst->horizontal3[i]) {
             av1_free_pc_tree_recursive(dst->horizontal3[i], num_planes, 0, 0);
             dst->horizontal3[i] = NULL;
@@ -620,6 +980,7 @@
                                        src->horizontal3[i], ss_x, ss_y,
                                        shared_bufs, tree_type, num_planes);
           }
+#endif  // CONFIG_EXTENDED_SDP
         }
       }
       break;
@@ -633,7 +994,22 @@
               get_h_partition_offset_mi_row(bsize, i, PARTITION_VERT_3);
           const int offset_mc =
               get_h_partition_offset_mi_col(bsize, i, PARTITION_VERT_3);
-
+#if CONFIG_EXTENDED_SDP
+          if (dst->vertical3[cur_region_type][i]) {
+            av1_free_pc_tree_recursive(dst->vertical3[cur_region_type][i],
+                                       num_planes, 0, 0);
+            dst->vertical3[cur_region_type][i] = NULL;
+          }
+          if (src->vertical3[cur_region_type][i]) {
+            dst->vertical3[cur_region_type][i] = av1_alloc_pc_tree_node(
+                tree_type, mi_row + offset_mr, mi_col + offset_mc, this_subsize,
+                dst, PARTITION_VERT_3, i, i == 3, ss_x, ss_y);
+            av1_copy_pc_tree_recursive(
+                xd, cm, dst->vertical3[cur_region_type][i],
+                src->vertical3[cur_region_type][i], ss_x, ss_y, shared_bufs,
+                tree_type, num_planes);
+          }
+#else   // CONFIG_EXTENDED_SDP
           if (dst->vertical3[i]) {
             av1_free_pc_tree_recursive(dst->vertical3[i], num_planes, 0, 0);
             dst->vertical3[i] = NULL;
@@ -646,6 +1022,7 @@
                                        src->vertical3[i], ss_x, ss_y,
                                        shared_bufs, tree_type, num_planes);
           }
+#endif  // CONFIG_EXTENDED_SDP
         }
       }
       break;
@@ -782,6 +1159,36 @@
   if (pc_tree == NULL || pc_tree == target) return NULL;
 
   PC_TREE *result;
+#if CONFIG_EXTENDED_SDP
+  REGION_TYPE cur_region_type = pc_tree->region_type;
+  result =
+      look_for_counterpart_helper(pc_tree->split[cur_region_type][0], target);
+  if (result) return result;
+  result = look_for_counterpart_helper(pc_tree->horizontal[cur_region_type][0],
+                                       target);
+  if (result) return result;
+  result = look_for_counterpart_helper(pc_tree->vertical[cur_region_type][0],
+                                       target);
+  if (result) return result;
+  result = look_for_counterpart_helper(
+      pc_tree->horizontal4a[cur_region_type][0], target);
+  if (result) return result;
+  result = look_for_counterpart_helper(
+      pc_tree->horizontal4b[cur_region_type][0], target);
+  if (result) return result;
+  result = look_for_counterpart_helper(pc_tree->vertical4a[cur_region_type][0],
+                                       target);
+  if (result) return result;
+  result = look_for_counterpart_helper(pc_tree->vertical4b[cur_region_type][0],
+                                       target);
+  if (result) return result;
+  result = look_for_counterpart_helper(pc_tree->horizontal3[cur_region_type][0],
+                                       target);
+  if (result) return result;
+  result = look_for_counterpart_helper(pc_tree->vertical3[cur_region_type][0],
+                                       target);
+  if (result) return result;
+#else
   result = look_for_counterpart_helper(pc_tree->split[0], target);
   if (result) return result;
   result = look_for_counterpart_helper(pc_tree->horizontal[0], target);
@@ -800,6 +1207,7 @@
   if (result) return result;
   result = look_for_counterpart_helper(pc_tree->vertical3[0], target);
   if (result) return result;
+#endif  // CONFIG_EXTENDED_SDP
   return NULL;
 }
 
diff --git a/av1/encoder/context_tree.h b/av1/encoder/context_tree.h
index 2016b4d..37c8744 100644
--- a/av1/encoder/context_tree.h
+++ b/av1/encoder/context_tree.h
@@ -71,7 +71,37 @@
 
 typedef struct PC_TREE {
   PARTITION_TYPE partitioning;
+#if CONFIG_EXTENDED_SDP
+  /*! \brief The region type used for the current block. */
+  REGION_TYPE region_type;
+#endif  // CONFIG_EXTENDED_SDP
   BLOCK_SIZE block_size;
+#if CONFIG_EXTENDED_SDP
+  int inter_sdp_allowed_flag;
+  PICK_MODE_CONTEXT *none[REGION_TYPES];
+  // record the chroma information in intra region.
+  PICK_MODE_CONTEXT *none_chroma;
+#if CONFIG_EXT_RECUR_PARTITIONS
+  struct PC_TREE *horizontal[REGION_TYPES][2];
+  struct PC_TREE *vertical[REGION_TYPES][2];
+  struct PC_TREE *horizontal4a[REGION_TYPES][4];
+  struct PC_TREE *horizontal4b[REGION_TYPES][4];
+  struct PC_TREE *vertical4a[REGION_TYPES][4];
+  struct PC_TREE *vertical4b[REGION_TYPES][4];
+  struct PC_TREE *horizontal3[REGION_TYPES][4];
+  struct PC_TREE *vertical3[REGION_TYPES][4];
+#else
+  PICK_MODE_CONTEXT *horizontal[REGION_TYPES][2];
+  PICK_MODE_CONTEXT *vertical[REGION_TYPES][2];
+  PICK_MODE_CONTEXT *horizontala[REGION_TYPES][3];
+  PICK_MODE_CONTEXT *horizontalb[REGION_TYPES][3];
+  PICK_MODE_CONTEXT *verticala[REGION_TYPES][3];
+  PICK_MODE_CONTEXT *verticalb[REGION_TYPES][3];
+  PICK_MODE_CONTEXT *horizontal4[REGION_TYPES][4];
+  PICK_MODE_CONTEXT *vertical4[REGION_TYPES][4];
+#endif  // CONFIG_EXT_RECUR_PARTITIONS
+  struct PC_TREE *split[REGION_TYPES][4];
+#else
   PICK_MODE_CONTEXT *none;
 #if CONFIG_EXT_RECUR_PARTITIONS
   struct PC_TREE *horizontal[2];
@@ -93,6 +123,7 @@
   PICK_MODE_CONTEXT *vertical4[4];
 #endif  // CONFIG_EXT_RECUR_PARTITIONS
   struct PC_TREE *split[4];
+#endif  // CONFIG_EXTENDED_SDP
   struct PC_TREE *parent;
   int mi_row;
   int mi_col;
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 0bb84cb..978dea1 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -566,6 +566,13 @@
     PC_TREE *const pc_root =
         av1_alloc_pc_tree_node(xd->tree_type, mi_row, mi_col, sb_size, NULL,
                                PARTITION_NONE, 0, 1, ss_x, ss_y);
+#if CONFIG_EXTENDED_SDP
+    if (!frame_is_intra_only(cm)) {
+      pc_root->region_type = MIXED_INTER_INTRA_REGION;
+    } else {
+      pc_root->region_type = INTRA_REGION;
+    }
+#endif  // CONFIG_EXTENDED_SDP
 #if CONFIG_EXT_RECUR_PARTITIONS
     const PARTITION_TREE *template_tree =
         multi_pass_params ? multi_pass_params->template_tree : NULL;
@@ -579,8 +586,11 @@
     int force_prune_flags[3] = { 0, 0, 0 };
 #endif  // CONFIG_ML_PART_SPLIT
     av1_rd_pick_partition(
-        cpi, td, tile_data, tp, mi_row, mi_col, sb_size, &dummy_rdc, dummy_rdc,
-        pc_root,
+        cpi, td, tile_data, tp, mi_row, mi_col, sb_size,
+#if CONFIG_EXTENDED_SDP
+        PARTITION_NONE,
+#endif  // CONFIG_EXTENDED_SDP
+        &dummy_rdc, dummy_rdc, pc_root,
 #if CONFIG_EXT_RECUR_PARTITIONS
         xd->tree_type == CHROMA_PART ? xd->sbi->ptree_root[0] : NULL,
         template_tree, INT_MAX,
diff --git a/av1/encoder/encodeframe_utils.c b/av1/encoder/encodeframe_utils.c
index cbb9c29..c352e68 100644
--- a/av1/encoder/encodeframe_utils.c
+++ b/av1/encoder/encodeframe_utils.c
@@ -1715,6 +1715,14 @@
                  UV_INTRA_MODES - 1, CDF_SIZE(UV_INTRA_MODES));
   AVERAGE_CDF(ctx_left->uv_mode_cdf[1], ctx_tr->uv_mode_cdf[1], UV_INTRA_MODES);
 #endif  // CONFIG_UV_CFL
+
+#if CONFIG_EXTENDED_SDP
+  for (int i = 0; i < INTER_SDP_BSIZE_GROUP; i++) {
+    AVERAGE_CDF(ctx_left->region_type_cdf[i], ctx_tr->region_type_cdf[i],
+                REGION_TYPES);
+  }
+#endif  // CONFIG_EXTENDED_SDP
+
 #if CONFIG_EXT_RECUR_PARTITIONS
   for (int plane_index = 0; plane_index < PARTITION_STRUCTURE_NUM;
        plane_index++) {
diff --git a/av1/encoder/encodeframe_utils.h b/av1/encoder/encodeframe_utils.h
index c714e9c..1eea6ef 100644
--- a/av1/encoder/encodeframe_utils.h
+++ b/av1/encoder/encodeframe_utils.h
@@ -173,6 +173,11 @@
   // Pointer to partition cost buffer
   const int *partition_cost;
 
+#if CONFIG_EXTENDED_SDP
+  // Pointer to region type cost buffer
+  int *region_type_cost;
+#endif  // CONFIG_EXTENDED_SDP
+
   // RD costs for different partition types.
   int64_t none_rd;
   int64_t split_rd[SUB_PARTITIONS_SPLIT];
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index aae2e02..b5f78aa 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -1374,6 +1374,9 @@
   unsigned int palette_uv_color_index[PALETTE_SIZES]
                                      [PALETTE_COLOR_INDEX_CONTEXTS]
                                      [PALETTE_COLORS];
+#if CONFIG_EXTENDED_SDP
+  unsigned int region_type[INTER_SDP_BSIZE_GROUP][REGION_TYPES];
+#endif  // CONFIG_EXTENDED_SDP
 #if CONFIG_EXT_RECUR_PARTITIONS
   unsigned int do_split[PARTITION_STRUCTURE_NUM][PARTITION_CONTEXTS][2];
   unsigned int do_square_split[PARTITION_STRUCTURE_NUM][SQUARE_SPLIT_CONTEXTS]
diff --git a/av1/encoder/intra_mode_search.c b/av1/encoder/intra_mode_search.c
index f392009..e8254f7 100644
--- a/av1/encoder/intra_mode_search.c
+++ b/av1/encoder/intra_mode_search.c
@@ -612,7 +612,10 @@
 
   // Only store reconstructed luma when there's chroma RDO. When there's no
   // chroma RDO, the reconstructed luma will be stored in encode_superblock().
-  xd->cfl.store_y = store_cfl_required_rdo(cm, x);
+#if CONFIG_EXTENDED_SDP
+  if (frame_is_intra_only(cm) || xd->tree_type != CHROMA_PART)
+#endif  // CONFIG_EXTENDED_SDP
+    xd->cfl.store_y = store_cfl_required_rdo(cm, x);
   if (xd->tree_type == SHARED_PART) {
     if (xd->cfl.store_y) {
       av1_encode_intra_block_plane(cpi, x, mbmi->sb_type[PLANE_TYPE_Y],
@@ -1251,7 +1254,7 @@
     mode_cost += ref_frame_cost;
     mode_cost += mrl_idx_cost;
   }
-#else   // CONFIG_LOSSLESS_DPCM
+#else  // CONFIG_LOSSLESS_DPCM
   const int context = get_y_mode_idx_ctx(xd);
   int mode_set_index = mbmi->y_mode_idx < FIRST_MODE_COUNT ? 0 : 1;
   mode_set_index += ((mbmi->y_mode_idx - FIRST_MODE_COUNT) / SECOND_MODE_COUNT);
@@ -1265,7 +1268,10 @@
                                 [mbmi->y_mode_idx - FIRST_MODE_COUNT -
                                  SECOND_MODE_COUNT * (mode_set_index - 1)];
   }
-  mode_cost += ref_frame_cost;
+#if CONFIG_EXTENDED_SDP
+  if (mbmi->region_type != INTRA_REGION)
+#endif  // CONFIG_EXTENDED_SDP
+    mode_cost += ref_frame_cost;
   mode_cost += mrl_idx_cost;
 #endif  // CONFIG_LOSSLESS_DPCM
 #else
diff --git a/av1/encoder/intra_mode_search_utils.h b/av1/encoder/intra_mode_search_utils.h
index 6304ccc..c853a3a 100644
--- a/av1/encoder/intra_mode_search_utils.h
+++ b/av1/encoder/intra_mode_search_utils.h
@@ -279,7 +279,7 @@
     }
   }
 #endif  // !CONFIG_AIMC
-  if (av1_allow_intrabc(&cpi->common) && xd->tree_type != CHROMA_PART) {
+  if (av1_allow_intrabc(&cpi->common, xd) && xd->tree_type != CHROMA_PART) {
 #if CONFIG_NEW_CONTEXT_MODELING
     const int intrabc_ctx = get_intrabc_ctx(xd);
     total_rate += mode_costs->intrabc_cost[intrabc_ctx][use_intrabc];
diff --git a/av1/encoder/partition_search.c b/av1/encoder/partition_search.c
index 67faefc..fc1851d 100644
--- a/av1/encoder/partition_search.c
+++ b/av1/encoder/partition_search.c
@@ -586,12 +586,11 @@
   }
 
   if (!dry_run) {
-    if (av1_allow_intrabc(cm) && is_intrabc_block(mbmi, xd->tree_type))
+    if (av1_allow_intrabc(cm, xd) && is_intrabc_block(mbmi, xd->tree_type))
       td->intrabc_used = 1;
 #if CONFIG_MORPH_PRED
     if (mbmi->morph_pred) {
-      assert(av1_allow_intrabc(cm));
-      assert(is_intrabc_block(mbmi, xd->tree_type));
+      assert(av1_allow_intrabc(cm, xd));
     }
 #endif  // CONFIG_MORPH_PRED
     if (txfm_params->tx_mode_search_type == TX_MODE_SELECT &&
@@ -653,12 +652,21 @@
       } else {
         intra_tx_size = mbmi->tx_size;
       }
-
-      for (j = 0; j < mi_height; j++)
-        for (i = 0; i < mi_width; i++)
-          if (mi_col + i < cm->mi_params.mi_cols &&
-              mi_row + j < cm->mi_params.mi_rows)
-            mi_4x4[mis * j + i]->tx_size = intra_tx_size;
+#if CONFIG_EXTENDED_SDP
+      // Since transform partitioning is only allowed for luma component,
+      // and tx_size variable represents the transform size of the luma
+      // component in one coded block, so chroma block should not change the
+      // tx_size.
+      if (xd->tree_type != CHROMA_PART || frame_is_intra_only(cm)) {
+#endif  // CONFIG_EXTENDED_SDP
+        for (j = 0; j < mi_height; j++)
+          for (i = 0; i < mi_width; i++)
+            if (mi_col + i < cm->mi_params.mi_cols &&
+                mi_row + j < cm->mi_params.mi_rows)
+              mi_4x4[mis * j + i]->tx_size = intra_tx_size;
+#if CONFIG_EXTENDED_SDP
+      }
+#endif  // CONFIG_EXTENDED_SDP
 
       if (intra_tx_size != max_txsize_rect_lookup[bsize])
         ++x->txfm_search_info.txb_split_count;
@@ -844,6 +852,11 @@
   av1_set_offsets_without_segment_id(cpi, tile, x, mi_row, mi_col, bsize,
                                      chroma_ref_info);
 
+#if CONFIG_EXTENDED_SDP
+  // Don't set up segment ID for chroma part in SDP of inter frame
+  if (!frame_is_intra_only(cm) && xd->tree_type == CHROMA_PART) return;
+#endif  // CONFIG_EXTENDED_SDP
+
   // Setup segment ID.
   mbmi = xd->mi[0];
   mbmi->segment_id = 0;
@@ -881,6 +894,7 @@
  * \param[in]    rd_cost        Pointer to structure holding rate and distortion
  *                              stats for the current block
  * \param[in]    partition      Partition mode of the parent block
+ * \param[in]    cur_region_type      Region type of the current block
  * \param[in]    bsize          Current block size
  * \param[in]    ctx            Pointer to structure holding coding contexts and
  *                              chosen modes for the current block
@@ -894,6 +908,9 @@
 static void pick_sb_modes(AV1_COMP *const cpi, TileDataEnc *tile_data,
                           MACROBLOCK *const x, int mi_row, int mi_col,
                           RD_STATS *rd_cost, PARTITION_TYPE partition,
+#if CONFIG_EXTENDED_SDP
+                          REGION_TYPE cur_region_type,
+#endif  // CONFIG_EXTENDED_SDP
                           BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
                           RD_STATS best_rd) {
   if (best_rd.rdcost < 0) {
@@ -912,6 +929,10 @@
   av1_set_offsets(cpi, &tile_data->tile_info, x, mi_row, mi_col, bsize,
                   &ctx->chroma_ref_info);
 
+#if CONFIG_EXTENDED_SDP
+  xd->mi[0]->region_type = cur_region_type;
+#endif  // CONFIG_EXTENDED_SDP
+
   if (ctx->rd_mode_is_ready) {
     assert(ctx->mic.sb_type[plane_type] == bsize);
     assert(ctx->mic.partition == partition);
@@ -998,7 +1019,11 @@
 
   // Find best coding mode & reconstruct the MB so it is available
   // as a predictor for MBs that follow in the SB
-  if (frame_is_intra_only(cm)) {
+  if (frame_is_intra_only(cm)
+#if CONFIG_EXTENDED_SDP
+      || mbmi->region_type == INTRA_REGION
+#endif  // CONFIG_EXTENDED_SDP
+  ) {
 #if CONFIG_COLLECT_COMPONENT_TIMING
     start_timing(cpi, av1_rd_pick_intra_mode_sb_time);
 #endif
@@ -1280,6 +1305,9 @@
   const int seg_ref_active = 0;
 
   if (current_frame->skip_mode_info.skip_mode_flag && !seg_ref_active &&
+#if CONFIG_EXTENDED_SDP
+      mbmi->region_type != INTRA_REGION &&
+#endif  // CONFIG_EXTENDED_SDP
       is_comp_ref_allowed(bsize)) {
     const int skip_mode_ctx = av1_get_skip_mode_context(xd);
 #if CONFIG_ENTROPY_STATS
@@ -1291,15 +1319,19 @@
 #if CONFIG_SKIP_TXFM_OPT
   const int use_intrabc = is_intrabc_block(mbmi, xd->tree_type);
   if (!seg_ref_active) {
-    if (!mbmi->skip_mode && !frame_is_intra_only(cm)) {
+    if (!mbmi->skip_mode && !frame_is_intra_only(cm)
+#if CONFIG_EXTENDED_SDP
+        && mbmi->region_type != INTRA_REGION
+#endif  // CONFIG_EXTENDED_SDP
+    ) {
       const int intra_inter_ctx = av1_get_intra_inter_context(xd);
 #if CONFIG_ENTROPY_STATS
       td->counts->intra_inter[intra_inter_ctx][inter_block]++;
 #endif  // CONFIG_ENTROPY_STATS
       update_cdf(fc->intra_inter_cdf[intra_inter_ctx], inter_block, 2);
     }
-
-    if (!inter_block && av1_allow_intrabc(cm) && xd->tree_type != CHROMA_PART) {
+    if (!inter_block && av1_allow_intrabc(cm, xd) &&
+        xd->tree_type != CHROMA_PART) {
 #if CONFIG_NEW_CONTEXT_MODELING
       const int intrabc_ctx = get_intrabc_ctx(xd);
       update_cdf(fc->intrabc_cdf[intrabc_ctx], use_intrabc, 2);
@@ -1393,7 +1425,7 @@
   if (!is_inter_block(mbmi, xd->tree_type)) {
     av1_sum_intra_stats(cm, td->counts, xd, mbmi);
   }
-  if (av1_allow_intrabc(cm) && xd->tree_type != CHROMA_PART) {
+  if (av1_allow_intrabc(cm, xd) && xd->tree_type != CHROMA_PART) {
 #if !CONFIG_SKIP_TXFM_OPT
     const int use_intrabc = is_intrabc_block(mbmi, xd->tree_type);
 #if CONFIG_NEW_CONTEXT_MODELING
@@ -2806,6 +2838,21 @@
     ptree->bsize = bsize;
     ptree->mi_row = mi_row;
     ptree->mi_col = mi_col;
+#if CONFIG_EXTENDED_SDP
+    ptree->region_type = pc_tree->region_type;
+    const int is_sb_root = bsize == cm->sb_size;
+    ptree->inter_sdp_allowed_flag = pc_tree->inter_sdp_allowed_flag;
+    if (!frame_is_intra_only(cm) && !is_sb_root &&
+        partition != PARTITION_NONE && parent &&
+        parent->region_type != INTRA_REGION && xd->tree_type != CHROMA_PART &&
+        ptree->inter_sdp_allowed_flag &&
+        is_bsize_allowed_for_inter_sdp(bsize, partition)) {
+      assert(xd->tree_type != CHROMA_PART);
+      const int intra_region_ctx = get_intra_region_context(bsize);
+      update_cdf(xd->tile_ctx->region_type_cdf[intra_region_ctx],
+                 ptree->region_type, REGION_TYPES);
+    }
+#endif  // CONFIG_EXTENDED_SDP
     const int ss_x = xd->plane[1].subsampling_x;
     const int ss_y = xd->plane[1].subsampling_y;
     set_chroma_ref_info(
@@ -2860,19 +2907,45 @@
     }
   }
 #endif  // CONFIG_EXT_RECUR_PARTITIONS
+#if CONFIG_EXTENDED_SDP
+  // encode both the luma and chroma blocks in one intra region
+  int encode_sdp_intra_region_yuv = 0;
+  if (!frame_is_intra_only(cm) && xd->tree_type == SHARED_PART &&
+      pc_tree->region_type == INTRA_REGION) {
+    encode_sdp_intra_region_yuv = 1;
+    xd->tree_type = LUMA_PART;
+  }
+#endif  // CONFIG_EXTENDED_SDP
   switch (partition) {
     case PARTITION_NONE:
       encode_b(cpi, tile_data, td, tp, mi_row, mi_col, dry_run, subsize,
-               partition, pc_tree->none, rate);
+               partition,
+#if CONFIG_EXTENDED_SDP
+               pc_tree->none[pc_tree->region_type],
+#else
+               pc_tree->none,
+#endif  // CONFIG_EXTENDED_SDP
+               rate);
       break;
     case PARTITION_VERT:
 #if CONFIG_EXT_RECUR_PARTITIONS
       encode_sb(cpi, td, tile_data, tp, mi_row, mi_col, dry_run, subsize,
-                pc_tree->vertical[0], sub_tree[0],
-                track_ptree_luma ? ptree_luma->sub_tree[0] : NULL, rate);
+#if CONFIG_EXTENDED_SDP
+                pc_tree->vertical[pc_tree->region_type][0],
+#else
+                pc_tree->vertical[0],
+#endif  // CONFIG_EXTENDED_SDP
+                sub_tree[0], track_ptree_luma ? ptree_luma->sub_tree[0] : NULL,
+                rate);
       if (mi_col + hbs_w < cm->mi_params.mi_cols) {
         encode_sb(cpi, td, tile_data, tp, mi_row, mi_col + hbs_w, dry_run,
-                  subsize, pc_tree->vertical[1], sub_tree[1],
+                  subsize,
+#if CONFIG_EXTENDED_SDP
+                  pc_tree->vertical[pc_tree->region_type][1],
+#else
+                  pc_tree->vertical[1],
+#endif  // CONFIG_EXTENDED_SDP
+                  sub_tree[1],
                   track_ptree_luma ? ptree_luma->sub_tree[1] : NULL, rate);
       }
 #else   // CONFIG_EXT_RECUR_PARTITIONS
@@ -2887,11 +2960,22 @@
     case PARTITION_HORZ:
 #if CONFIG_EXT_RECUR_PARTITIONS
       encode_sb(cpi, td, tile_data, tp, mi_row, mi_col, dry_run, subsize,
-                pc_tree->horizontal[0], sub_tree[0],
-                track_ptree_luma ? ptree_luma->sub_tree[0] : NULL, rate);
+#if CONFIG_EXTENDED_SDP
+                pc_tree->horizontal[pc_tree->region_type][0],
+#else
+                pc_tree->horizontal[0],
+#endif  // CONFIG_EXTENDED_SDP
+                sub_tree[0], track_ptree_luma ? ptree_luma->sub_tree[0] : NULL,
+                rate);
       if (mi_row + hbs_h < cm->mi_params.mi_rows) {
         encode_sb(cpi, td, tile_data, tp, mi_row + hbs_h, mi_col, dry_run,
-                  subsize, pc_tree->horizontal[1], sub_tree[1],
+                  subsize,
+#if CONFIG_EXTENDED_SDP
+                  pc_tree->horizontal[pc_tree->region_type][1],
+#else
+                  pc_tree->horizontal[1],
+#endif  // CONFIG_EXTENDED_SDP
+                  sub_tree[1],
                   track_ptree_luma ? ptree_luma->sub_tree[1] : NULL, rate);
       }
 #else   // CONFIG_EXT_RECUR_PARTITIONS
@@ -2909,20 +2993,41 @@
       const BLOCK_SIZE bsize_med = subsize_lookup[PARTITION_HORZ][bsize_big];
       assert(subsize == subsize_lookup[PARTITION_HORZ][bsize_med]);
       encode_sb(cpi, td, tile_data, tp, mi_row, mi_col, dry_run, subsize,
-                pc_tree->horizontal4a[0], sub_tree[0],
-                track_ptree_luma ? ptree_luma->sub_tree[0] : NULL, rate);
+#if CONFIG_EXTENDED_SDP
+                pc_tree->horizontal4a[pc_tree->region_type][0],
+#else
+                pc_tree->horizontal4a[0],
+#endif  // CONFIG_EXTENDED_SDP
+                sub_tree[0], track_ptree_luma ? ptree_luma->sub_tree[0] : NULL,
+                rate);
       if (mi_row + ebs_h >= cm->mi_params.mi_rows) break;
-      encode_sb(cpi, td, tile_data, tp, mi_row + ebs_h, mi_col, dry_run,
-                bsize_med, pc_tree->horizontal4a[1], sub_tree[1],
-                track_ptree_luma ? ptree_luma->sub_tree[1] : NULL, rate);
+      encode_sb(
+          cpi, td, tile_data, tp, mi_row + ebs_h, mi_col, dry_run, bsize_med,
+#if CONFIG_EXTENDED_SDP
+          pc_tree->horizontal4a[pc_tree->region_type][1],
+#else
+          pc_tree->horizontal4a[1],
+#endif  // CONFIG_EXTENDED_SDP
+          sub_tree[1], track_ptree_luma ? ptree_luma->sub_tree[1] : NULL, rate);
       if (mi_row + 3 * ebs_h >= cm->mi_params.mi_rows) break;
       encode_sb(cpi, td, tile_data, tp, mi_row + 3 * ebs_h, mi_col, dry_run,
-                bsize_big, pc_tree->horizontal4a[2], sub_tree[2],
-                track_ptree_luma ? ptree_luma->sub_tree[2] : NULL, rate);
+                bsize_big,
+#if CONFIG_EXTENDED_SDP
+                pc_tree->horizontal4a[pc_tree->region_type][2],
+#else
+                pc_tree->horizontal4a[2],
+#endif  // CONFIG_EXTENDED_SDP
+                sub_tree[2], track_ptree_luma ? ptree_luma->sub_tree[2] : NULL,
+                rate);
       if (mi_row + 7 * ebs_h >= cm->mi_params.mi_rows) break;
-      encode_sb(cpi, td, tile_data, tp, mi_row + 7 * ebs_h, mi_col, dry_run,
-                subsize, pc_tree->horizontal4a[3], sub_tree[3],
-                track_ptree_luma ? ptree_luma->sub_tree[3] : NULL, rate);
+      encode_sb(
+          cpi, td, tile_data, tp, mi_row + 7 * ebs_h, mi_col, dry_run, subsize,
+#if CONFIG_EXTENDED_SDP
+          pc_tree->horizontal4a[pc_tree->region_type][3],
+#else
+          pc_tree->horizontal4a[3],
+#endif  // CONFIG_EXTENDED_SDP
+          sub_tree[3], track_ptree_luma ? ptree_luma->sub_tree[3] : NULL, rate);
       break;
     }
     case PARTITION_HORZ_4B: {
@@ -2930,20 +3035,41 @@
       const BLOCK_SIZE bsize_med = subsize_lookup[PARTITION_HORZ][bsize_big];
       assert(subsize == subsize_lookup[PARTITION_HORZ][bsize_med]);
       encode_sb(cpi, td, tile_data, tp, mi_row, mi_col, dry_run, subsize,
-                pc_tree->horizontal4b[0], sub_tree[0],
-                track_ptree_luma ? ptree_luma->sub_tree[0] : NULL, rate);
+#if CONFIG_EXTENDED_SDP
+                pc_tree->horizontal4b[pc_tree->region_type][0],
+#else
+                pc_tree->horizontal4b[0],
+#endif  // CONFIG_EXTENDED_SDP
+                sub_tree[0], track_ptree_luma ? ptree_luma->sub_tree[0] : NULL,
+                rate);
       if (mi_row + ebs_h >= cm->mi_params.mi_rows) break;
-      encode_sb(cpi, td, tile_data, tp, mi_row + ebs_h, mi_col, dry_run,
-                bsize_big, pc_tree->horizontal4b[1], sub_tree[1],
-                track_ptree_luma ? ptree_luma->sub_tree[1] : NULL, rate);
+      encode_sb(
+          cpi, td, tile_data, tp, mi_row + ebs_h, mi_col, dry_run, bsize_big,
+#if CONFIG_EXTENDED_SDP
+          pc_tree->horizontal4b[pc_tree->region_type][1],
+#else
+          pc_tree->horizontal4b[1],
+#endif  // CONFIG_EXTENDED_SDP
+          sub_tree[1], track_ptree_luma ? ptree_luma->sub_tree[1] : NULL, rate);
       if (mi_row + 5 * ebs_h >= cm->mi_params.mi_rows) break;
       encode_sb(cpi, td, tile_data, tp, mi_row + 5 * ebs_h, mi_col, dry_run,
-                bsize_med, pc_tree->horizontal4b[2], sub_tree[2],
-                track_ptree_luma ? ptree_luma->sub_tree[2] : NULL, rate);
+                bsize_med,
+#if CONFIG_EXTENDED_SDP
+                pc_tree->horizontal4b[pc_tree->region_type][2],
+#else
+                pc_tree->horizontal4b[2],
+#endif  // CONFIG_EXTENDED_SDP
+                sub_tree[2], track_ptree_luma ? ptree_luma->sub_tree[2] : NULL,
+                rate);
       if (mi_row + 7 * ebs_h >= cm->mi_params.mi_rows) break;
-      encode_sb(cpi, td, tile_data, tp, mi_row + 7 * ebs_h, mi_col, dry_run,
-                subsize, pc_tree->horizontal4b[3], sub_tree[3],
-                track_ptree_luma ? ptree_luma->sub_tree[3] : NULL, rate);
+      encode_sb(
+          cpi, td, tile_data, tp, mi_row + 7 * ebs_h, mi_col, dry_run, subsize,
+#if CONFIG_EXTENDED_SDP
+          pc_tree->horizontal4b[pc_tree->region_type][3],
+#else
+          pc_tree->horizontal4b[3],
+#endif  // CONFIG_EXTENDED_SDP
+          sub_tree[3], track_ptree_luma ? ptree_luma->sub_tree[3] : NULL, rate);
       break;
     }
     case PARTITION_VERT_4A: {
@@ -2951,20 +3077,41 @@
       const BLOCK_SIZE bsize_med = subsize_lookup[PARTITION_VERT][bsize_big];
       assert(subsize == subsize_lookup[PARTITION_VERT][bsize_med]);
       encode_sb(cpi, td, tile_data, tp, mi_row, mi_col, dry_run, subsize,
-                pc_tree->vertical4a[0], sub_tree[0],
-                track_ptree_luma ? ptree_luma->sub_tree[0] : NULL, rate);
+#if CONFIG_EXTENDED_SDP
+                pc_tree->vertical4a[pc_tree->region_type][0],
+#else
+                pc_tree->vertical4a[0],
+#endif  // CONFIG_EXTENDED_SDP
+                sub_tree[0], track_ptree_luma ? ptree_luma->sub_tree[0] : NULL,
+                rate);
       if (mi_col + ebs_w >= cm->mi_params.mi_cols) break;
-      encode_sb(cpi, td, tile_data, tp, mi_row, mi_col + ebs_w, dry_run,
-                bsize_med, pc_tree->vertical4a[1], sub_tree[1],
-                track_ptree_luma ? ptree_luma->sub_tree[1] : NULL, rate);
+      encode_sb(
+          cpi, td, tile_data, tp, mi_row, mi_col + ebs_w, dry_run, bsize_med,
+#if CONFIG_EXTENDED_SDP
+          pc_tree->vertical4a[pc_tree->region_type][1],
+#else
+          pc_tree->vertical4a[1],
+#endif  // CONFIG_EXTENDED_SDP
+          sub_tree[1], track_ptree_luma ? ptree_luma->sub_tree[1] : NULL, rate);
       if (mi_col + 3 * ebs_w >= cm->mi_params.mi_cols) break;
       encode_sb(cpi, td, tile_data, tp, mi_row, mi_col + 3 * ebs_w, dry_run,
-                bsize_big, pc_tree->vertical4a[2], sub_tree[2],
-                track_ptree_luma ? ptree_luma->sub_tree[2] : NULL, rate);
+                bsize_big,
+#if CONFIG_EXTENDED_SDP
+                pc_tree->vertical4a[pc_tree->region_type][2],
+#else
+                pc_tree->vertical4a[2],
+#endif  // CONFIG_EXTENDED_SDP
+                sub_tree[2], track_ptree_luma ? ptree_luma->sub_tree[2] : NULL,
+                rate);
       if (mi_col + 7 * ebs_w >= cm->mi_params.mi_cols) break;
-      encode_sb(cpi, td, tile_data, tp, mi_row, mi_col + 7 * ebs_w, dry_run,
-                subsize, pc_tree->vertical4a[3], sub_tree[3],
-                track_ptree_luma ? ptree_luma->sub_tree[3] : NULL, rate);
+      encode_sb(
+          cpi, td, tile_data, tp, mi_row, mi_col + 7 * ebs_w, dry_run, subsize,
+#if CONFIG_EXTENDED_SDP
+          pc_tree->vertical4a[pc_tree->region_type][3],
+#else
+          pc_tree->vertical4a[3],
+#endif  // CONFIG_EXTENDED_SDP
+          sub_tree[3], track_ptree_luma ? ptree_luma->sub_tree[3] : NULL, rate);
       break;
     }
     case PARTITION_VERT_4B: {
@@ -2972,20 +3119,41 @@
       const BLOCK_SIZE bsize_med = subsize_lookup[PARTITION_VERT][bsize_big];
       assert(subsize == subsize_lookup[PARTITION_VERT][bsize_med]);
       encode_sb(cpi, td, tile_data, tp, mi_row, mi_col, dry_run, subsize,
-                pc_tree->vertical4b[0], sub_tree[0],
-                track_ptree_luma ? ptree_luma->sub_tree[0] : NULL, rate);
+#if CONFIG_EXTENDED_SDP
+                pc_tree->vertical4b[pc_tree->region_type][0],
+#else
+                pc_tree->vertical4b[0],
+#endif  // CONFIG_EXTENDED_SDP
+                sub_tree[0], track_ptree_luma ? ptree_luma->sub_tree[0] : NULL,
+                rate);
       if (mi_col + ebs_w >= cm->mi_params.mi_cols) break;
-      encode_sb(cpi, td, tile_data, tp, mi_row, mi_col + ebs_w, dry_run,
-                bsize_big, pc_tree->vertical4b[1], sub_tree[1],
-                track_ptree_luma ? ptree_luma->sub_tree[1] : NULL, rate);
+      encode_sb(
+          cpi, td, tile_data, tp, mi_row, mi_col + ebs_w, dry_run, bsize_big,
+#if CONFIG_EXTENDED_SDP
+          pc_tree->vertical4b[pc_tree->region_type][1],
+#else
+          pc_tree->vertical4b[1],
+#endif  // CONFIG_EXTENDED_SDP
+          sub_tree[1], track_ptree_luma ? ptree_luma->sub_tree[1] : NULL, rate);
       if (mi_col + 5 * ebs_w >= cm->mi_params.mi_cols) break;
       encode_sb(cpi, td, tile_data, tp, mi_row, mi_col + 5 * ebs_w, dry_run,
-                bsize_med, pc_tree->vertical4b[2], sub_tree[2],
-                track_ptree_luma ? ptree_luma->sub_tree[2] : NULL, rate);
+                bsize_med,
+#if CONFIG_EXTENDED_SDP
+                pc_tree->vertical4b[pc_tree->region_type][2],
+#else
+                pc_tree->vertical4b[2],
+#endif  // CONFIG_EXTENDED_SDP
+                sub_tree[2], track_ptree_luma ? ptree_luma->sub_tree[2] : NULL,
+                rate);
       if (mi_col + 7 * ebs_w >= cm->mi_params.mi_cols) break;
-      encode_sb(cpi, td, tile_data, tp, mi_row, mi_col + 7 * ebs_w, dry_run,
-                subsize, pc_tree->vertical4b[3], sub_tree[3],
-                track_ptree_luma ? ptree_luma->sub_tree[3] : NULL, rate);
+      encode_sb(
+          cpi, td, tile_data, tp, mi_row, mi_col + 7 * ebs_w, dry_run, subsize,
+#if CONFIG_EXTENDED_SDP
+          pc_tree->vertical4b[pc_tree->region_type][3],
+#else
+          pc_tree->vertical4b[3],
+#endif  // CONFIG_EXTENDED_SDP
+          sub_tree[3], track_ptree_luma ? ptree_luma->sub_tree[3] : NULL, rate);
       break;
     }
     case PARTITION_HORZ_3:
@@ -2997,9 +3165,15 @@
         const int offset_c = get_h_partition_offset_mi_col(bsize, i, partition);
         const int this_mi_row = mi_row + offset_r;
         const int this_mi_col = mi_col + offset_c;
-        PC_TREE *this_pc_tree = partition == PARTITION_HORZ_3
-                                    ? pc_tree->horizontal3[i]
-                                    : pc_tree->vertical3[i];
+        PC_TREE *this_pc_tree =
+            partition == PARTITION_HORZ_3
+#if CONFIG_EXTENDED_SDP
+                ? pc_tree->horizontal3[pc_tree->region_type][i]
+                : pc_tree->vertical3[pc_tree->region_type][i];
+#else
+                ? pc_tree->horizontal3[i]
+                : pc_tree->vertical3[i];
+#endif  // CONFIG_EXTENDED_SDP
 
         if (partition == PARTITION_HORZ_3) {
           if (this_mi_row >= cm->mi_params.mi_rows) break;
@@ -3014,17 +3188,38 @@
     }
     case PARTITION_SPLIT:
       encode_sb(cpi, td, tile_data, tp, mi_row, mi_col, dry_run, subsize,
-                pc_tree->split[0], sub_tree[0],
-                track_ptree_luma ? ptree_luma->sub_tree[0] : NULL, rate);
-      encode_sb(cpi, td, tile_data, tp, mi_row, mi_col + hbs_w, dry_run,
-                subsize, pc_tree->split[1], sub_tree[1],
-                track_ptree_luma ? ptree_luma->sub_tree[1] : NULL, rate);
-      encode_sb(cpi, td, tile_data, tp, mi_row + hbs_h, mi_col, dry_run,
-                subsize, pc_tree->split[2], sub_tree[2],
-                track_ptree_luma ? ptree_luma->sub_tree[2] : NULL, rate);
+#if CONFIG_EXTENDED_SDP
+                pc_tree->split[pc_tree->region_type][0],
+#else
+                pc_tree->split[0],
+#endif  // CONFIG_EXTENDED_SDP
+                sub_tree[0], track_ptree_luma ? ptree_luma->sub_tree[0] : NULL,
+                rate);
+      encode_sb(
+          cpi, td, tile_data, tp, mi_row, mi_col + hbs_w, dry_run, subsize,
+#if CONFIG_EXTENDED_SDP
+          pc_tree->split[pc_tree->region_type][1],
+#else
+          pc_tree->split[1],
+#endif  // CONFIG_EXTENDED_SDP
+          sub_tree[1], track_ptree_luma ? ptree_luma->sub_tree[1] : NULL, rate);
+      encode_sb(
+          cpi, td, tile_data, tp, mi_row + hbs_h, mi_col, dry_run, subsize,
+#if CONFIG_EXTENDED_SDP
+          pc_tree->split[pc_tree->region_type][2],
+#else
+          pc_tree->split[2],
+#endif  // CONFIG_EXTENDED_SDP
+          sub_tree[2], track_ptree_luma ? ptree_luma->sub_tree[2] : NULL, rate);
       encode_sb(cpi, td, tile_data, tp, mi_row + hbs_h, mi_col + hbs_w, dry_run,
-                subsize, pc_tree->split[3], sub_tree[3],
-                track_ptree_luma ? ptree_luma->sub_tree[3] : NULL, rate);
+                subsize,
+#if CONFIG_EXTENDED_SDP
+                pc_tree->split[pc_tree->region_type][3],
+#else
+                pc_tree->split[3],
+#endif  // CONFIG_EXTENDED_SDP
+                sub_tree[3], track_ptree_luma ? ptree_luma->sub_tree[3] : NULL,
+                rate);
       break;
 #else   // CONFIG_EXT_RECUR_PARTITIONS
     case PARTITION_SPLIT:
@@ -3091,6 +3286,16 @@
     default: assert(0 && "Invalid partition type."); break;
   }
 
+#if CONFIG_EXTENDED_SDP
+  // encode the chroma blocks under one intra region in inter frame
+  if (encode_sdp_intra_region_yuv && !cm->seq_params.monochrome) {
+    xd->tree_type = CHROMA_PART;
+    encode_b(cpi, tile_data, td, tp, mi_row, mi_col, dry_run, bsize,
+             PARTITION_NONE, pc_tree->none_chroma, rate);
+    xd->tree_type = SHARED_PART;
+  }
+#endif  // CONFIG_EXTENDED_SDP
+
   if (ptree) ptree->is_settled = 1;
   update_ext_partition_context(xd, mi_row, mi_col, subsize, bsize, partition);
 }
@@ -3348,12 +3553,40 @@
   RD_SEARCH_MACROBLOCK_CONTEXT x_ctx;
   RD_STATS last_part_rdc, invalid_rdc;
 
+#if CONFIG_EXTENDED_SDP
+  if (!frame_is_intra_only(cm))
+    pc_tree->region_type = MIXED_INTER_INTRA_REGION;
+  else
+    pc_tree->region_type = INTRA_REGION;
+  REGION_TYPE cur_region_type = pc_tree->region_type;
+  if (is_inter_sdp_chroma(cm, cur_region_type, x->e_mbd.tree_type)) {
+    if (pc_tree->none_chroma == NULL) {
+      pc_tree->none_chroma =
+          av1_alloc_pmc(cm, xd->tree_type, mi_row, mi_col, bsize, pc_tree,
+                        PARTITION_NONE, 0, ss_x, ss_y, &td->shared_coeff_buf);
+    }
+  } else {
+    if (pc_tree->none[cur_region_type] == NULL) {
+      pc_tree->none[cur_region_type] =
+          av1_alloc_pmc(cm, xd->tree_type, mi_row, mi_col, bsize, pc_tree,
+                        PARTITION_NONE, 0, ss_x, ss_y, &td->shared_coeff_buf);
+    }
+  }
+#else
   if (pc_tree->none == NULL) {
     pc_tree->none =
         av1_alloc_pmc(cm, xd->tree_type, mi_row, mi_col, bsize, pc_tree,
                       PARTITION_NONE, 0, ss_x, ss_y, &td->shared_coeff_buf);
   }
+#endif  // CONFIG_EXTENDED_SDP
+#if CONFIG_EXTENDED_SDP
+  PICK_MODE_CONTEXT *ctx_none =
+      is_inter_sdp_chroma(cm, cur_region_type, x->e_mbd.tree_type)
+          ? pc_tree->none_chroma
+          : pc_tree->none[pc_tree->region_type];
+#else
   PICK_MODE_CONTEXT *ctx_none = pc_tree->none;
+#endif  // CONFIG_EXTENDED_SDP
 
   if (mi_row >= mi_params->mi_rows || mi_col >= mi_params->mi_cols) return;
 
@@ -3398,20 +3631,36 @@
   switch (partition) {
     case PARTITION_NONE:
       pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &last_part_rdc,
-                    PARTITION_NONE, bsize, ctx_none, invalid_rdc);
+                    PARTITION_NONE,
+#if CONFIG_EXTENDED_SDP
+                    pc_tree->region_type,
+#endif  // CONFIG_EXTENDED_SDP
+                    bsize, ctx_none, invalid_rdc);
       break;
     case PARTITION_HORZ:
 #if CONFIG_EXT_RECUR_PARTITIONS
+#if CONFIG_EXTENDED_SDP
+      pc_tree->horizontal[cur_region_type][0] =
+#else
       pc_tree->horizontal[0] =
+#endif  // CONFIG_EXTENDED_SDP
           av1_alloc_pc_tree_node(xd->tree_type, mi_row, mi_col, subsize,
                                  pc_tree, PARTITION_HORZ, 0, 0, ss_x, ss_y);
+#if CONFIG_EXTENDED_SDP
+      pc_tree->horizontal[cur_region_type][1] =
+#else
       pc_tree->horizontal[1] =
+#endif  // CONFIG_EXTENDED_SDP
           av1_alloc_pc_tree_node(xd->tree_type, mi_row + hbh, mi_col, subsize,
                                  pc_tree, PARTITION_HORZ, 1, 1, ss_x, ss_y);
       av1_rd_use_partition(cpi, td, tile_data, mib, tp, mi_row, mi_col, subsize,
                            &last_part_rdc.rate, &last_part_rdc.dist, 1,
                            ptree ? ptree->sub_tree[0] : NULL,
+#if CONFIG_EXTENDED_SDP
+                           pc_tree->horizontal[cur_region_type][0]);
+#else
                            pc_tree->horizontal[0]);
+#endif  // CONFIG_EXTENDED_SDP
 #else   // CONFIG_EXT_RECUR_PARTITIONS
       for (int i = 0; i < SUB_PARTITIONS_RECT; ++i) {
         if (pc_tree->horizontal[i] == NULL) {
@@ -3429,10 +3678,15 @@
         RD_STATS tmp_rdc;
         av1_init_rd_stats(&tmp_rdc);
 #if CONFIG_EXT_RECUR_PARTITIONS
-        av1_rd_use_partition(
-            cpi, td, tile_data, mib + hbh * mi_params->mi_stride, tp,
-            mi_row + hbh, mi_col, subsize, &tmp_rdc.rate, &tmp_rdc.dist, 0,
-            ptree ? ptree->sub_tree[1] : NULL, pc_tree->horizontal[1]);
+        av1_rd_use_partition(cpi, td, tile_data,
+                             mib + hbh * mi_params->mi_stride, tp, mi_row + hbh,
+                             mi_col, subsize, &tmp_rdc.rate, &tmp_rdc.dist, 0,
+                             ptree ? ptree->sub_tree[1] : NULL,
+#if CONFIG_EXTENDED_SDP
+                             pc_tree->horizontal[cur_region_type][1]);
+#else
+                             pc_tree->horizontal[1]);
+#endif  // CONFIG_EXTENDED_SDP
 #else   // CONFIG_EXT_RECUR_PARTITIONS
         const PICK_MODE_CONTEXT *const ctx_h = pc_tree->horizontal[0];
         av1_update_state(cpi, td, ctx_h, mi_row, mi_col, subsize, 1);
@@ -3453,16 +3707,28 @@
       break;
     case PARTITION_VERT:
 #if CONFIG_EXT_RECUR_PARTITIONS
+#if CONFIG_EXTENDED_SDP
+      pc_tree->vertical[cur_region_type][0] =
+#else
       pc_tree->vertical[0] =
+#endif  // CONFIG_EXTENDED_SDP
           av1_alloc_pc_tree_node(xd->tree_type, mi_row, mi_col, subsize,
                                  pc_tree, PARTITION_VERT, 0, 0, ss_x, ss_y);
+#if CONFIG_EXTENDED_SDP
+      pc_tree->vertical[cur_region_type][1] =
+#else
       pc_tree->vertical[1] =
+#endif  // CONFIG_EXTENDED_SDP
           av1_alloc_pc_tree_node(xd->tree_type, mi_row, mi_col + hbw, subsize,
                                  pc_tree, PARTITION_VERT, 1, 1, ss_x, ss_y);
       av1_rd_use_partition(cpi, td, tile_data, mib, tp, mi_row, mi_col, subsize,
                            &last_part_rdc.rate, &last_part_rdc.dist, 1,
                            ptree ? ptree->sub_tree[0] : NULL,
+#if CONFIG_EXTENDED_SDP
+                           pc_tree->vertical[cur_region_type][0]);
+#else
                            pc_tree->vertical[0]);
+#endif  // CONFIG_EXTENDED_SDP
 #else   // CONFIG_EXT_RECUR_PARTITIONS
       for (int i = 0; i < SUB_PARTITIONS_RECT; ++i) {
         if (pc_tree->vertical[i] == NULL) {
@@ -3482,7 +3748,11 @@
         av1_rd_use_partition(
             cpi, td, tile_data, mib + hbw, tp, mi_row, mi_col + hbw, subsize,
             &tmp_rdc.rate, &tmp_rdc.dist, 0, ptree ? ptree->sub_tree[1] : NULL,
+#if CONFIG_EXTENDED_SDP
+            pc_tree->vertical[cur_region_type][1]);
+#else
             pc_tree->vertical[1]);
+#endif  // CONFIG_EXTENDED_SDP
 #else   // CONFIG_EXT_RECUR_PARTITIONS
         const PICK_MODE_CONTEXT *const ctx_v = pc_tree->vertical[0];
         av1_update_state(cpi, td, ctx_v, mi_row, mi_col, subsize, 1);
@@ -3514,17 +3784,27 @@
         if ((mi_row + y_idx >= mi_params->mi_rows) ||
             (mi_col + x_idx >= mi_params->mi_cols))
           continue;
-        pc_tree->split[i] = av1_alloc_pc_tree_node(
-            xd->tree_type, mi_row + y_idx, mi_col + x_idx, subsize, pc_tree,
-            PARTITION_SPLIT, i, i == 3, ss_x, ss_y);
+#if CONFIG_EXTENDED_SDP
+        pc_tree->split[cur_region_type][i]
+#else
+        pc_tree->split[i]
+#endif  // CONFIG_EXTENDED_SDP
+            = av1_alloc_pc_tree_node(xd->tree_type, mi_row + y_idx,
+                                     mi_col + x_idx, subsize, pc_tree,
+                                     PARTITION_SPLIT, i, i == 3, ss_x, ss_y);
 
         av1_init_rd_stats(&tmp_rdc);
-        av1_rd_use_partition(
-            cpi, td, tile_data,
-            mib + jj * hbs * mi_params->mi_stride + ii * hbs, tp,
-            mi_row + y_idx, mi_col + x_idx, subsize, &tmp_rdc.rate,
-            &tmp_rdc.dist, i != (SUB_PARTITIONS_SPLIT - 1),
-            ptree ? ptree->sub_tree[i] : NULL, pc_tree->split[i]);
+        av1_rd_use_partition(cpi, td, tile_data,
+                             mib + jj * hbs * mi_params->mi_stride + ii * hbs,
+                             tp, mi_row + y_idx, mi_col + x_idx, subsize,
+                             &tmp_rdc.rate, &tmp_rdc.dist,
+                             i != (SUB_PARTITIONS_SPLIT - 1),
+                             ptree ? ptree->sub_tree[i] : NULL,
+#if CONFIG_EXTENDED_SDP
+                             pc_tree->split[cur_region_type][i]);
+#else
+                             pc_tree->split[i]);
+#endif  // CONFIG_EXTENDED_SDP
         if (tmp_rdc.rate == INT_MAX || tmp_rdc.dist == INT64_MAX) {
           av1_invalid_rd_stats(&last_part_rdc);
           break;
@@ -3686,6 +3966,9 @@
   av1_rd_stats_subtraction(x->rdmult, &best_rdcost, sum_rdc, &rdcost_remaining);
   RD_STATS this_rdc;
   pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &this_rdc, partition,
+#if CONFIG_EXTENDED_SDP
+                pc_tree->region_type,
+#endif  // CONFIG_EXTENDED_SDP
                 subsize, this_ctx, rdcost_remaining);
 
   if (this_rdc.rate == INT_MAX) {
@@ -3759,6 +4042,12 @@
   update_best_level_banks(level_banks, &x->e_mbd);
 #endif  // CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
   pc_tree->partitioning = partition;
+#if CONFIG_EXTENDED_SDP
+  if (!frame_is_intra_only(cm))
+    pc_tree->region_type = MIXED_INTER_INTRA_REGION;
+  else
+    pc_tree->region_type = INTRA_REGION;
+#endif  // CONFIG_EXTENDED_SDP
   return true;
 }
 #endif  // !CONFIG_EXT_RECUR_PARTITIONS
@@ -3771,6 +4060,9 @@
     BLOCK_SIZE parent_bsize,
 #endif  // CONFIG_CB1TO4_SPLIT
     const PARTITION_TREE *ptree_luma, const PARTITION_TREE *template_tree,
+#if CONFIG_EXTENDED_SDP
+    REGION_TYPE cur_region_type,
+#endif  // CONFIG_EXTENDED_SDP
     const CHROMA_REF_INFO *chroma_ref_info) {
   // Partition types forced by bitstream syntax.
   const MACROBLOCKD *xd = &x->e_mbd;
@@ -3796,6 +4088,9 @@
 #if CONFIG_CB1TO4_SPLIT
       && (parent_bsize == BLOCK_INVALID || parent_bsize <= BLOCK_LARGEST)
 #endif  // CONFIG_CB1TO4_SPLIT
+#if CONFIG_EXTENDED_SDP
+      && !is_inter_sdp_chroma(cm, cur_region_type, xd->tree_type)
+#endif  // CONFIG_EXTENDED_SDP
   ) {
     return av1_get_prev_partition(x, mi_row, mi_col, bsize, cm->sb_size);
   }
@@ -3984,6 +4279,7 @@
   blk_params->bsize = bsize;
 
 #if CONFIG_CB1TO4_SPLIT
+  assert(pc_tree != NULL);
   blk_params->parent_bsize =
       pc_tree->parent ? pc_tree->parent->block_size : BLOCK_INVALID;
 #endif  // CONFIG_CB1TO4_SPLIT
@@ -4046,6 +4342,13 @@
   }
 #endif  // CONFIG_EXT_RECUR_PARTITIONS
 
+#if CONFIG_EXTENDED_SDP
+  if (xd->tree_type != CHROMA_PART) {
+    const int ctx = get_intra_region_context(bsize);
+    part_search_state->region_type_cost = mode_costs->region_type_cost[ctx];
+  }
+#endif  // CONFIG_EXTENDED_SDP
+
   // Initialize HORZ and VERT win flags as true for all split partitions.
   for (int i = 0; i < SUB_PARTITIONS_SPLIT; i++) {
     part_search_state->split_part_rect_win[i].rect_part_win[HORZ] = true;
@@ -4085,7 +4388,11 @@
 #if CONFIG_CB1TO4_SPLIT
       blk_params->parent_bsize,
 #endif  // CONFIG_CB1TO4_SPLIT
-      ptree_luma, template_tree, &pc_tree->chroma_ref_info);
+      ptree_luma, template_tree,
+#if CONFIG_EXTENDED_SDP
+      (pc_tree ? pc_tree->region_type : MIXED_INTER_INTRA_REGION),
+#endif  // CONFIG_EXTENDED_SDP
+      &pc_tree->chroma_ref_info);
 
   init_allowed_partitions(part_search_state, &cpi->oxcf.part_cfg,
                           &pc_tree->chroma_ref_info, tree_type);
@@ -4228,7 +4535,11 @@
 
   // Obtain the best mode for the partition sub-block.
   pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, &part_search_state->this_rdc,
-                partition_type, bsize, cur_partition_ctx, best_remain_rdcost);
+                partition_type,
+#if CONFIG_EXTENDED_SDP
+                pc_tree->region_type,
+#endif  // CONFIG_EXTENDED_SDP
+                bsize, cur_partition_ctx, best_remain_rdcost);
   av1_rd_cost_update(x->rdmult, &part_search_state->this_rdc);
 
   // Update the partition rd cost with the current sub-block rd.
@@ -4254,6 +4565,9 @@
     BLOCK_SIZE bsize, const int is_not_edge_block[NUM_RECT_PARTS],
     SB_MULTI_PASS_MODE multi_pass_mode, const PARTITION_TREE *ptree_luma,
     const PARTITION_TREE *template_tree, bool *both_blocks_skippable,
+#if CONFIG_EXTENDED_SDP
+    PARTITION_TYPE parent_partition,
+#endif  // CONFIG_INTER_SDP
     int max_recursion_depth
 #if CONFIG_ML_PART_SPLIT
     ,
@@ -4264,18 +4578,35 @@
   RD_STATS *sum_rdc = &part_search_state->sum_rdc;
 
   sum_rdc->rate = part_search_state->partition_cost[partition_type];
+#if CONFIG_EXTENDED_SDP
+  if (pc_tree->region_type == MIXED_INTER_INTRA_REGION && pc_tree->parent &&
+      is_inter_sdp_allowed(pc_tree->parent->block_size, parent_partition) &&
+      is_bsize_allowed_for_inter_sdp(bsize, PARTITION_HORZ))
+    sum_rdc->rate +=
+        part_search_state->region_type_cost[MIXED_INTER_INTRA_REGION];
+#endif  // CONFIG_EXTENDED_SDP
   sum_rdc->rdcost = RDCOST(x->rdmult, sum_rdc->rate, 0);
 
   RD_STATS this_rdc;
   RD_STATS best_remain_rdcost;
+#if CONFIG_EXTENDED_SDP
+  PC_TREE **sub_tree = (rect_type == HORZ)
+                           ? pc_tree->horizontal[pc_tree->region_type]
+                           : pc_tree->vertical[pc_tree->region_type];
+#else
   PC_TREE **sub_tree =
       (rect_type == HORZ) ? pc_tree->horizontal : pc_tree->vertical;
+#endif  // CONFIG_EXTENDED_SDP
   *both_blocks_skippable = true;
   av1_rd_stats_subtraction(x->rdmult, best_rdc, sum_rdc, &best_remain_rdcost);
   bool partition_found = av1_rd_pick_partition(
       cpi, td, tile_data, tp, mi_pos_rect[rect_type][0][0],
-      mi_pos_rect[rect_type][0][1], bsize, &this_rdc, best_remain_rdcost,
-      sub_tree[0], get_partition_subtree_const(ptree_luma, 0),
+      mi_pos_rect[rect_type][0][1], bsize,
+#if CONFIG_EXTENDED_SDP
+      (rect_type == HORZ ? PARTITION_HORZ : PARTITION_VERT),
+#endif  // CONFIG_EXTENDED_SDP
+      &this_rdc, best_remain_rdcost, sub_tree[0],
+      get_partition_subtree_const(ptree_luma, 0),
       get_partition_subtree_const(template_tree, 0), max_recursion_depth, NULL,
       NULL, multi_pass_mode, NULL
 #if CONFIG_ML_PART_SPLIT
@@ -4299,8 +4630,12 @@
     av1_rd_stats_subtraction(x->rdmult, best_rdc, sum_rdc, &best_remain_rdcost);
     partition_found = av1_rd_pick_partition(
         cpi, td, tile_data, tp, mi_pos_rect[rect_type][1][0],
-        mi_pos_rect[rect_type][1][1], bsize, &this_rdc, best_remain_rdcost,
-        sub_tree[1], get_partition_subtree_const(ptree_luma, 1),
+        mi_pos_rect[rect_type][1][1], bsize,
+#if CONFIG_EXTENDED_SDP
+        (rect_type == HORZ ? PARTITION_HORZ : PARTITION_VERT),
+#endif  // CONFIG_EXTENDED_SDP
+        &this_rdc, best_remain_rdcost, sub_tree[1],
+        get_partition_subtree_const(ptree_luma, 1),
         get_partition_subtree_const(template_tree, 1), max_recursion_depth,
         NULL, NULL, multi_pass_mode, NULL
 #if CONFIG_ML_PART_SPLIT
@@ -4397,6 +4732,9 @@
 #if CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
     LevelBanksRDO *level_banks,
 #endif  // CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
+#if CONFIG_EXTENDED_SDP
+    PARTITION_TYPE parent_partition,
+#endif  // CONFIG_INTER_SDP
     int64_t part_none_rd
 #if CONFIG_ML_PART_SPLIT
     ,
@@ -4515,7 +4853,13 @@
       continue;
     }
 
+#if CONFIG_EXTENDED_SDP
+    const REGION_TYPE cur_region_type = pc_tree->region_type;
+    PC_TREE **sub_tree = (i == HORZ) ? pc_tree->horizontal[cur_region_type]
+                                     : pc_tree->vertical[cur_region_type];
+#else
     PC_TREE **sub_tree = (i == HORZ) ? pc_tree->horizontal : pc_tree->vertical;
+#endif  // CONFIG_EXTENDED_SDP
     assert(sub_tree);
 
     const int num_planes = av1_num_planes(cm);
@@ -4543,7 +4887,11 @@
         cpi, td, tile_data, tp, x, pc_tree, part_search_state, best_rdc, i,
         mi_pos_rect, blk_params.subsize, is_not_edge_block, multi_pass_mode,
         track_ptree_luma ? ptree_luma : NULL, template_tree,
-        &both_blocks_skippable, max_recursion_depth
+        &both_blocks_skippable,
+#if CONFIG_EXTENDED_SDP
+        parent_partition,
+#endif  // CONFIG_INTER_SDP
+        max_recursion_depth
 #if CONFIG_ML_PART_SPLIT
         ,
         next_force_prune_flags[i]
@@ -4965,6 +5313,12 @@
 #endif  // CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
     part_search_state->found_best_partition = true;
     pc_tree->partitioning = partition_type;
+#if CONFIG_EXTENDED_SDP
+    if (!frame_is_intra_only(cm))
+      pc_tree->region_type = MIXED_INTER_INTRA_REGION;
+    else
+      pc_tree->region_type = INTRA_REGION;
+#endif  // CONFIG_EXTENDED_SDP
   }
 #if CONFIG_COLLECT_PARTITION_STATS
   if (partition_timer_on) {
@@ -5078,6 +5432,9 @@
 #if CONFIG_EXT_RECUR_PARTITIONS
     TREE_TYPE tree_type,
 #endif  // CONFIG_EXT_RECUR_PARTITIONS
+#if CONFIG_EXTENDED_SDP
+    int sdp_inter_chroma_flag,
+#endif  // CONFIG_EXTENDED_SDP
     PartitionSearchState *part_search_state) {
   PartitionBlkParams blk_params = part_search_state->part_blk_params;
 #if CONFIG_EXT_RECUR_PARTITIONS
@@ -5086,6 +5443,12 @@
     return;
   }
 #endif  // CONFIG_EXT_RECUR_PARTITIONS
+#if CONFIG_EXTENDED_SDP
+  if (sdp_inter_chroma_flag) {
+    part_search_state->partition_none_allowed = 1;
+    return;
+  }
+#endif  // CONFIG_EXTENDED_SDP
 #if CONFIG_EXT_RECUR_PARTITIONS
   if (is_bsize_geq(blk_params.min_partition_size, blk_params.bsize) &&
       blk_params.has_rows && blk_params.has_cols)
@@ -5118,15 +5481,37 @@
   PartitionBlkParams blk_params = part_search_state->part_blk_params;
   RD_STATS partition_rdcost;
   // Set PARTITION_NONE context.
+#if CONFIG_EXTENDED_SDP
+  if (is_inter_sdp_chroma(cm, pc_tree->region_type, x->e_mbd.tree_type)) {
+    if (pc_tree->none_chroma == NULL) {
+      pc_tree->none_chroma = av1_alloc_pmc(
+          cm, x->e_mbd.tree_type, blk_params.mi_row, blk_params.mi_col,
+          blk_params.bsize, pc_tree, PARTITION_NONE, 0, part_search_state->ss_x,
+          part_search_state->ss_y, &td->shared_coeff_buf);
+    }
+  } else {
+    if (pc_tree->none[pc_tree->region_type] == NULL) {
+      pc_tree->none[pc_tree->region_type] = av1_alloc_pmc(
+          cm, x->e_mbd.tree_type, blk_params.mi_row, blk_params.mi_col,
+          blk_params.bsize, pc_tree, PARTITION_NONE, 0, part_search_state->ss_x,
+          part_search_state->ss_y, &td->shared_coeff_buf);
+    }
+  }
+#else
   if (pc_tree->none == NULL)
     pc_tree->none = av1_alloc_pmc(
         cm, x->e_mbd.tree_type, blk_params.mi_row, blk_params.mi_col,
         blk_params.bsize, pc_tree, PARTITION_NONE, 0, part_search_state->ss_x,
         part_search_state->ss_y, &td->shared_coeff_buf);
+#endif  // CONFIG_EXTENDED_SDP
 
   // Set PARTITION_NONE type cost.
   if (part_search_state->partition_none_allowed) {
-    if (part_search_state->is_block_splittable) {
+    if (part_search_state->is_block_splittable
+#if CONFIG_EXTENDED_SDP
+        && !is_inter_sdp_chroma(cm, pc_tree->region_type, x->e_mbd.tree_type)
+#endif  // CONFIG_EXTENDED_SDP
+    ) {
       *pt_cost = part_search_state->partition_cost[PARTITION_NONE] < INT_MAX
                      ? part_search_state->partition_cost[PARTITION_NONE]
                      : 0;
@@ -5290,6 +5675,50 @@
 }
 #endif
 
+#if CONFIG_EXTENDED_SDP
+static void inter_sdp_copy_luma_mode_info(PC_TREE *pc_tree,
+                                          PICK_MODE_CONTEXT *ctx_chroma_none,
+                                          MB_MODE_INFO *mbmi) {
+  PC_TREE *cur_pc_tree = pc_tree;
+  PARTITION_TYPE partition = cur_pc_tree->partitioning;
+  while (partition) {
+    switch (partition) {
+      case PARTITION_HORZ:
+        cur_pc_tree = cur_pc_tree->horizontal[INTRA_REGION][0];
+        break;
+      case PARTITION_VERT:
+        cur_pc_tree = cur_pc_tree->vertical[INTRA_REGION][0];
+        break;
+      case PARTITION_SPLIT:
+        cur_pc_tree = cur_pc_tree->split[INTRA_REGION][0];
+        break;
+      case PARTITION_HORZ_4A:
+        cur_pc_tree = cur_pc_tree->horizontal4a[INTRA_REGION][0];
+        break;
+      case PARTITION_HORZ_4B:
+        cur_pc_tree = cur_pc_tree->horizontal4b[INTRA_REGION][0];
+        break;
+      case PARTITION_VERT_4A:
+        cur_pc_tree = cur_pc_tree->vertical4a[INTRA_REGION][0];
+        break;
+      case PARTITION_VERT_4B:
+        cur_pc_tree = cur_pc_tree->vertical4b[INTRA_REGION][0];
+        break;
+      case PARTITION_VERT_3:
+        cur_pc_tree = cur_pc_tree->vertical3[INTRA_REGION][0];
+        break;
+      case PARTITION_HORZ_3:
+        cur_pc_tree = cur_pc_tree->horizontal3[INTRA_REGION][0];
+        break;
+      default: assert(0 && "Invalid partition type!"); break;
+    }
+    partition = cur_pc_tree->partitioning;
+  }
+  ctx_chroma_none->mic = cur_pc_tree->none[INTRA_REGION]->mic;
+  *mbmi = cur_pc_tree->none[INTRA_REGION]->mic;
+}
+#endif  // CONFIG_EXTENDED_SDP
+
 // PARTITION_NONE search.
 static void none_partition_search(
     AV1_COMP *const cpi, ThreadData *td, TileDataEnc *tile_data, MACROBLOCK *x,
@@ -5315,17 +5744,29 @@
     return;
   }
 #endif  // CONFIG_EXT_RECUR_PARTITIONS
+
+#if CONFIG_EXTENDED_SDP
+  int sdp_inter_chroma_flag =
+      is_inter_sdp_chroma(cm, pc_tree->region_type, x->e_mbd.tree_type);
+#endif  // CONFIG_EXTENDED_SDP
   // Set PARTITION_NONE allowed flag.
   set_part_none_allowed_flag(cpi,
 #if CONFIG_EXT_RECUR_PARTITIONS
                              x->e_mbd.tree_type,
 #endif  // CONFIG_EXT_RECUR_PARTITIONS
+#if CONFIG_EXTENDED_SDP
+                             sdp_inter_chroma_flag,
+#endif  // CONFIG_EXTENDED_SDP
                              part_search_state);
   if (!part_search_state->partition_none_allowed) {
     return;
   }
 #if CONFIG_EXT_RECUR_PARTITIONS
-  if (part_search_state->prune_partition_none) {
+  if (part_search_state->prune_partition_none
+#if CONFIG_EXTENDED_SDP
+      && !sdp_inter_chroma_flag
+#endif  // CONFIG_EXTENDED_SDP
+  ) {
     return;
   }
 #endif  // CONFIG_EXT_RECUR_PARTITIONS
@@ -5337,6 +5778,16 @@
   set_none_partition_params(cm, td, x, pc_tree, part_search_state,
                             &best_remain_rdcost, best_rdc, &pt_cost);
 
+#if CONFIG_EXTENDED_SDP
+  REGION_TYPE cur_region_type = pc_tree->region_type;
+  PICK_MODE_CONTEXT *ctx_none = sdp_inter_chroma_flag
+                                    ? pc_tree->none_chroma
+                                    : pc_tree->none[pc_tree->region_type];
+  if (sdp_inter_chroma_flag) {
+    inter_sdp_copy_luma_mode_info(pc_tree, ctx_none, x->e_mbd.mi[0]);
+  }
+#endif  // CONFIG_EXTENDED_SDP
+
 #if CONFIG_COLLECT_PARTITION_STATS
   // Timer start for partition None.
   if (best_remain_rdcost >= 0) {
@@ -5353,11 +5804,30 @@
 
   // PARTITION_NONE evaluation and cost update.
   pick_sb_modes(cpi, tile_data, x, mi_row, mi_col, this_rdc, PARTITION_NONE,
-                bsize, pc_tree->none, best_remain_rdcost);
+#if CONFIG_EXTENDED_SDP
+                pc_tree->region_type,
+#endif  // CONFIG_EXTENDED_SDP
+                bsize,
+#if CONFIG_EXTENDED_SDP
+                ctx_none,
+#else
+                pc_tree->none,
+#endif  // CONFIG_EXTENDED_SDP
+                best_remain_rdcost);
 #if CONFIG_EXT_RECUR_PARTITIONS
   x->inter_mode_cache = NULL;
-  if (this_rdc->rate != INT_MAX) {
-    av1_add_mode_search_context_to_cache(sms_data, pc_tree->none);
+  if (this_rdc->rate != INT_MAX
+#if CONFIG_EXTENDED_SDP
+      && !is_inter_sdp_chroma(cm, cur_region_type, x->e_mbd.tree_type)
+#endif  // CONFIG_EXTENDED_SDP
+  ) {
+    av1_add_mode_search_context_to_cache(sms_data,
+#if CONFIG_EXTENDED_SDP
+                                         pc_tree->none[pc_tree->region_type]
+#else
+                                         pc_tree->none
+#endif  // CONFIG_EXTENDED_SDP
+    );
   }
 #endif  // CONFIG_EXT_RECUR_PARTITIONS
   av1_rd_cost_update(x->rdmult, this_rdc);
@@ -5375,21 +5845,44 @@
   if (none_rd) *none_rd = this_rdc->rdcost;
   part_search_state->none_rd = this_rdc->rdcost;
 #if CONFIG_EXT_RECUR_PARTITIONS
-  pc_tree->none_rd = *this_rdc;
+#if CONFIG_EXTENDED_SDP
+  if (pc_tree->region_type == MIXED_INTER_INTRA_REGION ||
+      frame_is_intra_only(cm))
+#endif  // CONFIG_EXTENDED_SDP
+    pc_tree->none_rd = *this_rdc;
 #endif  // CONFIG_EXT_RECUR_PARTITIONS
   if (this_rdc->rate != INT_MAX) {
 #if CONFIG_EXT_RECUR_PARTITIONS
+#if CONFIG_EXTENDED_SDP
+    pc_tree->skippable = sdp_inter_chroma_flag
+                             ? pc_tree->none_chroma->skippable
+                             : pc_tree->none[pc_tree->region_type]->skippable;
+#else
     pc_tree->skippable = pc_tree->none->skippable;
+#endif  // CONFIG_EXTENDED_SDP
 #endif  // CONFIG_EXT_RECUR_PARTITIONS
     // Record picked ref frame to prune ref frames for other partition types.
-    if (cpi->sf.inter_sf.prune_ref_frames) {
+    if (cpi->sf.inter_sf.prune_ref_frames
+#if CONFIG_EXTENDED_SDP
+        && x->e_mbd.tree_type != CHROMA_PART
+#endif  // CONFIG_EXTENDED_SDP
+    ) {
+#if CONFIG_EXTENDED_SDP
+      const int ref_type = av1_ref_frame_type(
+          pc_tree->none[pc_tree->region_type]->mic.ref_frame);
+#else
       const int ref_type = av1_ref_frame_type(pc_tree->none->mic.ref_frame);
+#endif  // CONFIG_EXTENDED_SDP
       av1_update_picked_ref_frames_mask(x, ref_type, bsize, cm->mib_size,
                                         mi_row, mi_col);
     }
 
     // Calculate the total cost and update the best partition.
-    if (part_search_state->is_block_splittable) {
+    if (part_search_state->is_block_splittable
+#if CONFIG_EXTENDED_SDP
+        && !sdp_inter_chroma_flag
+#endif  // CONFIG_EXTENDED_SDP
+    ) {
       this_rdc->rate += pt_cost;
       this_rdc->rdcost = RDCOST(x->rdmult, this_rdc->rate, this_rdc->dist);
     }
@@ -5405,14 +5898,26 @@
         pc_tree->partitioning = PARTITION_NONE;
       }
 #else
-      pc_tree->partitioning = PARTITION_NONE;
+#if CONFIG_EXTENDED_SDP
+      if (!sdp_inter_chroma_flag)
+#endif  // CONFIG_EXTENDED_SDP
+        pc_tree->partitioning = PARTITION_NONE;
 #endif  // !CONFIG_EXT_RECUR_PARTITIONS
 
       // Disable split and rectangular partition search
       // based on PARTITION_NONE cost.
-      prune_partitions_after_none(cpi, x, sms_tree, pc_tree->none,
-                                  part_search_state, best_rdc,
-                                  pb_source_variance);
+#if CONFIG_EXTENDED_SDP
+      if (frame_is_intra_only(cm) || cur_region_type != INTRA_REGION ||
+          x->e_mbd.tree_type != CHROMA_PART)
+#endif  // CONFIG_EXTENDED_SDP
+        prune_partitions_after_none(cpi, x, sms_tree,
+#if CONFIG_EXTENDED_SDP
+                                    pc_tree->none[pc_tree->region_type],
+#else
+                                  pc_tree->none,
+#endif  // CONFIG_EXTENDED_SDP
+                                    part_search_state, best_rdc,
+                                    pb_source_variance);
     }
   }
   av1_restore_context(cm, x, x_ctx, mi_row, mi_col, bsize, av1_num_planes(cm));
@@ -5469,7 +5974,11 @@
   }
 
   const int num_planes = av1_num_planes(cm);
+#if CONFIG_EXTENDED_SDP
+  PC_TREE **sub_tree = pc_tree->split[pc_tree->region_type];
+#else
   PC_TREE **sub_tree = pc_tree->split;
+#endif  // CONFIG_EXTENDED_SDP
   assert(sub_tree);
   for (int idx = 0; idx < SUB_PARTITIONS_SPLIT; idx++) {
     if (sub_tree[idx]) {
@@ -5509,9 +6018,16 @@
     if (mi_row + y_idx >= mi_params->mi_rows ||
         mi_col + x_idx >= mi_params->mi_cols)
       continue;
-
+#if CONFIG_EXTENDED_SDP
+    if (pc_tree->split[pc_tree->region_type][idx] == NULL) {
+#else
     if (pc_tree->split[idx] == NULL) {
+#endif  // CONFIG_EXTENDED_SDP
+#if CONFIG_EXTENDED_SDP
+      pc_tree->split[pc_tree->region_type][idx] = av1_alloc_pc_tree_node(
+#else
       pc_tree->split[idx] = av1_alloc_pc_tree_node(
+#endif
           x->e_mbd.tree_type, mi_row + y_idx, mi_col + x_idx, subsize, pc_tree,
           PARTITION_SPLIT, idx, idx == 3, part_search_state->ss_x,
           part_search_state->ss_y);
@@ -5538,6 +6054,9 @@
 #endif  // CONFIG_ML_PART_SPLIT
     if (!av1_rd_pick_partition(
             cpi, td, tile_data, tp, mi_row + y_idx, mi_col + x_idx, subsize,
+#if CONFIG_EXTENDED_SDP
+            PARTITION_SPLIT,
+#endif  // CONFIG_EXTENDED_SDP
             &part_search_state->this_rdc, best_remain_rdcost, sub_tree[idx],
             track_ptree_luma ? ptree_luma->sub_tree[idx] : NULL,
             get_partition_subtree_const(template_tree, idx),
@@ -5569,8 +6088,21 @@
 
     // Set split ctx as ready for use.
     if (idx <= 1 && (bsize <= BLOCK_8X8 ||
-                     pc_tree->split[idx]->partitioning == PARTITION_NONE)) {
+#if CONFIG_EXTENDED_SDP
+                     pc_tree->split[pc_tree->region_type][idx]->partitioning ==
+                         PARTITION_NONE
+#else
+                     pc_tree->split[idx]->partitioning == PARTITION_NONE
+#endif  // CONFIG_EXTENDED_SDP
+                     )) {
+#if CONFIG_EXTENDED_SDP
+      const MB_MODE_INFO *const mbmi =
+          &pc_tree->split[pc_tree->region_type][idx]
+               ->none[pc_tree->region_type]
+               ->mic;
+#else
       const MB_MODE_INFO *const mbmi = &pc_tree->split[idx]->none->mic;
+#endif  // CONFIG_EXTENDED_SDP
       const PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
       // Neither palette mode nor cfl predicted.
       if (pmi->palette_size[0] == 0 && pmi->palette_size[1] == 0) {
@@ -5687,6 +6219,9 @@
   int force_prune_flags[3] = { 0, 0, 0 };
 #endif  // CONFIG_ML_PART_SPLIT
   if (!av1_rd_pick_partition(cpi, td, tile_data, tp, mi_row, mi_col, bsize,
+#if CONFIG_EXTENDED_SDP
+                             rdo_data->partition,
+#endif  // CONFIG_EXTENDED_SDP
                              &this_rdc, rdcost_remaining, rdo_data->pc_tree,
                              rdo_data->ptree_luma, rdo_data->template_tree,
                              max_recursion_depth, NULL, NULL, multi_pass_mode,
@@ -5739,6 +6274,9 @@
   const int ebs_w = mi_size_wide[bsize] / 8;
   const int ebs_h = mi_size_high[bsize] / 8;
   const BLOCK_SIZE subsize = get_partition_subsize(bsize, partition);
+#if CONFIG_EXTENDED_SDP
+  REGION_TYPE cur_region_type = pc_tree->region_type;
+#endif  // CONFIG_EXTENDED_SDP
   switch (partition) {
     case PARTITION_NONE:
       for (int col = 0; col < mi_width; col++) {
@@ -5751,52 +6289,113 @@
       }
       break;
     case PARTITION_HORZ:
-      trace_partition_boundary(partition_boundaries, pc_tree->horizontal[0],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->horizontal[cur_region_type][0],
+#else
+                               pc_tree->horizontal[0],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row, mi_col,
                                get_partition_subsize(bsize, PARTITION_HORZ));
-      trace_partition_boundary(partition_boundaries, pc_tree->horizontal[1],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->horizontal[cur_region_type][1],
+#else
+                               pc_tree->horizontal[1],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row + mi_height / 2, mi_col,
                                get_partition_subsize(bsize, PARTITION_HORZ));
       break;
     case PARTITION_VERT:
-      trace_partition_boundary(partition_boundaries, pc_tree->vertical[0],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->vertical[cur_region_type][0],
+#else
+                               pc_tree->vertical[0],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row, mi_col,
                                get_partition_subsize(bsize, PARTITION_VERT));
-      trace_partition_boundary(partition_boundaries, pc_tree->vertical[1],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->vertical[cur_region_type][1],
+#else
+                               pc_tree->vertical[1],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row, mi_col + mi_width / 2,
                                get_partition_subsize(bsize, PARTITION_VERT));
       break;
     case PARTITION_HORZ_3:
       trace_partition_boundary(
-          partition_boundaries, pc_tree->horizontal3[0], mi_row, mi_col,
-          get_h_partition_subsize(bsize, 0, PARTITION_HORZ_3));
+          partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+          pc_tree->horizontal3[cur_region_type][0],
+#else
+          pc_tree->horizontal3[0],
+#endif  // CONFIG_EXTENDED_SDP
+          mi_row, mi_col, get_h_partition_subsize(bsize, 0, PARTITION_HORZ_3));
       trace_partition_boundary(
-          partition_boundaries, pc_tree->horizontal3[1], mi_row + mi_height / 4,
-          mi_col, get_h_partition_subsize(bsize, 1, PARTITION_HORZ_3));
-      trace_partition_boundary(
-          partition_boundaries, pc_tree->horizontal3[2], mi_row + mi_height / 4,
-          mi_col + mi_width / 2,
+          partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+          pc_tree->horizontal3[cur_region_type][1],
+#else
+          pc_tree->horizontal3[1],
+#endif  // CONFIG_EXTENDED_SDP
+          mi_row + mi_height / 4, mi_col,
           get_h_partition_subsize(bsize, 1, PARTITION_HORZ_3));
       trace_partition_boundary(
-          partition_boundaries, pc_tree->horizontal3[3],
+          partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+          pc_tree->horizontal3[cur_region_type][2],
+#else
+          pc_tree->horizontal3[2],
+#endif  // CONFIG_EXTENDED_SDP
+          mi_row + mi_height / 4, mi_col + mi_width / 2,
+          get_h_partition_subsize(bsize, 1, PARTITION_HORZ_3));
+      trace_partition_boundary(
+          partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+          pc_tree->horizontal3[cur_region_type][3],
+#else
+          pc_tree->horizontal3[3],
+#endif  // CONFIG_EXTENDED_SDP
           mi_row + 3 * mi_height / 4, mi_col,
           get_h_partition_subsize(bsize, 0, PARTITION_HORZ_3));
       break;
     case PARTITION_VERT_3:
       trace_partition_boundary(
-          partition_boundaries, pc_tree->vertical3[0], mi_row, mi_col,
-          get_h_partition_subsize(bsize, 0, PARTITION_VERT_3));
+          partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+          pc_tree->vertical3[cur_region_type][0],
+#else
+          pc_tree->vertical3[0],
+#endif  // CONFIG_EXTENDED_SDP
+          mi_row, mi_col, get_h_partition_subsize(bsize, 0, PARTITION_VERT_3));
       trace_partition_boundary(
-          partition_boundaries, pc_tree->vertical3[1], mi_row,
-          mi_col + mi_width / 4,
+          partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+          pc_tree->vertical3[cur_region_type][1],
+#else
+          pc_tree->vertical3[1],
+#endif  // CONFIG_EXTENDED_SDP
+          mi_row, mi_col + mi_width / 4,
           get_h_partition_subsize(bsize, 1, PARTITION_VERT_3));
       trace_partition_boundary(
-          partition_boundaries, pc_tree->vertical3[2], mi_row + mi_height / 2,
-          mi_col + mi_width / 4,
+          partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+          pc_tree->vertical3[cur_region_type][2],
+#else
+          pc_tree->vertical3[2],
+#endif  // CONFIG_EXTENDED_SDP
+          mi_row + mi_height / 2, mi_col + mi_width / 4,
           get_h_partition_subsize(bsize, 1, PARTITION_VERT_3));
       trace_partition_boundary(
-          partition_boundaries, pc_tree->vertical3[3], mi_row,
-          mi_col + 3 * mi_width / 4,
+          partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+          pc_tree->vertical3[cur_region_type][3],
+#else
+          pc_tree->vertical3[3],
+#endif  // CONFIG_EXTENDED_SDP
+          mi_row, mi_col + 3 * mi_width / 4,
           get_h_partition_subsize(bsize, 0, PARTITION_VERT_3));
       break;
     case PARTITION_HORZ_4A: {
@@ -5804,13 +6403,33 @@
       assert(bsize_big < BLOCK_SIZES_ALL);
       const BLOCK_SIZE bsize_med = subsize_lookup[PARTITION_HORZ][bsize_big];
       assert(subsize == subsize_lookup[PARTITION_HORZ][bsize_med]);
-      trace_partition_boundary(partition_boundaries, pc_tree->horizontal4a[0],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->horizontal4a[cur_region_type][0],
+#else
+                               pc_tree->horizontal4a[0],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row, mi_col, subsize);
-      trace_partition_boundary(partition_boundaries, pc_tree->horizontal4a[1],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->horizontal4a[cur_region_type][1],
+#else
+                               pc_tree->horizontal4a[1],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row + ebs_h, mi_col, bsize_med);
-      trace_partition_boundary(partition_boundaries, pc_tree->horizontal4a[2],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->horizontal4a[cur_region_type][2],
+#else
+                               pc_tree->horizontal4a[2],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row + 3 * ebs_h, mi_col, bsize_big);
-      trace_partition_boundary(partition_boundaries, pc_tree->horizontal4a[3],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->horizontal4a[cur_region_type][3],
+#else
+                               pc_tree->horizontal4a[3],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row + 7 * ebs_h, mi_col, subsize);
       break;
     }
@@ -5819,13 +6438,33 @@
       assert(bsize_big < BLOCK_SIZES_ALL);
       const BLOCK_SIZE bsize_med = subsize_lookup[PARTITION_HORZ][bsize_big];
       assert(subsize == subsize_lookup[PARTITION_HORZ][bsize_med]);
-      trace_partition_boundary(partition_boundaries, pc_tree->horizontal4b[0],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->horizontal4b[cur_region_type][0],
+#else
+                               pc_tree->horizontal4b[0],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row, mi_col, subsize);
-      trace_partition_boundary(partition_boundaries, pc_tree->horizontal4b[1],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->horizontal4b[cur_region_type][1],
+#else
+                               pc_tree->horizontal4b[1],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row + ebs_h, mi_col, bsize_big);
-      trace_partition_boundary(partition_boundaries, pc_tree->horizontal4b[2],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->horizontal4b[cur_region_type][2],
+#else
+                               pc_tree->horizontal4b[2],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row + 5 * ebs_h, mi_col, bsize_med);
-      trace_partition_boundary(partition_boundaries, pc_tree->horizontal4b[3],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->horizontal4b[cur_region_type][3],
+#else
+                               pc_tree->horizontal4b[3],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row + 7 * ebs_h, mi_col, subsize);
       break;
     }
@@ -5834,13 +6473,33 @@
       assert(bsize_big < BLOCK_SIZES_ALL);
       const BLOCK_SIZE bsize_med = subsize_lookup[PARTITION_VERT][bsize_big];
       assert(subsize == subsize_lookup[PARTITION_VERT][bsize_med]);
-      trace_partition_boundary(partition_boundaries, pc_tree->vertical4a[0],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->vertical4a[cur_region_type][0],
+#else
+                               pc_tree->vertical4a[0],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row, mi_col, subsize);
-      trace_partition_boundary(partition_boundaries, pc_tree->vertical4a[1],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->vertical4a[cur_region_type][1],
+#else
+                               pc_tree->vertical4a[1],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row, mi_col + ebs_w, bsize_med);
-      trace_partition_boundary(partition_boundaries, pc_tree->vertical4a[2],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->vertical4a[cur_region_type][2],
+#else
+                               pc_tree->vertical4a[2],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row, mi_col + 3 * ebs_w, bsize_big);
-      trace_partition_boundary(partition_boundaries, pc_tree->vertical4a[3],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->vertical4a[cur_region_type][3],
+#else
+                               pc_tree->vertical4a[3],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row, mi_col + 7 * ebs_w, subsize);
       break;
     }
@@ -5849,13 +6508,33 @@
       assert(bsize_big < BLOCK_SIZES_ALL);
       const BLOCK_SIZE bsize_med = subsize_lookup[PARTITION_VERT][bsize_big];
       assert(subsize == subsize_lookup[PARTITION_VERT][bsize_med]);
-      trace_partition_boundary(partition_boundaries, pc_tree->vertical4b[0],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->vertical4b[cur_region_type][0],
+#else
+                               pc_tree->vertical4b[0],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row, mi_col, subsize);
-      trace_partition_boundary(partition_boundaries, pc_tree->vertical4b[1],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->vertical4b[cur_region_type][1],
+#else
+                               pc_tree->vertical4b[1],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row, mi_col + ebs_w, bsize_big);
-      trace_partition_boundary(partition_boundaries, pc_tree->vertical4b[2],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->vertical4b[cur_region_type][2],
+#else
+                               pc_tree->vertical4b[2],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row, mi_col + 5 * ebs_w, bsize_med);
-      trace_partition_boundary(partition_boundaries, pc_tree->vertical4b[3],
+      trace_partition_boundary(partition_boundaries,
+#if CONFIG_EXTENDED_SDP
+                               pc_tree->vertical4b[cur_region_type][3],
+#else
+                               pc_tree->vertical4b[3],
+#endif  // CONFIG_EXTENDED_SDP
                                mi_row, mi_col + 7 * ebs_w, subsize);
       break;
     }
@@ -6058,6 +6737,10 @@
     return;
   }
 
+#if CONFIG_EXTENDED_SDP
+  REGION_TYPE cur_region_type = pc_tree->region_type;
+#endif  // CONFIG_EXTENDED_SDP
+
   // Prune horz 3 with speed features
   if (part_search_state->partition_3_allowed[HORZ] &&
       !frame_is_intra_only(cm) && forced_partition != PARTITION_HORZ_3) {
@@ -6070,13 +6753,29 @@
       // Prune if the best partition is rect but the subtrees did not further
       // split in horz
       if (pc_tree->partitioning == PARTITION_HORZ &&
+#if CONFIG_EXTENDED_SDP
+          pc_tree->horizontal[cur_region_type][0] &&
+          pc_tree->horizontal[cur_region_type][1] &&
+          !node_uses_horz(pc_tree->horizontal[cur_region_type][0]) &&
+          !node_uses_horz(pc_tree->horizontal[cur_region_type][1])
+#else
           !node_uses_horz(pc_tree->horizontal[0]) &&
-          !node_uses_horz(pc_tree->horizontal[1])) {
+          !node_uses_horz(pc_tree->horizontal[1])
+#endif  // CONFIG_EXTENDED_SDP
+      ) {
         part_search_state->prune_partition_3[HORZ] = 1;
       }
       if (pc_tree->partitioning == PARTITION_VERT &&
+#if CONFIG_EXTENDED_SDP
+          pc_tree->vertical[cur_region_type][0] &&
+          pc_tree->vertical[cur_region_type][1] &&
+          !node_uses_horz(pc_tree->vertical[cur_region_type][0]) &&
+          !node_uses_horz(pc_tree->vertical[cur_region_type][1])
+#else
           !node_uses_horz(pc_tree->vertical[0]) &&
-          !node_uses_horz(pc_tree->vertical[1])) {
+          !node_uses_horz(pc_tree->vertical[1])
+#endif  // CONFIG_EXTENDED_SDP
+      ) {
         part_search_state->prune_partition_3[HORZ] = 1;
       }
     }
@@ -6093,13 +6792,29 @@
       // Prune if the best partition is rect but the subtrees did not further
       // split in vert
       if (pc_tree->partitioning == PARTITION_VERT &&
+#if CONFIG_EXTENDED_SDP
+          pc_tree->vertical[cur_region_type][0] &&
+          pc_tree->vertical[cur_region_type][1] &&
+          !node_uses_vert(pc_tree->vertical[cur_region_type][0]) &&
+          !node_uses_vert(pc_tree->vertical[cur_region_type][1])
+#else
           !node_uses_vert(pc_tree->vertical[0]) &&
-          !node_uses_vert(pc_tree->vertical[1])) {
+          !node_uses_vert(pc_tree->vertical[1])
+#endif  // CONFIG_EXTENDED_SDP
+      ) {
         part_search_state->prune_partition_3[VERT] = 1;
       }
       if (pc_tree->partitioning == PARTITION_HORZ &&
+#if CONFIG_EXTENDED_SDP
+          pc_tree->horizontal[cur_region_type][0] &&
+          pc_tree->horizontal[cur_region_type][1] &&
+          !node_uses_vert(pc_tree->horizontal[cur_region_type][0]) &&
+          !node_uses_vert(pc_tree->horizontal[cur_region_type][1])
+#else
           !node_uses_vert(pc_tree->horizontal[0]) &&
-          !node_uses_vert(pc_tree->horizontal[1])) {
+          !node_uses_vert(pc_tree->horizontal[1])
+#endif  // CONFIG_EXTENDED_SDP
+      ) {
         part_search_state->prune_partition_3[VERT] = 1;
       }
     }
@@ -6126,6 +6841,205 @@
   }
 }
 
+#if CONFIG_EXTENDED_SDP
+// Early termination of SDP for intra blocks in inter frames
+static INLINE void early_termination_inter_sdp(PC_TREE *pc_tree,
+                                               float *total_count,
+                                               float *inter_mode_count) {
+  REGION_TYPE cur_region_type = pc_tree->region_type;
+  if (pc_tree->partitioning == PARTITION_NONE) {
+    if (pc_tree->none[cur_region_type] == NULL) return;
+    const MB_MODE_INFO *const mi = &(pc_tree->none[cur_region_type])->mic;
+    if (mi == NULL) return;
+    *total_count += 1;
+    if (mi->mode >= NEARMV && mi->mode < MB_MODE_COUNT) *inter_mode_count += 1;
+    return;
+  }
+  switch (pc_tree->partitioning) {
+    case PARTITION_HORZ:
+      early_termination_inter_sdp(pc_tree->horizontal[cur_region_type][0],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->horizontal[cur_region_type][1],
+                                  total_count, inter_mode_count);
+      break;
+    case PARTITION_VERT:
+      early_termination_inter_sdp(pc_tree->vertical[cur_region_type][0],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->vertical[cur_region_type][1],
+                                  total_count, inter_mode_count);
+      break;
+    case PARTITION_HORZ_4A:
+      early_termination_inter_sdp(pc_tree->horizontal4a[cur_region_type][0],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->horizontal4a[cur_region_type][1],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->horizontal4a[cur_region_type][2],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->horizontal4a[cur_region_type][3],
+                                  total_count, inter_mode_count);
+      break;
+    case PARTITION_HORZ_4B:
+      early_termination_inter_sdp(pc_tree->horizontal4b[cur_region_type][0],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->horizontal4b[cur_region_type][1],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->horizontal4b[cur_region_type][2],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->horizontal4b[cur_region_type][3],
+                                  total_count, inter_mode_count);
+      break;
+    case PARTITION_VERT_4A:
+      early_termination_inter_sdp(pc_tree->vertical4a[cur_region_type][0],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->vertical4a[cur_region_type][1],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->vertical4a[cur_region_type][2],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->vertical4a[cur_region_type][3],
+                                  total_count, inter_mode_count);
+      break;
+    case PARTITION_VERT_4B:
+      early_termination_inter_sdp(pc_tree->vertical4b[cur_region_type][0],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->vertical4b[cur_region_type][1],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->vertical4b[cur_region_type][2],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->vertical4b[cur_region_type][3],
+                                  total_count, inter_mode_count);
+      break;
+    case PARTITION_HORZ_3:
+      early_termination_inter_sdp(pc_tree->horizontal3[cur_region_type][0],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->horizontal3[cur_region_type][1],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->horizontal3[cur_region_type][2],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->horizontal3[cur_region_type][3],
+                                  total_count, inter_mode_count);
+      break;
+    case PARTITION_VERT_3:
+      early_termination_inter_sdp(pc_tree->vertical3[cur_region_type][0],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->vertical3[cur_region_type][1],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->vertical3[cur_region_type][2],
+                                  total_count, inter_mode_count);
+      early_termination_inter_sdp(pc_tree->vertical3[cur_region_type][3],
+                                  total_count, inter_mode_count);
+      break;
+    default: break;
+  }
+}
+
+// Search SDP for intra blocks in inter frames
+static INLINE void search_intra_region_partitioning(
+    PartitionSearchState *search_state, AV1_COMP *const cpi, ThreadData *td,
+    TileDataEnc *tile_data, TokenExtra **tp, RD_STATS *best_rdc,
+    PC_TREE *pc_tree, const PARTITION_TREE *ptree_luma,
+    const PARTITION_TREE *template_tree, RD_SEARCH_MACROBLOCK_CONTEXT *x_ctx,
+    PartitionSearchState *part_search_state,
+#if CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
+    LevelBanksRDO *level_banks,
+#endif  // CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
+    SB_MULTI_PASS_MODE multi_pass_mode, int max_recursion_depth,
+    PARTITION_TYPE parent_partition) {
+  const AV1_COMMON *const cm = &cpi->common;
+  MACROBLOCK *const x = &td->mb;
+  const int num_planes = av1_num_planes(cm);
+  MACROBLOCKD *const xd = &x->e_mbd;
+
+  // Add one encoder fast method for early terminating inter-sdp
+  float total_count = 0;
+  float inter_mode_count = 0;
+  early_termination_inter_sdp(pc_tree, &total_count, &inter_mode_count);
+  // if over 60% of the coded blocks under this region are inter coded blocks,
+  // skip the rdo for inter-sdp
+  if (total_count * 0.7 < inter_mode_count) return;
+
+  pc_tree->region_type = INTRA_REGION;
+  // store the current best partitioning
+  PARTITION_TYPE cur_best_partitioning = pc_tree->partitioning;
+  pc_tree->partitioning = PARTITION_NONE;
+
+  RD_STATS *sum_rdc = &part_search_state->sum_rdc;
+  av1_init_rd_stats(sum_rdc);
+
+  sum_rdc->rate = part_search_state->region_type_cost[pc_tree->region_type];
+  sum_rdc->rdcost = RDCOST(x->rdmult, sum_rdc->rate, 0);
+
+  RD_STATS best_remain_rdcost;
+
+  av1_rd_stats_subtraction(x->rdmult, best_rdc, sum_rdc, &best_remain_rdcost);
+
+  const PartitionBlkParams *blk_params = &search_state->part_blk_params;
+  const int mi_row = blk_params->mi_row, mi_col = blk_params->mi_col;
+  const BLOCK_SIZE bsize = blk_params->bsize;
+
+  RD_STATS this_rdc;
+  av1_init_rd_stats(&this_rdc);
+
+  // Encoder RDO for luma component in intra region
+  xd->tree_type = LUMA_PART;
+  if (!av1_rd_pick_partition(cpi, td, tile_data, tp, mi_row, mi_col, bsize,
+#if CONFIG_EXTENDED_SDP
+                             parent_partition,
+#endif  // CONFIG_EXTENDED_SDP
+                             &this_rdc, best_remain_rdcost, pc_tree, ptree_luma,
+                             template_tree, max_recursion_depth, NULL, NULL,
+                             multi_pass_mode, NULL)) {
+    av1_invalid_rd_stats(&this_rdc);
+    av1_invalid_rd_stats(sum_rdc);
+  }
+  // Encoder RDO for chroma component in intra region
+  if (this_rdc.rdcost != INT64_MAX && !cm->seq_params.monochrome) {
+    sum_rdc->rate += this_rdc.rate;
+    sum_rdc->dist += this_rdc.dist;
+    av1_rd_cost_update(x->rdmult, sum_rdc);
+    xd->tree_type = CHROMA_PART;
+    av1_rd_stats_subtraction(x->rdmult, best_rdc, sum_rdc, &best_remain_rdcost);
+    av1_init_rd_stats(&this_rdc);
+    if (!av1_rd_pick_partition(cpi, td, tile_data, tp, mi_row, mi_col, bsize,
+#if CONFIG_EXTENDED_SDP
+                               parent_partition,
+#endif  // CONFIG_EXTENDED_SDP
+                               &this_rdc, best_remain_rdcost, pc_tree,
+                               ptree_luma, template_tree, max_recursion_depth,
+                               NULL, NULL, multi_pass_mode, NULL)) {
+      av1_invalid_rd_stats(&this_rdc);
+      av1_invalid_rd_stats(sum_rdc);
+    }
+    if (this_rdc.rdcost != INT64_MAX) {
+      sum_rdc->rate += this_rdc.rate;
+      sum_rdc->dist += this_rdc.dist;
+      av1_rd_cost_update(x->rdmult, sum_rdc);
+    }
+  }
+  // reset tree_type to shared_part
+  xd->tree_type = SHARED_PART;
+  // compare current rd cost with best rd cost
+  if (sum_rdc->rdcost < best_rdc->rdcost) {
+#if CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
+    update_best_level_banks(level_banks, &x->e_mbd);
+#endif  // CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
+    *best_rdc = *sum_rdc;
+    search_state->found_best_partition = true;
+#if CONFIG_EXTENDED_SDP
+    pc_tree->region_type = INTRA_REGION;
+#endif  // CONFIG_EXTENDED_SDP
+  } else {
+    // set back to the previous stored region_type and partitioning type
+    pc_tree->region_type = MIXED_INTER_INTRA_REGION;
+    pc_tree->partitioning = cur_best_partitioning;
+  }
+
+  av1_restore_context(cm, x, x_ctx, mi_row, mi_col, bsize, num_planes);
+#if CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
+  restore_level_banks(&x->e_mbd, level_banks);
+#endif  // CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
+}
+#endif  // CONFIG_EXTENDED_SDP
+
 // Pruning logic for PARTITION_HORZ_4A/B and PARTITION_VERT_4A/B.
 static AOM_INLINE void prune_ext_partitions_4way(
     AV1_COMP *const cpi, PC_TREE *pc_tree,
@@ -6134,6 +7048,10 @@
   const PARTITION_SPEED_FEATURES *part_sf = &cpi->sf.part_sf;
   const PARTITION_TYPE forced_partition = part_search_state->forced_partition;
 
+#if CONFIG_EXTENDED_SDP
+  const int cur_region_type = pc_tree->region_type;
+#endif  // CONFIG_EXTENDED_SDP
+
   // Prune HORZ 4A with speed features
   if (part_search_state->partition_4a_allowed[HORZ] &&
       forced_partition != PARTITION_HORZ_4A) {
@@ -6147,27 +7065,47 @@
       // Prune if the best partition is rect but subtrees did not further split
       // in horz
       if (pc_tree->partitioning == PARTITION_HORZ &&
+#if CONFIG_EXTENDED_SDP
+          !node_uses_horz(pc_tree->horizontal[cur_region_type][0]) &&
+          !node_uses_horz(pc_tree->horizontal[cur_region_type][1])) {
+#else
           !node_uses_horz(pc_tree->horizontal[0]) &&
           !node_uses_horz(pc_tree->horizontal[1])) {
+#endif  // CONFIG_EXTENDED_SDP
         part_search_state->prune_partition_4a[HORZ] = 1;
       }
       if (pc_tree->partitioning == PARTITION_VERT &&
+#if CONFIG_EXTENDED_SDP
+          !node_uses_horz(pc_tree->vertical[cur_region_type][0]) &&
+          !node_uses_horz(pc_tree->vertical[cur_region_type][1])) {
+#else
           !node_uses_horz(pc_tree->vertical[0]) &&
           !node_uses_horz(pc_tree->vertical[1])) {
+#endif  // CONFIG_EXTENDED_SDP
         part_search_state->prune_partition_4a[HORZ] = 1;
       }
     }
     if (part_sf->prune_part_4_with_part_3 && !frame_is_intra_only(cm)) {
       if (pc_tree->partitioning == PARTITION_HORZ_3 &&
+#if CONFIG_EXTENDED_SDP
+          !node_uses_horz(pc_tree->horizontal3[cur_region_type][0]) &&
+          !node_uses_horz(pc_tree->horizontal3[cur_region_type][3])) {
+#else
           !node_uses_horz(pc_tree->horizontal3[0]) &&
           !node_uses_horz(pc_tree->horizontal3[3])) {
+#endif  // CONFIG_EXTENDED_SDP
         // Prune if best partition is horizontal H, but first and last
         // subpartitions did not further split in horizontal direction.
         part_search_state->prune_partition_4a[HORZ] = 1;
       }
       if (pc_tree->partitioning == PARTITION_VERT_3 &&
+#if CONFIG_EXTENDED_SDP
+          !node_uses_horz(pc_tree->vertical3[cur_region_type][1]) &&
+          !node_uses_horz(pc_tree->vertical3[cur_region_type][2])) {
+#else
           !node_uses_horz(pc_tree->vertical3[1]) &&
           !node_uses_horz(pc_tree->vertical3[2])) {
+#endif  // CONFIG_EXTENDED_SDP
         // Prune if best partition is vertical H, but middle two
         // subpartitions did not further split in horizontal direction.
         part_search_state->prune_partition_4a[HORZ] = 1;
@@ -6211,27 +7149,47 @@
       // Prune if the best partition is rect but subtrees did not further split
       // in horz
       if (pc_tree->partitioning == PARTITION_HORZ &&
+#if CONFIG_EXTENDED_SDP
+          !node_uses_horz(pc_tree->horizontal[cur_region_type][0]) &&
+          !node_uses_horz(pc_tree->horizontal[cur_region_type][1])) {
+#else
           !node_uses_horz(pc_tree->horizontal[0]) &&
           !node_uses_horz(pc_tree->horizontal[1])) {
+#endif  // CONFIG_EXTENDED_SDP
         part_search_state->prune_partition_4b[HORZ] = 1;
       }
       if (pc_tree->partitioning == PARTITION_VERT &&
+#if CONFIG_EXTENDED_SDP
+          !node_uses_horz(pc_tree->vertical[cur_region_type][0]) &&
+          !node_uses_horz(pc_tree->vertical[cur_region_type][1])) {
+#else
           !node_uses_horz(pc_tree->vertical[0]) &&
           !node_uses_horz(pc_tree->vertical[1])) {
+#endif  // CONFIG_EXTENDED_SDP
         part_search_state->prune_partition_4b[HORZ] = 1;
       }
     }
     if (part_sf->prune_part_4_with_part_3 && !frame_is_intra_only(cm)) {
       if (pc_tree->partitioning == PARTITION_HORZ_3 &&
+#if CONFIG_EXTENDED_SDP
+          !node_uses_horz(pc_tree->horizontal3[cur_region_type][0]) &&
+          !node_uses_horz(pc_tree->horizontal3[cur_region_type][3])) {
+#else
           !node_uses_horz(pc_tree->horizontal3[0]) &&
           !node_uses_horz(pc_tree->horizontal3[3])) {
+#endif  // CONFIG_EXTENDED_SDP
         // Prune if best partition is horizontal H, but first and last
         // subpartitions did not further split in horizontal direction.
         part_search_state->prune_partition_4b[HORZ] = 1;
       }
       if (pc_tree->partitioning == PARTITION_VERT_3 &&
+#if CONFIG_EXTENDED_SDP
+          !node_uses_horz(pc_tree->vertical3[cur_region_type][1]) &&
+          !node_uses_horz(pc_tree->vertical3[cur_region_type][2])) {
+#else
           !node_uses_horz(pc_tree->vertical3[1]) &&
           !node_uses_horz(pc_tree->vertical3[2])) {
+#endif  // CONFIG_EXTENDED_SDP
         // Prune if best partition is vertical H, but middle two
         // subpartitions did not further split in horizontal direction.
         part_search_state->prune_partition_4b[HORZ] = 1;
@@ -6275,27 +7233,47 @@
       // Prune if the best partition is rect but subtrees did not further split
       // in vert
       if (pc_tree->partitioning == PARTITION_VERT &&
+#if CONFIG_EXTENDED_SDP
+          !node_uses_vert(pc_tree->vertical[cur_region_type][0]) &&
+          !node_uses_vert(pc_tree->vertical[cur_region_type][1])) {
+#else
           !node_uses_vert(pc_tree->vertical[0]) &&
           !node_uses_vert(pc_tree->vertical[1])) {
+#endif  // CONFIG_EXTENDED_SDP
         part_search_state->prune_partition_4a[VERT] = 1;
       }
       if (pc_tree->partitioning == PARTITION_HORZ &&
+#if CONFIG_EXTENDED_SDP
+          !node_uses_vert(pc_tree->horizontal[cur_region_type][0]) &&
+          !node_uses_vert(pc_tree->horizontal[cur_region_type][1])) {
+#else
           !node_uses_vert(pc_tree->horizontal[0]) &&
           !node_uses_vert(pc_tree->horizontal[1])) {
+#endif  // CONFIG_EXTENDED_SDP
         part_search_state->prune_partition_4a[VERT] = 1;
       }
     }
     if (part_sf->prune_part_4_with_part_3 && !frame_is_intra_only(cm)) {
       if (pc_tree->partitioning == PARTITION_VERT_3 &&
+#if CONFIG_EXTENDED_SDP
+          !node_uses_vert(pc_tree->vertical3[cur_region_type][0]) &&
+          !node_uses_vert(pc_tree->vertical3[cur_region_type][3])) {
+#else
           !node_uses_vert(pc_tree->vertical3[0]) &&
           !node_uses_vert(pc_tree->vertical3[3])) {
+#endif  // CONFIG_EXTENDED_SDP
         // Prune if best partition is vertical H, but first and last
         // subpartitions did not further split in vertical direction.
         part_search_state->prune_partition_4a[VERT] = 1;
       }
       if (pc_tree->partitioning == PARTITION_HORZ_3 &&
+#if CONFIG_EXTENDED_SDP
+          !node_uses_vert(pc_tree->horizontal3[cur_region_type][1]) &&
+          !node_uses_vert(pc_tree->horizontal3[cur_region_type][2])) {
+#else
           !node_uses_vert(pc_tree->horizontal3[1]) &&
           !node_uses_vert(pc_tree->horizontal3[2])) {
+#endif  // CONFIG_EXTENDED_SDP
         // Prune if best partition is horizontal H, but middle two
         // subpartitions did not further split in vertical direction.
         part_search_state->prune_partition_4a[VERT] = 1;
@@ -6339,27 +7317,47 @@
       // Prune if the best partition is rect but subtrees did not further split
       // in vert
       if (pc_tree->partitioning == PARTITION_VERT &&
+#if CONFIG_EXTENDED_SDP
+          !node_uses_vert(pc_tree->vertical[cur_region_type][0]) &&
+          !node_uses_vert(pc_tree->vertical[cur_region_type][1])) {
+#else
           !node_uses_vert(pc_tree->vertical[0]) &&
           !node_uses_vert(pc_tree->vertical[1])) {
+#endif  // CONFIG_EXTENDED_SDP
         part_search_state->prune_partition_4b[VERT] = 1;
       }
       if (pc_tree->partitioning == PARTITION_HORZ &&
+#if CONFIG_EXTENDED_SDP
+          !node_uses_vert(pc_tree->horizontal[cur_region_type][0]) &&
+          !node_uses_vert(pc_tree->horizontal[cur_region_type][1])) {
+#else
           !node_uses_vert(pc_tree->horizontal[0]) &&
           !node_uses_vert(pc_tree->horizontal[1])) {
+#endif  // CONFIG_EXTENDED_SDP
         part_search_state->prune_partition_4b[VERT] = 1;
       }
     }
     if (part_sf->prune_part_4_with_part_3 && !frame_is_intra_only(cm)) {
       if (pc_tree->partitioning == PARTITION_VERT_3 &&
+#if CONFIG_EXTENDED_SDP
+          !node_uses_vert(pc_tree->vertical3[cur_region_type][0]) &&
+          !node_uses_vert(pc_tree->vertical3[cur_region_type][3])) {
+#else
           !node_uses_vert(pc_tree->vertical3[0]) &&
           !node_uses_vert(pc_tree->vertical3[3])) {
+#endif  // CONFIG_EXTENDED_SDP
         // Prune if best partition is vertical H, but first and last
         // subpartitions did not further split in vertical direction.
         part_search_state->prune_partition_4b[VERT] = 1;
       }
       if (pc_tree->partitioning == PARTITION_HORZ_3 &&
+#if CONFIG_EXTENDED_SDP
+          !node_uses_vert(pc_tree->horizontal3[cur_region_type][1]) &&
+          !node_uses_vert(pc_tree->horizontal3[cur_region_type][2])) {
+#else
           !node_uses_vert(pc_tree->horizontal3[1]) &&
           !node_uses_vert(pc_tree->horizontal3[2])) {
+#endif  // CONFIG_EXTENDED_SDP
         // Prune if best partition is horizontal H, but middle two
         // subpartitions did not further split in vertical direction.
         part_search_state->prune_partition_4b[VERT] = 1;
@@ -6468,6 +7466,14 @@
   const int eighth_step = mi_size_high[bsize] / 8;
 
   sum_rdc.rate = search_state->partition_cost[PARTITION_HORZ_4A];
+#if CONFIG_EXTENDED_SDP
+  if (pc_tree->region_type == MIXED_INTER_INTRA_REGION && pc_tree->parent &&
+      is_inter_sdp_allowed(pc_tree->parent->block_size,
+                           pc_tree->parent->partitioning) &&
+      is_bsize_allowed_for_inter_sdp(bsize, PARTITION_HORZ_4A))
+    sum_rdc.rate +=
+        part_search_state->region_type_cost[MIXED_INTER_INTRA_REGION];
+#endif  // CONFIG_EXTENDED_SDP
   sum_rdc.rdcost = RDCOST(x->rdmult, sum_rdc.rate, 0);
 
   const BLOCK_SIZE sml_subsize =
@@ -6480,7 +7486,22 @@
   const BLOCK_SIZE subblock_sizes[4] = { sml_subsize, med_subsize, big_subsize,
                                          sml_subsize };
 
+#if CONFIG_EXTENDED_SDP
+  REGION_TYPE cur_region_type = pc_tree->region_type;
+#endif  // CONFIG_EXTENDED_SDP
+
   for (int idx = 0; idx < 4; idx++) {
+#if CONFIG_EXTENDED_SDP
+    if (pc_tree->horizontal4a[cur_region_type][idx]) {
+      av1_free_pc_tree_recursive(pc_tree->horizontal4a[cur_region_type][idx],
+                                 num_planes, 0, 0);
+      pc_tree->horizontal4a[cur_region_type][idx] = NULL;
+    }
+    const int this_mi_row = mi_row + eighth_step * cum_step_multipliers[idx];
+    pc_tree->horizontal4a[cur_region_type][idx] = av1_alloc_pc_tree_node(
+        xd->tree_type, this_mi_row, mi_col, subblock_sizes[idx], pc_tree,
+        PARTITION_HORZ_4A, idx, idx == 3, ss_x, ss_y);
+#else
     if (pc_tree->horizontal4a[idx]) {
       av1_free_pc_tree_recursive(pc_tree->horizontal4a[idx], num_planes, 0, 0);
       pc_tree->horizontal4a[idx] = NULL;
@@ -6489,6 +7510,7 @@
     pc_tree->horizontal4a[idx] = av1_alloc_pc_tree_node(
         xd->tree_type, this_mi_row, mi_col, subblock_sizes[idx], pc_tree,
         PARTITION_HORZ_4A, idx, idx == 3, ss_x, ss_y);
+#endif  // CONFIG_EXTENDED_SDP
   }
 
   bool skippable = true;
@@ -6497,14 +7519,19 @@
 
     if (i > 0 && this_mi_row >= cm->mi_params.mi_rows) break;
 
-    SUBBLOCK_RDO_DATA rdo_data = { pc_tree->horizontal4a[i],
-                                   get_partition_subtree_const(ptree_luma, i),
-                                   get_partition_subtree_const(template_tree,
-                                                               i),
-                                   this_mi_row,
-                                   mi_col,
-                                   subblock_sizes[i],
-                                   PARTITION_HORZ_4A };
+    SUBBLOCK_RDO_DATA rdo_data = {
+#if CONFIG_EXTENDED_SDP
+      pc_tree->horizontal4a[cur_region_type][i],
+#else
+      pc_tree->horizontal4a[i],
+#endif
+      get_partition_subtree_const(ptree_luma, i),
+      get_partition_subtree_const(template_tree, i),
+      this_mi_row,
+      mi_col,
+      subblock_sizes[i],
+      PARTITION_HORZ_4A
+    };
     if (!rd_try_subblock_new(cpi, td, tile_data, tp, &rdo_data, *best_rdc,
                              &sum_rdc, multi_pass_mode, &skippable,
                              max_recursion_depth)) {
@@ -6551,6 +7578,10 @@
   const int mi_row = blk_params->mi_row, mi_col = blk_params->mi_col;
   const BLOCK_SIZE bsize = blk_params->bsize;
 
+#if CONFIG_EXTENDED_SDP
+  REGION_TYPE cur_region_type = pc_tree->region_type;
+#endif
+
   if (is_part_pruned_by_forced_partition(part_search_state,
                                          PARTITION_HORZ_4B) ||
       !part_search_state->partition_4b_allowed[HORZ] ||
@@ -6575,6 +7606,14 @@
   const int eighth_step = mi_size_high[bsize] / 8;
 
   sum_rdc.rate = search_state->partition_cost[PARTITION_HORZ_4B];
+#if CONFIG_EXTENDED_SDP
+  if (pc_tree->region_type == MIXED_INTER_INTRA_REGION && pc_tree->parent &&
+      is_inter_sdp_allowed(pc_tree->parent->block_size,
+                           pc_tree->parent->partitioning) &&
+      is_bsize_allowed_for_inter_sdp(bsize, PARTITION_HORZ_4A))
+    sum_rdc.rate +=
+        part_search_state->region_type_cost[MIXED_INTER_INTRA_REGION];
+#endif  // CONFIG_EXTENDED_SDP
   sum_rdc.rdcost = RDCOST(x->rdmult, sum_rdc.rate, 0);
 
   const BLOCK_SIZE sml_subsize =
@@ -6588,6 +7627,17 @@
                                          sml_subsize };
 
   for (int idx = 0; idx < 4; idx++) {
+#if CONFIG_EXTENDED_SDP
+    if (pc_tree->horizontal4b[cur_region_type][idx]) {
+      av1_free_pc_tree_recursive(pc_tree->horizontal4b[cur_region_type][idx],
+                                 num_planes, 0, 0);
+      pc_tree->horizontal4b[cur_region_type][idx] = NULL;
+    }
+    const int this_mi_row = mi_row + eighth_step * cum_step_multipliers[idx];
+    pc_tree->horizontal4b[cur_region_type][idx] = av1_alloc_pc_tree_node(
+        xd->tree_type, this_mi_row, mi_col, subblock_sizes[idx], pc_tree,
+        PARTITION_HORZ_4B, idx, idx == 3, ss_x, ss_y);
+#else
     if (pc_tree->horizontal4b[idx]) {
       av1_free_pc_tree_recursive(pc_tree->horizontal4b[idx], num_planes, 0, 0);
       pc_tree->horizontal4b[idx] = NULL;
@@ -6596,6 +7646,7 @@
     pc_tree->horizontal4b[idx] = av1_alloc_pc_tree_node(
         xd->tree_type, this_mi_row, mi_col, subblock_sizes[idx], pc_tree,
         PARTITION_HORZ_4B, idx, idx == 3, ss_x, ss_y);
+#endif  // CONFIG_EXTENDED_SDP
   }
 
   bool skippable = true;
@@ -6604,14 +7655,19 @@
 
     if (i > 0 && this_mi_row >= cm->mi_params.mi_rows) break;
 
-    SUBBLOCK_RDO_DATA rdo_data = { pc_tree->horizontal4b[i],
-                                   get_partition_subtree_const(ptree_luma, i),
-                                   get_partition_subtree_const(template_tree,
-                                                               i),
-                                   this_mi_row,
-                                   mi_col,
-                                   subblock_sizes[i],
-                                   PARTITION_HORZ_4B };
+    SUBBLOCK_RDO_DATA rdo_data = {
+#if CONFIG_EXTENDED_SDP
+      pc_tree->horizontal4b[cur_region_type][i],
+#else
+      pc_tree->horizontal4b[i],
+#endif  // CONFIG_EXTENDED_SDP
+      get_partition_subtree_const(ptree_luma, i),
+      get_partition_subtree_const(template_tree, i),
+      this_mi_row,
+      mi_col,
+      subblock_sizes[i],
+      PARTITION_HORZ_4B
+    };
     if (!rd_try_subblock_new(cpi, td, tile_data, tp, &rdo_data, *best_rdc,
                              &sum_rdc, multi_pass_mode, &skippable,
                              max_recursion_depth)) {
@@ -6658,6 +7714,10 @@
   const int mi_row = blk_params->mi_row, mi_col = blk_params->mi_col;
   const BLOCK_SIZE bsize = blk_params->bsize;
 
+#if CONFIG_EXTENDED_SDP
+  REGION_TYPE cur_region_type = pc_tree->region_type;
+#endif  // CONFIG_EXTENDED_SDP
+
   if (is_part_pruned_by_forced_partition(part_search_state,
                                          PARTITION_VERT_4A) ||
       !part_search_state->partition_4a_allowed[VERT] ||
@@ -6682,6 +7742,14 @@
   const int eighth_step = mi_size_wide[bsize] / 8;
 
   sum_rdc.rate = search_state->partition_cost[PARTITION_VERT_4A];
+#if CONFIG_EXTENDED_SDP
+  if (pc_tree->region_type == MIXED_INTER_INTRA_REGION && pc_tree->parent &&
+      is_inter_sdp_allowed(pc_tree->parent->block_size,
+                           pc_tree->parent->partitioning) &&
+      is_bsize_allowed_for_inter_sdp(bsize, PARTITION_VERT_4A))
+    sum_rdc.rate +=
+        part_search_state->region_type_cost[MIXED_INTER_INTRA_REGION];
+#endif  // CONFIG_EXTENDED_SDP
   sum_rdc.rdcost = RDCOST(x->rdmult, sum_rdc.rate, 0);
 
   const BLOCK_SIZE sml_subsize =
@@ -6695,6 +7763,17 @@
                                          sml_subsize };
 
   for (int idx = 0; idx < 4; idx++) {
+#if CONFIG_EXTENDED_SDP
+    if (pc_tree->vertical4a[cur_region_type][idx]) {
+      av1_free_pc_tree_recursive(pc_tree->vertical4a[cur_region_type][idx],
+                                 num_planes, 0, 0);
+      pc_tree->vertical4a[cur_region_type][idx] = NULL;
+    }
+    const int this_mi_col = mi_col + eighth_step * cum_step_multipliers[idx];
+    pc_tree->vertical4a[cur_region_type][idx] = av1_alloc_pc_tree_node(
+        xd->tree_type, mi_row, this_mi_col, subblock_sizes[idx], pc_tree,
+        PARTITION_VERT_4A, idx, idx == 3, ss_x, ss_y);
+#else
     if (pc_tree->vertical4a[idx]) {
       av1_free_pc_tree_recursive(pc_tree->vertical4a[idx], num_planes, 0, 0);
       pc_tree->vertical4a[idx] = NULL;
@@ -6703,6 +7782,7 @@
     pc_tree->vertical4a[idx] = av1_alloc_pc_tree_node(
         xd->tree_type, mi_row, this_mi_col, subblock_sizes[idx], pc_tree,
         PARTITION_VERT_4A, idx, idx == 3, ss_x, ss_y);
+#endif  // CONFIG_EXTENDED_SDP
   }
 
   bool skippable = true;
@@ -6711,14 +7791,19 @@
 
     if (i > 0 && this_mi_col >= cm->mi_params.mi_cols) break;
 
-    SUBBLOCK_RDO_DATA rdo_data = { pc_tree->vertical4a[i],
-                                   get_partition_subtree_const(ptree_luma, i),
-                                   get_partition_subtree_const(template_tree,
-                                                               i),
-                                   mi_row,
-                                   this_mi_col,
-                                   subblock_sizes[i],
-                                   PARTITION_VERT_4A };
+    SUBBLOCK_RDO_DATA rdo_data = {
+#if CONFIG_EXTENDED_SDP
+      pc_tree->vertical4a[cur_region_type][i],
+#else
+      pc_tree->vertical4a[i],
+#endif  // CONFIG_EXTENDED_SDP
+      get_partition_subtree_const(ptree_luma, i),
+      get_partition_subtree_const(template_tree, i),
+      mi_row,
+      this_mi_col,
+      subblock_sizes[i],
+      PARTITION_VERT_4A
+    };
     if (!rd_try_subblock_new(cpi, td, tile_data, tp, &rdo_data, *best_rdc,
                              &sum_rdc, multi_pass_mode, &skippable,
                              max_recursion_depth)) {
@@ -6765,6 +7850,10 @@
   const int mi_row = blk_params->mi_row, mi_col = blk_params->mi_col;
   const BLOCK_SIZE bsize = blk_params->bsize;
 
+#if CONFIG_EXTENDED_SDP
+  REGION_TYPE cur_region_type = pc_tree->region_type;
+#endif  // CONFIG_EXTENDED_SDP
+
   if (is_part_pruned_by_forced_partition(part_search_state,
                                          PARTITION_VERT_4B) ||
       !part_search_state->partition_4b_allowed[VERT] ||
@@ -6789,6 +7878,14 @@
   const int eighth_step = mi_size_wide[bsize] / 8;
 
   sum_rdc.rate = search_state->partition_cost[PARTITION_VERT_4B];
+#if CONFIG_EXTENDED_SDP
+  if (pc_tree->region_type == MIXED_INTER_INTRA_REGION && pc_tree->parent &&
+      is_inter_sdp_allowed(pc_tree->parent->block_size,
+                           pc_tree->parent->partitioning) &&
+      is_bsize_allowed_for_inter_sdp(bsize, PARTITION_VERT_4A))
+    sum_rdc.rate +=
+        part_search_state->region_type_cost[MIXED_INTER_INTRA_REGION];
+#endif  // CONFIG_EXTENDED_SDP
   sum_rdc.rdcost = RDCOST(x->rdmult, sum_rdc.rate, 0);
 
   const BLOCK_SIZE sml_subsize =
@@ -6802,6 +7899,17 @@
                                          sml_subsize };
 
   for (int idx = 0; idx < 4; idx++) {
+#if CONFIG_EXTENDED_SDP
+    if (pc_tree->vertical4b[cur_region_type][idx]) {
+      av1_free_pc_tree_recursive(pc_tree->vertical4b[cur_region_type][idx],
+                                 num_planes, 0, 0);
+      pc_tree->vertical4b[cur_region_type][idx] = NULL;
+    }
+    const int this_mi_col = mi_col + eighth_step * cum_step_multipliers[idx];
+    pc_tree->vertical4b[cur_region_type][idx] = av1_alloc_pc_tree_node(
+        xd->tree_type, mi_row, this_mi_col, subblock_sizes[idx], pc_tree,
+        PARTITION_VERT_4B, idx, idx == 3, ss_x, ss_y);
+#else
     if (pc_tree->vertical4b[idx]) {
       av1_free_pc_tree_recursive(pc_tree->vertical4b[idx], num_planes, 0, 0);
       pc_tree->vertical4b[idx] = NULL;
@@ -6810,6 +7918,7 @@
     pc_tree->vertical4b[idx] = av1_alloc_pc_tree_node(
         xd->tree_type, mi_row, this_mi_col, subblock_sizes[idx], pc_tree,
         PARTITION_VERT_4B, idx, idx == 3, ss_x, ss_y);
+#endif  // CONFIG_EXTENDED_SDP
   }
 
   bool skippable = true;
@@ -6818,14 +7927,19 @@
 
     if (i > 0 && this_mi_col >= cm->mi_params.mi_cols) break;
 
-    SUBBLOCK_RDO_DATA rdo_data = { pc_tree->vertical4b[i],
-                                   get_partition_subtree_const(ptree_luma, i),
-                                   get_partition_subtree_const(template_tree,
-                                                               i),
-                                   mi_row,
-                                   this_mi_col,
-                                   subblock_sizes[i],
-                                   PARTITION_VERT_4B };
+    SUBBLOCK_RDO_DATA rdo_data = {
+#if CONFIG_EXTENDED_SDP
+      pc_tree->vertical4b[cur_region_type][i],
+#else
+      pc_tree->vertical4b[i],
+#endif  // CONFIG_EXTENDED_SDP
+      get_partition_subtree_const(ptree_luma, i),
+      get_partition_subtree_const(template_tree, i),
+      mi_row,
+      this_mi_col,
+      subblock_sizes[i],
+      PARTITION_VERT_4B
+    };
     if (!rd_try_subblock_new(cpi, td, tile_data, tp, &rdo_data, *best_rdc,
                              &sum_rdc, multi_pass_mode, &skippable,
                              max_recursion_depth)) {
@@ -6873,6 +7987,10 @@
   const int mi_row = blk_params->mi_row, mi_col = blk_params->mi_col;
   const BLOCK_SIZE bsize = blk_params->bsize;
 
+#if CONFIG_EXTENDED_SDP
+  REGION_TYPE cur_region_type = pc_tree->region_type;
+#endif  // CONFIG_EXTENDED_SDP
+
   if (is_part_pruned_by_forced_partition(part_search_state, PARTITION_HORZ_3) ||
       !part_search_state->partition_3_allowed[HORZ] ||
       part_search_state->prune_partition_3[HORZ]) {
@@ -6899,6 +8017,14 @@
   const int quarter_step = mi_size_high[bsize] / 4;
 
   sum_rdc.rate = search_state->partition_cost[PARTITION_HORZ_3];
+#if CONFIG_EXTENDED_SDP
+  if (pc_tree->region_type == MIXED_INTER_INTRA_REGION && pc_tree->parent &&
+      is_inter_sdp_allowed(pc_tree->parent->block_size,
+                           pc_tree->parent->partitioning) &&
+      is_bsize_allowed_for_inter_sdp(bsize, PARTITION_HORZ_3))
+    sum_rdc.rate +=
+        part_search_state->region_type_cost[MIXED_INTER_INTRA_REGION];
+#endif  // CONFIG_EXTENDED_SDP
   sum_rdc.rdcost = RDCOST(x->rdmult, sum_rdc.rate, 0);
 
   const BLOCK_SIZE sml_subsize =
@@ -6911,6 +8037,18 @@
   const int offset_mc[4] = { 0, 0, mi_size_wide[bsize] / 2, 0 };
 
   for (int idx = 0; idx < 4; idx++) {
+#if CONFIG_EXTENDED_SDP
+    if (pc_tree->horizontal3[cur_region_type][idx]) {
+      av1_free_pc_tree_recursive(pc_tree->horizontal3[cur_region_type][idx],
+                                 num_planes, 0, 0);
+      pc_tree->horizontal3[cur_region_type][idx] = NULL;
+    }
+
+    pc_tree->horizontal3[cur_region_type][idx] = av1_alloc_pc_tree_node(
+        xd->tree_type, mi_row + offset_mr[idx], mi_col + offset_mc[idx],
+        subblock_sizes[idx], pc_tree, PARTITION_HORZ_3, idx, idx == 3, ss_x,
+        ss_y);
+#else
     if (pc_tree->horizontal3[idx]) {
       av1_free_pc_tree_recursive(pc_tree->horizontal3[idx], num_planes, 0, 0);
       pc_tree->horizontal3[idx] = NULL;
@@ -6920,6 +8058,7 @@
         xd->tree_type, mi_row + offset_mr[idx], mi_col + offset_mc[idx],
         subblock_sizes[idx], pc_tree, PARTITION_HORZ_3, idx, idx == 3, ss_x,
         ss_y);
+#endif
   }
 
   bool skippable = true;
@@ -6929,14 +8068,19 @@
 
     if (i > 0 && this_mi_row >= cm->mi_params.mi_rows) break;
 
-    SUBBLOCK_RDO_DATA rdo_data = { pc_tree->horizontal3[i],
-                                   get_partition_subtree_const(ptree_luma, i),
-                                   get_partition_subtree_const(template_tree,
-                                                               i),
-                                   this_mi_row,
-                                   this_mi_col,
-                                   subblock_sizes[i],
-                                   PARTITION_HORZ_3 };
+    SUBBLOCK_RDO_DATA rdo_data = {
+#if CONFIG_EXTENDED_SDP
+      pc_tree->horizontal3[cur_region_type][i],
+#else
+      pc_tree->horizontal3[i],
+#endif  // CONFIG_EXTENDED_SDP
+      get_partition_subtree_const(ptree_luma, i),
+      get_partition_subtree_const(template_tree, i),
+      this_mi_row,
+      this_mi_col,
+      subblock_sizes[i],
+      PARTITION_HORZ_3
+    };
     if (!rd_try_subblock_new(cpi, td, tile_data, tp, &rdo_data, *best_rdc,
                              &sum_rdc, multi_pass_mode, &skippable,
                              max_recursion_depth)) {
@@ -6984,6 +8128,10 @@
   const int mi_row = blk_params->mi_row, mi_col = blk_params->mi_col;
   const BLOCK_SIZE bsize = blk_params->bsize;
 
+#if CONFIG_EXTENDED_SDP
+  REGION_TYPE cur_region_type = pc_tree->region_type;
+#endif  // CONFIG_EXTENDED_SDP
+
   if (is_part_pruned_by_forced_partition(part_search_state, PARTITION_VERT_3) ||
       !part_search_state->partition_3_allowed[VERT] ||
       part_search_state->prune_partition_3[VERT]) {
@@ -7011,6 +8159,14 @@
   const int quarter_step = mi_size_wide[bsize] / 4;
 
   sum_rdc.rate = search_state->partition_cost[PARTITION_VERT_3];
+#if CONFIG_EXTENDED_SDP
+  if (pc_tree->region_type == MIXED_INTER_INTRA_REGION && pc_tree->parent &&
+      is_inter_sdp_allowed(pc_tree->parent->block_size,
+                           pc_tree->parent->partitioning) &&
+      is_bsize_allowed_for_inter_sdp(bsize, PARTITION_VERT_3))
+    sum_rdc.rate +=
+        part_search_state->region_type_cost[MIXED_INTER_INTRA_REGION];
+#endif  // CONFIG_EXTENDED_SDP
   sum_rdc.rdcost = RDCOST(x->rdmult, sum_rdc.rate, 0);
 
   const BLOCK_SIZE sml_subsize =
@@ -7023,6 +8179,18 @@
   const int offset_mc[4] = { 0, quarter_step, quarter_step, 3 * quarter_step };
 
   for (int idx = 0; idx < 4; idx++) {
+#if CONFIG_EXTENDED_SDP
+    if (pc_tree->vertical3[cur_region_type][idx]) {
+      av1_free_pc_tree_recursive(pc_tree->vertical3[cur_region_type][idx],
+                                 num_planes, 0, 0);
+      pc_tree->vertical3[cur_region_type][idx] = NULL;
+    }
+
+    pc_tree->vertical3[cur_region_type][idx] = av1_alloc_pc_tree_node(
+        xd->tree_type, mi_row + offset_mr[idx], mi_col + offset_mc[idx],
+        subblock_sizes[idx], pc_tree, PARTITION_VERT_3, idx, idx == 3, ss_x,
+        ss_y);
+#else
     if (pc_tree->vertical3[idx]) {
       av1_free_pc_tree_recursive(pc_tree->vertical3[idx], num_planes, 0, 0);
       pc_tree->vertical3[idx] = NULL;
@@ -7032,6 +8200,7 @@
         xd->tree_type, mi_row + offset_mr[idx], mi_col + offset_mc[idx],
         subblock_sizes[idx], pc_tree, PARTITION_VERT_3, idx, idx == 3, ss_x,
         ss_y);
+#endif
   }
 
   bool skippable = true;
@@ -7041,14 +8210,19 @@
 
     if (i > 0 && this_mi_col >= cm->mi_params.mi_cols) break;
 
-    SUBBLOCK_RDO_DATA rdo_data = { pc_tree->vertical3[i],
-                                   get_partition_subtree_const(ptree_luma, i),
-                                   get_partition_subtree_const(template_tree,
-                                                               i),
-                                   this_mi_row,
-                                   this_mi_col,
-                                   subblock_sizes[i],
-                                   PARTITION_VERT_3 };
+    SUBBLOCK_RDO_DATA rdo_data = {
+#if CONFIG_EXTENDED_SDP
+      pc_tree->vertical3[cur_region_type][i],
+#else
+      pc_tree->vertical3[i],
+#endif  // CONFIG_EXTENDED_SDP
+      get_partition_subtree_const(ptree_luma, i),
+      get_partition_subtree_const(template_tree, i),
+      this_mi_row,
+      this_mi_col,
+      subblock_sizes[i],
+      PARTITION_VERT_3
+    };
     if (!rd_try_subblock_new(cpi, td, tile_data, tp, &rdo_data, *best_rdc,
                              &sum_rdc, multi_pass_mode, &skippable,
                              max_recursion_depth)) {
@@ -7079,69 +8253,134 @@
                                           int curr_depth) {
   const PARTITION_TYPE partition = pc_tree->partitioning;
   int max_depth = curr_depth;
+#if CONFIG_EXTENDED_SDP
+  int cur_region_type = pc_tree->region_type;
+#endif  // CONFIG_EXTENDED_SDP
   switch (partition) {
     case PARTITION_NONE: break;
     case PARTITION_SPLIT:
       for (int idx = 0; idx < 4; idx++) {
+#if CONFIG_EXTENDED_SDP
+        max_depth = AOMMAX(
+            max_depth, get_partition_depth(pc_tree->split[cur_region_type][idx],
+                                           curr_depth + 2));
+#else
         max_depth = AOMMAX(max_depth, get_partition_depth(pc_tree->split[idx],
                                                           curr_depth + 2));
+#endif  // CONFIG_EXTENDED_SDP
       }
       break;
 #if CONFIG_EXT_RECUR_PARTITIONS
     case PARTITION_HORZ:
       for (int idx = 0; idx < 2; idx++) {
+#if CONFIG_EXTENDED_SDP
+        max_depth = AOMMAX(
+            max_depth,
+            get_partition_depth(pc_tree->horizontal[cur_region_type][idx],
+                                curr_depth + 1));
+#else
         max_depth = AOMMAX(
             max_depth,
             get_partition_depth(pc_tree->horizontal[idx], curr_depth + 1));
+#endif  // CONFIG_EXTENDED_SDP
       }
       break;
     case PARTITION_VERT:
       for (int idx = 0; idx < 2; idx++) {
+#if CONFIG_EXTENDED_SDP
+        max_depth =
+            AOMMAX(max_depth,
+                   get_partition_depth(pc_tree->vertical[cur_region_type][idx],
+                                       curr_depth + 1));
+#else
         max_depth =
             AOMMAX(max_depth,
                    get_partition_depth(pc_tree->vertical[idx], curr_depth + 1));
+#endif  // CONFIG_EXTENDED_SDP
       }
       break;
     case PARTITION_HORZ_3:
       for (int idx = 0; idx < 4; idx++) {
+#if CONFIG_EXTENDED_SDP
+        max_depth = AOMMAX(
+            max_depth,
+            get_partition_depth(pc_tree->horizontal3[cur_region_type][idx],
+                                curr_depth + 1));
+#else
         max_depth = AOMMAX(
             max_depth,
             get_partition_depth(pc_tree->horizontal3[idx], curr_depth + 1));
+#endif  // CONFIG_EXTENDED_SDP
       }
       break;
     case PARTITION_VERT_3:
       for (int idx = 0; idx < 4; idx++) {
+#if CONFIG_EXTENDED_SDP
+        max_depth =
+            AOMMAX(max_depth,
+                   get_partition_depth(pc_tree->vertical3[cur_region_type][idx],
+                                       curr_depth + 1));
+#else
         max_depth = AOMMAX(
             max_depth,
             get_partition_depth(pc_tree->vertical3[idx], curr_depth + 1));
+#endif
       }
       break;
     case PARTITION_HORZ_4A:
       for (int idx = 0; idx < 4; idx++) {
+#if CONFIG_EXTENDED_SDP
+        max_depth = AOMMAX(
+            max_depth,
+            get_partition_depth(pc_tree->horizontal4a[cur_region_type][idx],
+                                curr_depth + 1));
+#else
         max_depth = AOMMAX(
             max_depth,
             get_partition_depth(pc_tree->horizontal4a[idx], curr_depth + 1));
+#endif  // CONFIG_EXTENDED_SDP
       }
       break;
     case PARTITION_HORZ_4B:
       for (int idx = 0; idx < 4; idx++) {
+#if CONFIG_EXTENDED_SDP
+        max_depth = AOMMAX(
+            max_depth,
+            get_partition_depth(pc_tree->horizontal4b[cur_region_type][idx],
+                                curr_depth + 1));
+#else
         max_depth = AOMMAX(
             max_depth,
             get_partition_depth(pc_tree->horizontal4b[idx], curr_depth + 1));
+#endif  // CONFIG_EXTENDED_SDP
       }
       break;
     case PARTITION_VERT_4A:
       for (int idx = 0; idx < 4; idx++) {
+#if CONFIG_EXTENDED_SDP
+        max_depth = AOMMAX(
+            max_depth,
+            get_partition_depth(pc_tree->vertical4a[cur_region_type][idx],
+                                curr_depth + 1));
+#else
         max_depth = AOMMAX(
             max_depth,
             get_partition_depth(pc_tree->vertical4a[idx], curr_depth + 1));
+#endif  // CONFIG_EXTENDED_SDP
       }
       break;
     case PARTITION_VERT_4B:
       for (int idx = 0; idx < 4; idx++) {
+#if CONFIG_EXTENDED_SDP
+        max_depth = AOMMAX(
+            max_depth,
+            get_partition_depth(pc_tree->vertical4b[cur_region_type][idx],
+                                curr_depth + 1));
+#else
         max_depth = AOMMAX(
             max_depth,
             get_partition_depth(pc_tree->vertical4b[idx], curr_depth + 1));
+#endif  // CONFIG_EXTENDED_SDP
       }
       break;
     default: assert(0); break;
@@ -7241,13 +8480,25 @@
   PC_TREE *const *tree = NULL;
   int num_sub_parts = 0;
   if (cur_best_partition == PARTITION_SPLIT) {
+#if CONFIG_EXTENDED_SDP
+    tree = pc_tree->split[pc_tree->region_type];
+#else
     tree = pc_tree->split;
+#endif  // CONFIG_EXTENDED_SDP
     num_sub_parts = SUB_PARTITIONS_SPLIT;
   } else if (cur_best_partition == PARTITION_HORZ) {
+#if CONFIG_EXTENDED_SDP
+    tree = pc_tree->horizontal[pc_tree->region_type];
+#else
     tree = pc_tree->horizontal;
+#endif  // CONFIG_EXTENDED_SDP
     num_sub_parts = NUM_RECT_PARTS;
   } else if (cur_best_partition == PARTITION_VERT) {
+#if CONFIG_EXTENDED_SDP
+    tree = pc_tree->vertical[pc_tree->region_type];
+#else
     tree = pc_tree->vertical;
+#endif  // CONFIG_EXTENDED_SDP
     num_sub_parts = NUM_RECT_PARTS;
   } else {
     assert(0 &&
@@ -7284,6 +8535,7 @@
 * \param[in]    mi_col             Column coordinate of the block in a step
 size of MI_SIZE
 * \param[in]    bsize              Current block size
+* \param[in]    parent_partition   Partition of the parent block
 * \param[in]    rd_cost            Pointer to the final rd cost of the block
 * \param[in]    best_rdc           Upper bound of rd cost of a valid partition
 * \param[in]    pc_tree            Pointer to the PC_TREE node storing the
@@ -7357,8 +8609,12 @@
 
 bool av1_rd_pick_partition(AV1_COMP *const cpi, ThreadData *td,
                            TileDataEnc *tile_data, TokenExtra **tp, int mi_row,
-                           int mi_col, BLOCK_SIZE bsize, RD_STATS *rd_cost,
-                           RD_STATS best_rdc, PC_TREE *pc_tree,
+                           int mi_col, BLOCK_SIZE bsize,
+#if CONFIG_EXTENDED_SDP
+                           PARTITION_TYPE parent_partition,
+#endif  // CONFIG_EXTENDED_SDP
+                           RD_STATS *rd_cost, RD_STATS best_rdc,
+                           PC_TREE *pc_tree,
 #if CONFIG_EXT_RECUR_PARTITIONS
                            const PARTITION_TREE *ptree_luma,
                            const PARTITION_TREE *template_tree,
@@ -7380,6 +8636,13 @@
   RD_SEARCH_MACROBLOCK_CONTEXT x_ctx;
   const TokenExtra *const tp_orig = *tp;
   PartitionSearchState part_search_state;
+
+#if CONFIG_EXTENDED_SDP
+  if (frame_is_intra_only(cm) && pc_tree) {
+    pc_tree->region_type = INTRA_REGION;
+  }
+#endif  // CONFIG_EXTENDED_SDP
+
   // Initialization of state variables used in partition search.
   init_partition_search_state_params(x, cpi, &part_search_state,
 #if CONFIG_EXT_RECUR_PARTITIONS
@@ -7402,6 +8665,7 @@
   // different partition path. If yes directly copy the RDO decision made for
   // the counterpart.
   PC_TREE *counterpart_block = av1_look_for_counterpart_block(pc_tree);
+  assert(pc_tree != NULL);
   if (counterpart_block
 #if CONFIG_CB1TO4_SPLIT
       &&
@@ -7412,6 +8676,10 @@
                               ? counterpart_block->parent->block_size
                               : BLOCK_INVALID))
 #endif  // CONFIG_CB1TO4_SPLIT
+#if CONFIG_EXTENDED_SDP
+      && (pc_tree->region_type == counterpart_block->region_type &&
+          (pc_tree->region_type != INTRA_REGION || frame_is_intra_only(cm)))
+#endif  // CONFIG_EXTENDED_SDP
   ) {
     if (counterpart_block->rd_cost.rate != INT_MAX) {
       av1_copy_pc_tree_recursive(xd, cm, pc_tree, counterpart_block,
@@ -7568,7 +8836,11 @@
 #if CONFIG_CB1TO4_SPLIT
         blk_params.parent_bsize,
 #endif  // CONFIG_CB1TO4_SPLIT
-        ptree_luma, template_tree, &pc_tree->chroma_ref_info);
+        ptree_luma, template_tree,
+#if CONFIG_EXTENDED_SDP
+        pc_tree->region_type,
+#endif  // CONFIG_EXTENDED_SDP
+        &pc_tree->chroma_ref_info);
   }
 #endif  // CONFIG_EXT_RECUR_PARTITIONS
 
@@ -7683,7 +8955,19 @@
 #endif  // CONFIG_ML_PART_SPLIT
   // PARTITION_NONE search stage.
   int64_t part_none_rd = INT64_MAX;
+#if CONFIG_EXTENDED_SDP
+  int partition_none_allowed = 1;
+  if (pc_tree->parent && pc_tree->region_type == INTRA_REGION &&
+      pc_tree->parent->region_type == MIXED_INTER_INTRA_REGION &&
+      xd->tree_type != CHROMA_PART)
+    partition_none_allowed = 0;
+  if (!frame_is_intra_only(cm) && pc_tree->region_type == INTRA_REGION)
+    search_none_after_rect &= (xd->tree_type != CHROMA_PART);
+  if (!search_none_after_rect && !search_none_after_split &&
+      partition_none_allowed) {
+#else
   if (!search_none_after_rect && !search_none_after_split) {
+#endif  // CONFIG_EXTENDED_SDP
     none_partition_search(cpi, td, tile_data, x, pc_tree, sms_tree, &x_ctx,
                           &part_search_state, &best_rdc, &pb_source_variance,
                           none_rd, &part_none_rd
@@ -7693,6 +8977,14 @@
 #endif  // CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
     );
   }
+#if CONFIG_EXTENDED_SDP
+  if (pc_tree->parent && pc_tree->region_type == INTRA_REGION &&
+      pc_tree->parent->region_type == MIXED_INTER_INTRA_REGION &&
+      xd->tree_type == CHROMA_PART) {
+    *rd_cost = best_rdc;
+    return part_search_state.found_best_partition;
+  }
+#endif  // CONFIG_EXTENDED_SDP
 
 #if CONFIG_EXT_RECUR_PARTITIONS
   if (cpi->sf.part_sf.end_part_search_after_consec_failures && x->is_whole_sb &&
@@ -7743,17 +9035,35 @@
     // after rect
     assert(pc_tree->partitioning == PARTITION_SPLIT);
     for (int idx = 0; idx < 4; idx++) {
+#if CONFIG_EXTENDED_SDP
+      const int depth =
+          get_partition_depth(pc_tree->split[pc_tree->region_type][idx], 0);
+#else
       const int depth = get_partition_depth(pc_tree->split[idx], 0);
+#endif  // CONFIG_EXTENDED_SDP
       search_none_after_split &= depth == 0;
     }
   }
   if (cpi->sf.part_sf.prune_rect_with_split_depth && !frame_is_intra_only(cm) &&
       part_search_state.forced_partition == PARTITION_INVALID &&
+#if CONFIG_EXTENDED_SDP
+      pc_tree->split[pc_tree->region_type][0] &&
+      pc_tree->split[pc_tree->region_type][1] &&
+      pc_tree->split[pc_tree->region_type][2] &&
+      pc_tree->split[pc_tree->region_type][3]
+#else
       pc_tree->split[0] && pc_tree->split[1] && pc_tree->split[2] &&
-      pc_tree->split[3]) {
+      pc_tree->split[3]
+#endif  // CONFIG_EXTENDED_SDP
+  ) {
     int min_depth = INT_MAX, max_depth = 0;
     for (int idx = 0; idx < 4; idx++) {
+#if CONFIG_EXTENDED_SDP
+      const int depth =
+          get_partition_depth(pc_tree->split[pc_tree->region_type][idx], 0);
+#else
       const int depth = get_partition_depth(pc_tree->split[idx], 0);
+#endif  // CONFIG_EXTENDED_SDP
       min_depth = AOMMIN(min_depth, depth);
       max_depth = AOMMAX(max_depth, depth);
     }
@@ -7765,6 +9075,9 @@
   }
 
   if (part_search_state.forced_partition == PARTITION_INVALID &&
+#if CONFIG_EXTENDED_SDP
+      partition_none_allowed &&
+#endif  // CONFIG_EXTENDED_SDP
       search_none_after_split) {
     none_partition_search(cpi, td, tile_data, x, pc_tree, sms_tree, &x_ctx,
                           &part_search_state, &best_rdc, &pb_source_variance,
@@ -7787,6 +9100,9 @@
 #if CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
       &level_banks,
 #endif  // CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
+#if CONFIG_EXTENDED_SDP
+      parent_partition,
+#endif  // CONFIG_INTER_SDP
       part_none_rd
 #if CONFIG_ML_PART_SPLIT
       ,
@@ -7803,7 +9119,12 @@
   assert(IMPLIES(!cpi->oxcf.part_cfg.enable_rect_partitions,
                  !part_search_state.do_rectangular_split));
 #if CONFIG_EXT_RECUR_PARTITIONS
+#if CONFIG_EXTENDED_SDP
+  if (search_none_after_rect && !search_none_after_split &&
+      partition_none_allowed) {
+#else
   if (search_none_after_rect && !search_none_after_split) {
+#endif  // CONFIG_EXTENDED_SDP
     prune_none_with_rect_results(&part_search_state, pc_tree);
     none_partition_search(cpi, td, tile_data, x, pc_tree, sms_tree, &x_ctx,
                           &part_search_state, &best_rdc, &pb_source_variance,
@@ -7918,51 +9239,63 @@
 #endif  // CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
                           multi_pass_mode, ext_recur_depth);
 
-  prune_ext_partitions_4way(cpi, pc_tree, &part_search_state,
-                            partition_boundaries);
+#if CONFIG_EXTENDED_SDP
+  if ((pc_tree->region_type != INTRA_REGION || frame_is_intra_only(cm))) {
+#endif  // CONFIG_EXTENDED_SDP
+    prune_ext_partitions_4way(cpi, pc_tree, &part_search_state,
+                              partition_boundaries);
 
-  // PARTITION_HORZ_4A
-  search_partition_horz_4a(&part_search_state, cpi, td, tile_data, tp,
-                           &best_rdc, pc_tree,
-                           track_ptree_luma ? ptree_luma : NULL, template_tree,
-                           &x_ctx, &part_search_state,
+    // PARTITION_HORZ_4A
+    search_partition_horz_4a(&part_search_state, cpi, td, tile_data, tp,
+                             &best_rdc, pc_tree,
+                             track_ptree_luma ? ptree_luma : NULL,
+                             template_tree, &x_ctx, &part_search_state,
 #if CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
-                           &level_banks,
+                             &level_banks,
 #endif  // CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
-                           multi_pass_mode, ext_recur_depth);
+                             multi_pass_mode, ext_recur_depth);
 
-  // PARTITION_HORZ_4B
-  search_partition_horz_4b(&part_search_state, cpi, td, tile_data, tp,
-                           &best_rdc, pc_tree,
-                           track_ptree_luma ? ptree_luma : NULL, template_tree,
-                           &x_ctx, &part_search_state,
+    // PARTITION_HORZ_4B
+    search_partition_horz_4b(&part_search_state, cpi, td, tile_data, tp,
+                             &best_rdc, pc_tree,
+                             track_ptree_luma ? ptree_luma : NULL,
+                             template_tree, &x_ctx, &part_search_state,
 #if CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
-                           &level_banks,
+                             &level_banks,
 #endif  // CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
-                           multi_pass_mode, ext_recur_depth);
+                             multi_pass_mode, ext_recur_depth);
 
-  // PARTITION_VERT_4A
-  search_partition_vert_4a(&part_search_state, cpi, td, tile_data, tp,
-                           &best_rdc, pc_tree,
-                           track_ptree_luma ? ptree_luma : NULL, template_tree,
-                           &x_ctx, &part_search_state,
+    // PARTITION_VERT_4A
+    search_partition_vert_4a(&part_search_state, cpi, td, tile_data, tp,
+                             &best_rdc, pc_tree,
+                             track_ptree_luma ? ptree_luma : NULL,
+                             template_tree, &x_ctx, &part_search_state,
 #if CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
-                           &level_banks,
+                             &level_banks,
 #endif  // CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
-                           multi_pass_mode, ext_recur_depth);
+                             multi_pass_mode, ext_recur_depth);
 
-  // PARTITION_VERT_4B
-  search_partition_vert_4b(&part_search_state, cpi, td, tile_data, tp,
-                           &best_rdc, pc_tree,
-                           track_ptree_luma ? ptree_luma : NULL, template_tree,
-                           &x_ctx, &part_search_state,
+    // PARTITION_VERT_4B
+    search_partition_vert_4b(&part_search_state, cpi, td, tile_data, tp,
+                             &best_rdc, pc_tree,
+                             track_ptree_luma ? ptree_luma : NULL,
+                             template_tree, &x_ctx, &part_search_state,
 #if CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
-                           &level_banks,
+                             &level_banks,
 #endif  // CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
-                           multi_pass_mode, ext_recur_depth);
+                             multi_pass_mode, ext_recur_depth);
+#if CONFIG_EXTENDED_SDP
+  }
+#endif  // CONFIG_EXTENDED_SDP
 #endif  // CONFIG_EXT_RECUR_PARTITIONS
 
-  if (bsize == cm->sb_size && !part_search_state.found_best_partition) {
+  if (bsize == cm->sb_size && !part_search_state.found_best_partition
+#if CONFIG_EXTENDED_SDP
+      && ((!frame_is_intra_only(cm) &&
+           pc_tree->region_type == MIXED_INTER_INTRA_REGION) ||
+          ((frame_is_intra_only(cm) && pc_tree->region_type == INTRA_REGION)))
+#endif  // CONFIG_EXTENDED_SDP
+  ) {
     if (x->must_find_valid_partition) {
       aom_internal_error(
           &cpi->common.error, AOM_CODEC_ERROR,
@@ -7991,6 +9324,23 @@
   }
 #endif  // CONFIG_EXT_RECUR_PARTITIONS && !defined(NDEBUG)
 
+#if CONFIG_EXTENDED_SDP
+  if (frame_is_intra_only(cm)) pc_tree->inter_sdp_allowed_flag = 0;
+  if (!frame_is_intra_only(cm) &&
+      pc_tree->region_type == MIXED_INTER_INTRA_REGION && pc_tree->parent &&
+      pc_tree->inter_sdp_allowed_flag == 1 &&
+      is_bsize_allowed_for_inter_sdp(bsize, PARTITION_HORZ)) {
+    search_intra_region_partitioning(
+        &part_search_state, cpi, td, tile_data, tp, &best_rdc, pc_tree,
+        track_ptree_luma ? ptree_luma : NULL, template_tree, &x_ctx,
+        &part_search_state,
+#if CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
+        &level_banks,
+#endif  // CONFIG_MVP_IMPROVEMENT || WARP_CU_BANK
+        multi_pass_mode, ext_recur_depth, parent_partition);
+  }
+#endif  // CONFIG_EXTENDED_SDP
+
   // Store the final rd cost
   *rd_cost = best_rdc;
 #if CONFIG_MVP_IMPROVEMENT
diff --git a/av1/encoder/partition_search.h b/av1/encoder/partition_search.h
index fec481c..f11aa1c 100644
--- a/av1/encoder/partition_search.h
+++ b/av1/encoder/partition_search.h
@@ -34,8 +34,12 @@
                           PC_TREE *pc_tree);
 bool av1_rd_pick_partition(AV1_COMP *const cpi, ThreadData *td,
                            TileDataEnc *tile_data, TokenExtra **tp, int mi_row,
-                           int mi_col, BLOCK_SIZE bsize, RD_STATS *rd_cost,
-                           RD_STATS best_rdc, PC_TREE *pc_tree,
+                           int mi_col, BLOCK_SIZE bsize,
+#if CONFIG_EXTENDED_SDP
+                           PARTITION_TYPE parent_partition,
+#endif  // CONFIG_EXTENDED_SDP
+                           RD_STATS *rd_cost, RD_STATS best_rdc,
+                           PC_TREE *pc_tree,
 #if CONFIG_EXT_RECUR_PARTITIONS
                            const PARTITION_TREE *ptree_luma,
                            const PARTITION_TREE *template_tree,
diff --git a/av1/encoder/partition_strategy.c b/av1/encoder/partition_strategy.c
index 853f06e..3c19b0e 100644
--- a/av1/encoder/partition_strategy.c
+++ b/av1/encoder/partition_strategy.c
@@ -1467,6 +1467,18 @@
       : (rect_part == PARTITION_HORZ) ? rect_part_win_info->rect_part_win[HORZ]
                                       : rect_part_win_info->rect_part_win[VERT];
   num_win += (sub_part_win) ? 1 : 0;
+#if CONFIG_EXTENDED_SDP
+  REGION_TYPE cur_region_type = pc_tree->region_type;
+  if (pc_tree->split[cur_region_type][split_idx1]) {
+    num_win += (pc_tree->split[cur_region_type][split_idx1]->partitioning ==
+                PARTITION_NONE);
+  } else {
+    num_win += 1;
+  }
+  if (pc_tree->split[cur_region_type][split_idx2]) {
+    num_win += (pc_tree->split[cur_region_type][split_idx2]->partitioning ==
+                PARTITION_NONE);
+#else
   if (pc_tree->split[split_idx1]) {
     num_win +=
         (pc_tree->split[split_idx1]->partitioning == PARTITION_NONE) ? 1 : 0;
@@ -1476,6 +1488,7 @@
   if (pc_tree->split[split_idx2]) {
     num_win +=
         (pc_tree->split[split_idx2]->partitioning == PARTITION_NONE) ? 1 : 0;
+#endif  // CONFIG_EXTENDED_SDP
   } else {
     num_win += 1;
   }
@@ -2030,10 +2043,20 @@
 
   // Whether we are in the middle of a PARTITION_3 subblock
   const PC_TREE *parent = pc_tree->parent;
+#if CONFIG_EXTENDED_SDP
+  REGION_TYPE cur_region_type = pc_tree->region_type;
+  ml_features[num_features++] =
+      parent && (parent->horizontal3[cur_region_type][1] == pc_tree ||
+                 parent->horizontal3[cur_region_type][2] == pc_tree);
+  ml_features[num_features++] =
+      parent && (parent->vertical3[cur_region_type][1] == pc_tree ||
+                 parent->vertical3[cur_region_type][2] == pc_tree);
+#else
   ml_features[num_features++] = parent && (parent->horizontal3[1] == pc_tree ||
                                            parent->horizontal3[2] == pc_tree);
   ml_features[num_features++] = parent && (parent->vertical3[1] == pc_tree ||
                                            parent->vertical3[2] == pc_tree);
+#endif  // CONFIG_EXTENDED_SDP
   assert(num_features == 19);
 }
 
diff --git a/av1/encoder/rd.c b/av1/encoder/rd.c
index d32653b..0e71e22 100644
--- a/av1/encoder/rd.c
+++ b/av1/encoder/rd.c
@@ -99,6 +99,12 @@
 void av1_fill_mode_rates(AV1_COMMON *const cm, const MACROBLOCKD *xd,
                          ModeCosts *mode_costs, FRAME_CONTEXT *fc) {
   int i, j;
+#if CONFIG_EXTENDED_SDP
+  for (i = 0; i < INTER_SDP_BSIZE_GROUP; ++i) {
+    av1_cost_tokens_from_cdf(mode_costs->region_type_cost[i],
+                             fc->region_type_cdf[i], NULL);
+  }
+#endif  // CONFIG_EXTENDED_SDP
 #if CONFIG_EXT_RECUR_PARTITIONS
   for (int plane_index = (xd->tree_type == CHROMA_PART);
        plane_index < PARTITION_STRUCTURE_NUM; plane_index++) {
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index f2a7745..d96450b 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -6595,7 +6595,7 @@
                                        int64_t best_rd) {
   const AV1_COMMON *const cm = &cpi->common;
   MACROBLOCKD *const xd = &x->e_mbd;
-  if (!av1_allow_intrabc(cm) || (xd->tree_type == CHROMA_PART) ||
+  if (!av1_allow_intrabc(cm, xd) || (xd->tree_type == CHROMA_PART) ||
       !cpi->oxcf.kf_cfg.enable_intrabc)
     return INT64_MAX;
   const int num_planes = av1_num_planes(cm);
@@ -10584,7 +10584,7 @@
   if (search_state.best_skip2 == 0) {
     const int try_intrabc = cpi->oxcf.kf_cfg.enable_intrabc &&
                             cpi->oxcf.kf_cfg.enable_intrabc_ext &&
-                            av1_allow_intrabc(cm) &&
+                            av1_allow_intrabc(cm, xd) &&
                             (xd->tree_type != CHROMA_PART);
     if (try_intrabc) {
       this_rd_cost.rdcost = INT64_MAX;
diff --git a/av1/encoder/reconinter_enc.c b/av1/encoder/reconinter_enc.c
index eb0b368..17c6029 100644
--- a/av1/encoder/reconinter_enc.c
+++ b/av1/encoder/reconinter_enc.c
@@ -358,7 +358,7 @@
 
 #if CONFIG_MORPH_PRED
   if (mbmi->morph_pred) {
-    assert(av1_allow_intrabc(cm));
+    assert(av1_allow_intrabc(cm, xd));
     assert(is_intrabc_block(mbmi, xd->tree_type));
     av1_build_morph_pred(cm, xd, bsize, mi_row, mi_col);
   }
diff --git a/av1/encoder/segmentation.c b/av1/encoder/segmentation.c
index b8adb49..31d1ffc 100644
--- a/av1/encoder/segmentation.c
+++ b/av1/encoder/segmentation.c
@@ -63,7 +63,11 @@
   no_pred_segcounts[segment_id]++;
 
   // Temporal prediction not allowed on key frames
-  if (cm->current_frame.frame_type != KEY_FRAME) {
+  if (cm->current_frame.frame_type != KEY_FRAME
+#if CONFIG_EXTENDED_SDP
+      && xd->mi[0]->region_type != INTRA_REGION
+#endif  // CONFIG_EXTENDED_SDP
+  ) {
     const BLOCK_SIZE bsize = xd->mi[0]->sb_type[xd->tree_type == CHROMA_PART];
     // Test to see if the segment id matches the predicted value.
     const int pred_segment_id =
diff --git a/build/cmake/aom_config_defaults.cmake b/build/cmake/aom_config_defaults.cmake
index 6625c9b..8ced654 100644
--- a/build/cmake/aom_config_defaults.cmake
+++ b/build/cmake/aom_config_defaults.cmake
@@ -197,6 +197,8 @@
   "AV2 experiment flag to enable modified context derivation : CWG-B065.")
 set_aom_config_var(CONFIG_EXTENDED_WARP_PREDICTION 1
                    "AV2 experiment flag to add new local warp modes")
+set_aom_config_var(CONFIG_EXTENDED_SDP 1
+                   "Enable SDP for intra blocks in inter frame")
 # Begin: CWG-C016
 set_aom_config_var(
   CONFIG_LR_IMPROVEMENTS
diff --git a/tools/aom_entropy_optimizer.c b/tools/aom_entropy_optimizer.c
index f88324a..d53937e 100644
--- a/tools/aom_entropy_optimizer.c
+++ b/tools/aom_entropy_optimizer.c
@@ -620,6 +620,15 @@
       "[CCTX_CONTEXTS][CDF_SIZE(CCTX_TYPES)]",
       0, &total_count, 0, mem_wanted, "Transforms");
 
+#if CONFIG_INTER_SDP
+  cts_each_dim[0] = INTER_SDP_BSIZE_GROUP;
+  cts_each_dim[1] = REGION_TYPES;
+  optimize_cdf_table(&fc.region_type[0][0], probsfile, 2, cts_each_dim,
+                     "static aom_cdf_prob default_region_type_cdf"
+                     "[INTER_SDP_BSIZE_GROUP][CDF_SIZE(2)]",
+                     0, &total_count, 0, mem_wanted, "Partitions");
+#endif  // CONFIG_INTER_SDP
+
 #if CONFIG_EXT_RECUR_PARTITIONS
   cts_each_dim[0] = PARTITION_STRUCTURE_NUM;
   cts_each_dim[1] = PARTITION_CONTEXTS;