code: def forward_caption(self, x, mask_features, extra=None):
      assert len(x) == self.num_feature_levels
      src = []
      pos = []
      size_list = []
  
      for i in range(self.num_feature_levels):
          size_list.append(x[i].shape[-2:])
          pos.append(self.pe_layer(x[i], None).flatten(2))
          src.append(
              self.input_proj[i](x[i]).flatten(2)
              + self.level_embed.weight[i][None, :, None]
          )
  
          # flatten NxCxHxW to HWxNxC
          pos[-1] = pos[-1].permute(2, 0, 1)
          src[-1] = src[-1].permute(2, 0, 1)
  
      _, bs, _ = src[0].shape
  
      # QxNxC
      query_embed_ = self.query_embed.weight.unsqueeze(1).repeat(
          1, bs, 1
      )
      query_feat = self.query_feat.weight.unsqueeze(1).repeat(1, bs, 1)
      lang_token = extra["start_token"].repeat(bs, 1)
      pos_embed = self.pos_embed_caping.weight.unsqueeze(1).repeat(
          1, bs, 1
      )
  
      # prepare token embedding for evaluation
      token_embs = self.lang_encoder.lang_encoder.token_embedding.weight
  
      for cap_idx in range(0, self.captioning_step):
          lang_embed = self.lang_encoder.forward_language(
              (lang_token,), with_cls_embed=False
          )[1].transpose(0, 1)
          # concat object query, class token and caption token.
          output = torch.cat((query_feat, lang_embed), dim=0)
          lang_embed += pos_embed
          query_embed = torch.cat((query_embed_, lang_embed), dim=0)
  
          # prediction heads on learnable query features
          results = self.forward_prediction_heads(
              output, mask_features, attn_mask_target_size=size_list[0]
          )
          attn_mask = results["attn_mask"]
  
          for i in range(self.num_layers):
              level_index = i % self.num_feature_levels
              attn_mask[
                  torch.where(attn_mask.sum(-1) == attn_mask.shape[-1])
              ] = False
              attn_mask = torch.cat(
                  (
                      attn_mask,
                      torch.zeros_like(
                          attn_mask[:, : self.max_token_num, :]
                      ),
                  ),
                  dim=1,
              )
              self_tgt_mask = self.self_attn_mask.repeat(
                  output.shape[1] * self.num_heads, 1, 1
              )
  
              if "grounding_mask" in extra:
                  bs, nq, wh = attn_mask.shape
                  assert bs == self.num_heads, (
                      "Only support single "
                      "image referring captioning."
                  )
                  grounding_mask = extra["grounding_mask"]
                  attn_mask = attn_mask.reshape(
                      bs, nq, size_list[i % 3][0], size_list[i % 3][1]
                  )
                  grounding_mask = F.interpolate(
                      grounding_mask.float(),
                      size_list[i % 3],
                      mode="nearest",
                  ).bool()[0, 0]
                  attn_mask[
                      :, self.num_queries :, grounding_mask
                  ] = True
                  attn_mask = attn_mask.reshape(bs, nq, wh)
  
              # attention: cross-attention first
              (
                  output,
                  avg_attn,
              ) = self.transformer_cross_attention_layers[i](
                  output,
                  src[level_index],
                  memory_mask=attn_mask,
                  # here we do not apply masking on padded region
                  memory_key_padding_mask=None,
                  pos=pos[level_index],
                  query_pos=query_embed,
              )
  
              output = self.transformer_self_attention_layers[i](
                  output,
                  tgt_mask=self_tgt_mask,
                  tgt_key_padding_mask=None,
                  query_pos=query_embed,
              )
  
              output = self.transformer_ffn_layers[i](output)
  
              results = self.forward_prediction_heads(
                  output,
                  mask_features,
                  attn_mask_target_size=size_list[
                      (i + 1) % self.num_feature_levels
                  ],
              )
              attn_mask = results["attn_mask"]
  
          pred_captions = results["outputs_caption"]
          pred_captions = pred_captions @ token_embs.t()
          lang_token[:, cap_idx + 1] = pred_captions[:, cap_idx].max(
              -1
          )[1]
  
      texts = self.lang_encoder.tokenizer.batch_decode(
          lang_token, skip_special_tokens=False
      )
      texts_new = []
  
      for x in texts:
          x = x.split("<|endoftext|>")[0]
          x = x.replace("<|endoftext|>", "")
          x = x.replace("<|startoftext|>", "")
          x = x.strip()
          texts_new.append(x)
  
      out = {"pred_caption": texts_new}
      return out
  
file_path: mmdetection/projects/XDecoder/xdecoder/transformer_decoder.py
imports: import torch
  from torch import nn
  from torch.nn import functional
  from mmdet.registry import MODELS
  from .language_model import LanguageEncoder
  from .transformer_blocks import MLP, Conv2d, CrossAttentionLayer, FFNLayer, PositionEmbeddingSine, SelfAttentionLayer
  from .utils import is_lower_torch_version
label_desc: Use image node_id 3 for calling the XDecoderTransformerDecoder obj's underlying member method code with example usage: obj.forward_caption(x, mask_features, extra) and returns: out