uint32_t
nouveau_vp3_bsp_end(struct nouveau_vp3_decoder *dec, union pipe_desc desc)
{
   enum pipe_video_format codec = u_reduce_video_profile(dec->base.profile);
   unsigned comm_seq = dec->fence_seq;
   struct nouveau_bo *bsp_bo = dec->bsp_bo[comm_seq % NOUVEAU_VP3_VIDEO_QDEPTH];
   uint32_t endmarker, caps;
   struct strparm_bsp *str_bsp = strparm_bsp(dec);
   char *bsp = bsp_bo->map;
   /*
    * 0x000..0x100: picparm_bsp
    * 0x200..0x500: picparm_vp
    * 0x500..0x700: comm
    * 0x700..onward: raw bitstream
    */

   switch (codec){
   case PIPE_VIDEO_FORMAT_MPEG12:
      endmarker = 0xb7010000;
      caps = nouveau_vp3_fill_picparm_mpeg12_bsp(dec, desc.mpeg12, bsp);
      break;
   case PIPE_VIDEO_FORMAT_MPEG4:
      endmarker = 0xb1010000;
      caps = nouveau_vp3_fill_picparm_mpeg4_bsp(dec, desc.mpeg4, bsp);
      break;
   case PIPE_VIDEO_FORMAT_VC1: {
      endmarker = 0x0a010000;
      caps = nouveau_vp3_fill_picparm_vc1_bsp(dec, desc.vc1, bsp);
      break;
   }
   case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
      endmarker = 0x0b010000;
      caps = nouveau_vp3_fill_picparm_h264_bsp(dec, desc.h264, bsp);
      break;
   }
   default: assert(0); return -1;
   }

   caps |= 0 << 16; // reset struct comm if flag is set
   caps |= 1 << 17; // enable watchdog
   caps |= 0 << 18; // do not report error to VP, so it can continue decoding what we have
   caps |= 0 << 19; // if enabled, use crypto crap?

   str_bsp = strparm_bsp(dec);
   str_bsp->w1[0] = 0x1;

   /* Append end sequence */
   *(uint32_t *)dec->bsp_ptr = endmarker;
   dec->bsp_ptr += 4;
   *(uint32_t *)dec->bsp_ptr = 0x00000000;
   dec->bsp_ptr += 4;
   *(uint32_t *)dec->bsp_ptr = endmarker;
   dec->bsp_ptr += 4;
   *(uint32_t *)dec->bsp_ptr = 0x00000000;
   str_bsp->w0[0] += 16;

   dec->bsp_ptr = NULL;

   return caps;
}
uint32_t
nouveau_vp3_bsp(struct nouveau_vp3_decoder *dec,  union pipe_desc desc,
                struct nouveau_vp3_video_buffer *target,
                unsigned comm_seq, unsigned num_buffers,
                const void *const *data, const unsigned *num_bytes)
{
   enum pipe_video_format codec = u_reduce_video_profile(dec->base.profile);
   struct nouveau_bo *bsp_bo = dec->bsp_bo[comm_seq % NOUVEAU_VP3_VIDEO_QDEPTH];
   char *bsp;
   uint32_t endmarker, caps;
   struct strparm_bsp *str_bsp;
   int i;

   bsp = bsp_bo->map;
   /*
    * 0x000..0x100: picparm_bsp
    * 0x200..0x500: picparm_vp
    * 0x500..0x700: comm
    * 0x700..onward: raw bitstream
    */

   switch (codec){
   case PIPE_VIDEO_FORMAT_MPEG12:
      endmarker = 0xb7010000;
      caps = nouveau_vp3_fill_picparm_mpeg12_bsp(dec, desc.mpeg12, bsp);
      break;
   case PIPE_VIDEO_FORMAT_MPEG4:
      endmarker = 0xb1010000;
      caps = nouveau_vp3_fill_picparm_mpeg4_bsp(dec, desc.mpeg4, bsp);
      break;
   case PIPE_VIDEO_FORMAT_VC1: {
      endmarker = 0x0a010000;
      caps = nouveau_vp3_fill_picparm_vc1_bsp(dec, desc.vc1, bsp);
      break;
   }
   case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
      endmarker = 0x0b010000;
      caps = nouveau_vp3_fill_picparm_h264_bsp(dec, desc.h264, bsp);
      break;
   }
   default: assert(0); return -1;
   }

   caps |= 0 << 16; // reset struct comm if flag is set
   caps |= 1 << 17; // enable watchdog
   caps |= 0 << 18; // do not report error to VP, so it can continue decoding what we have
   caps |= 0 << 19; // if enabled, use crypto crap?
   bsp += 0x100;

   str_bsp = (struct strparm_bsp *)bsp;
   memset(str_bsp, 0, 0x80);
   str_bsp->w0[0] = 16;
   str_bsp->w1[0] = 0x1;
   bsp += 0x100;
   /* Reserved for picparm_vp */
   bsp += 0x300;
   /* Reserved for comm */
#if !NOUVEAU_VP3_DEBUG_FENCE
   memset(bsp, 0, 0x200);
#endif
   bsp += 0x200;
   for (i = 0; i < num_buffers; ++i) {
      memcpy(bsp, data[i], num_bytes[i]);
      bsp += num_bytes[i];
      str_bsp->w0[0] += num_bytes[i];
   }

   /* Append end sequence */
   *(uint32_t *)bsp = endmarker;
   bsp += 4;
   *(uint32_t *)bsp = 0x00000000;
   bsp += 4;
   *(uint32_t *)bsp = endmarker;
   bsp += 4;
   *(uint32_t *)bsp = 0x00000000;

   return caps;
}