func: static int svq1_encode_plane(SVQ1Context *s, int plane,
  
                               unsigned char *src_plane,
  
                               unsigned char *ref_plane,
  
                               unsigned char *decoded_plane,
  
                               int width, int height, int src_stride, int stride)
  
  {
  
      const AVFrame *f = s->avctx->coded_frame;
  
      int x, y;
  
      int i;
  
      int block_width, block_height;
  
      int level;
  
      int threshold[6];
  
      uint8_t *src     = s->scratchbuf + stride * 16;
  
      const int lambda = (f->quality * f->quality) >>
  
                         (2 * FF_LAMBDA_SHIFT);
  
  
  
      /* figure out the acceptable level thresholds in advance */
  
      threshold[5] = QUALITY_THRESHOLD;
  
      for (level = 4; level >= 0; level--)
  
          threshold[level] = threshold[level + 1] * THRESHOLD_MULTIPLIER;
  
  
  
      block_width  = (width  + 15) / 16;
  
      block_height = (height + 15) / 16;
  
  
  
      if (f->pict_type == AV_PICTURE_TYPE_P) {
  
          s->m.avctx                         = s->avctx;
  
          s->m.current_picture_ptr           = &s->m.current_picture;
  
          s->m.last_picture_ptr              = &s->m.last_picture;
  
          s->m.last_picture.f.data[0]        = ref_plane;
  
          s->m.linesize                      =
  
          s->m.last_picture.f.linesize[0]    =
  
          s->m.new_picture.f.linesize[0]     =
  
          s->m.current_picture.f.linesize[0] = stride;
  
          s->m.width                         = width;
  
          s->m.height                        = height;
  
          s->m.mb_width                      = block_width;
  
          s->m.mb_height                     = block_height;
  
          s->m.mb_stride                     = s->m.mb_width + 1;
  
          s->m.b8_stride                     = 2 * s->m.mb_width + 1;
  
          s->m.f_code                        = 1;
  
          s->m.pict_type                     = f->pict_type;
  
          s->m.me_method                     = s->avctx->me_method;
  
          s->m.me.scene_change_score         = 0;
  
          s->m.flags                         = s->avctx->flags;
  
          // s->m.out_format                    = FMT_H263;
  
          // s->m.unrestricted_mv               = 1;
  
          s->m.lambda                        = f->quality;
  
          s->m.qscale                        = s->m.lambda * 139 +
  
                                               FF_LAMBDA_SCALE * 64 >>
  
                                               FF_LAMBDA_SHIFT + 7;
  
          s->m.lambda2                       = s->m.lambda * s->m.lambda +
  
                                               FF_LAMBDA_SCALE / 2 >>
  
                                               FF_LAMBDA_SHIFT;
  
  
  
          if (!s->motion_val8[plane]) {
  
              s->motion_val8[plane]  = av_mallocz((s->m.b8_stride *
  
                                                   block_height * 2 + 2) *
  
                                                  2 * sizeof(int16_t));
  
              s->motion_val16[plane] = av_mallocz((s->m.mb_stride *
  
                                                   (block_height + 2) + 1) *
  
                                                  2 * sizeof(int16_t));
  
          }
  
  
  
          s->m.mb_type = s->mb_type;
  
  
  
          // dummies, to avoid segfaults
  
          s->m.current_picture.mb_mean   = (uint8_t *)s->dummy;
  
          s->m.current_picture.mb_var    = (uint16_t *)s->dummy;
  
          s->m.current_picture.mc_mb_var = (uint16_t *)s->dummy;
  
          s->m.current_picture.mb_type = s->dummy;
  
  
  
          s->m.current_picture.motion_val[0]   = s->motion_val8[plane] + 2;
  
          s->m.p_mv_table                      = s->motion_val16[plane] +
  
                                                 s->m.mb_stride + 1;
  
          s->m.dsp                             = s->dsp; // move
  
          ff_init_me(&s->m);
  
  
  
          s->m.me.dia_size      = s->avctx->dia_size;
  
          s->m.first_slice_line = 1;
  
          for (y = 0; y < block_height; y++) {
  
              s->m.new_picture.f.data[0] = src - y * 16 * stride; // ugly
  
              s->m.mb_y                  = y;
  
  
  
              for (i = 0; i < 16 && i + 16 * y < height; i++) {
  
                  memcpy(&src[i * stride], &src_plane[(i + 16 * y) * src_stride],
  
                         width);
  
                  for (x = width; x < 16 * block_width; x++)
  
                      src[i * stride + x] = src[i * stride + x - 1];
  
              }
  
              for (; i < 16 && i + 16 * y < 16 * block_height; i++)
  
                  memcpy(&src[i * stride], &src[(i - 1) * stride],
  
                         16 * block_width);
  
  
  
              for (x = 0; x < block_width; x++) {
  
                  s->m.mb_x = x;
  
                  ff_init_block_index(&s->m);
  
                  ff_update_block_index(&s->m);
  
  
  
                  ff_estimate_p_frame_motion(&s->m, x, y);
  
              }
  
              s->m.first_slice_line = 0;
  
          }
  
  
  
          ff_fix_long_p_mvs(&s->m);
  
          ff_fix_long_mvs(&s->m, NULL, 0, s->m.p_mv_table, s->m.f_code,
  
                          CANDIDATE_MB_TYPE_INTER, 0);
  
      }
  
  
  
      s->m.first_slice_line = 1;
  
      for (y = 0; y < block_height; y++) {
  
          for (i = 0; i < 16 && i + 16 * y < height; i++) {
  
              memcpy(&src[i * stride], &src_plane[(i + 16 * y) * src_stride],
  
                     width);
  
              for (x = width; x < 16 * block_width; x++)
  
                  src[i * stride + x] = src[i * stride + x - 1];
  
          }
  
          for (; i < 16 && i + 16 * y < 16 * block_height; i++)
  
              memcpy(&src[i * stride], &src[(i - 1) * stride], 16 * block_width);
  
  
  
          s->m.mb_y = y;
  
          for (x = 0; x < block_width; x++) {
  
              uint8_t reorder_buffer[3][6][7 * 32];
  
              int count[3][6];
  
              int offset       = y * 16 * stride + x * 16;
  
              uint8_t *decoded = decoded_plane + offset;
  
              uint8_t *ref     = ref_plane + offset;
  
              int score[4]     = { 0, 0, 0, 0 }, best;
  
              uint8_t *temp    = s->scratchbuf;
  
  
  
              if (s->pb.buf_end - s->pb.buf -
  
                  (put_bits_count(&s->pb) >> 3) < 3000) { // FIXME: check size
  
                  av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
  
                  return -1;
  
              }
  
  
  
              s->m.mb_x = x;
  
              ff_init_block_index(&s->m);
  
              ff_update_block_index(&s->m);
  
  
  
              if (f->pict_type == AV_PICTURE_TYPE_I ||
  
                  (s->m.mb_type[x + y * s->m.mb_stride] &
  
                   CANDIDATE_MB_TYPE_INTRA)) {
  
                  for (i = 0; i < 6; i++)
  
                      init_put_bits(&s->reorder_pb[i], reorder_buffer[0][i],
  
                                    7 * 32);
  
                  if (f->pict_type == AV_PICTURE_TYPE_P) {
  
                      const uint8_t *vlc = ff_svq1_block_type_vlc[SVQ1_BLOCK_INTRA];
  
                      put_bits(&s->reorder_pb[5], vlc[1], vlc[0]);
  
                      score[0] = vlc[1] * lambda;
  
                  }
  
                  score[0] += encode_block(s, src + 16 * x, NULL, temp, stride,
  
                                           5, 64, lambda, 1);
  
                  for (i = 0; i < 6; i++) {
  
                      count[0][i] = put_bits_count(&s->reorder_pb[i]);
  
                      flush_put_bits(&s->reorder_pb[i]);
  
                  }
  
              } else
  
                  score[0] = INT_MAX;
  
  
  
              best = 0;
  
  
  
              if (f->pict_type == AV_PICTURE_TYPE_P) {
  
                  const uint8_t *vlc = ff_svq1_block_type_vlc[SVQ1_BLOCK_INTER];
  
                  int mx, my, pred_x, pred_y, dxy;
  
                  int16_t *motion_ptr;
  
  
  
                  motion_ptr = ff_h263_pred_motion(&s->m, 0, 0, &pred_x, &pred_y);
  
                  if (s->m.mb_type[x + y * s->m.mb_stride] &
  
                      CANDIDATE_MB_TYPE_INTER) {
  
                      for (i = 0; i < 6; i++)
  
                          init_put_bits(&s->reorder_pb[i], reorder_buffer[1][i],
  
                                        7 * 32);
  
  
  
                      put_bits(&s->reorder_pb[5], vlc[1], vlc[0]);
  
  
  
                      s->m.pb = s->reorder_pb[5];
  
                      mx      = motion_ptr[0];
  
                      my      = motion_ptr[1];
  
                      assert(mx     >= -32 && mx     <= 31);
  
                      assert(my     >= -32 && my     <= 31);
  
                      assert(pred_x >= -32 && pred_x <= 31);
  
                      assert(pred_y >= -32 && pred_y <= 31);
  
                      ff_h263_encode_motion(&s->m, mx - pred_x, 1);
  
                      ff_h263_encode_motion(&s->m, my - pred_y, 1);
  
                      s->reorder_pb[5] = s->m.pb;
  
                      score[1]        += lambda * put_bits_count(&s->reorder_pb[5]);
  
  
  
                      dxy = (mx & 1) + 2 * (my & 1);
  
  
  
                      s->hdsp.put_pixels_tab[0][dxy](temp + 16,
  
                                                     ref + (mx >> 1) +
  
                                                     stride * (my >> 1),
  
                                                     stride, 16);
  
  
  
                      score[1] += encode_block(s, src + 16 * x, temp + 16,
  
                                               decoded, stride, 5, 64, lambda, 0);
  
                      best      = score[1] <= score[0];
  
  
  
                      vlc       = ff_svq1_block_type_vlc[SVQ1_BLOCK_SKIP];
  
                      score[2]  = s->dsp.sse[0](NULL, src + 16 * x, ref,
  
                                                stride, 16);
  
                      score[2] += vlc[1] * lambda;
  
                      if (score[2] < score[best] && mx == 0 && my == 0) {
  
                          best = 2;
  
                          s->hdsp.put_pixels_tab[0][0](decoded, ref, stride, 16);
  
                          for (i = 0; i < 6; i++)
  
                              count[2][i] = 0;
  
                          put_bits(&s->pb, vlc[1], vlc[0]);
  
                      }
  
                  }
  
  
  
                  if (best == 1) {
  
                      for (i = 0; i < 6; i++) {
  
                          count[1][i] = put_bits_count(&s->reorder_pb[i]);
  
                          flush_put_bits(&s->reorder_pb[i]);
  
                      }
  
                  } else {
  
                      motion_ptr[0]                      =
  
                      motion_ptr[1]                      =
  
                      motion_ptr[2]                      =
  
                      motion_ptr[3]                      =
  
                      motion_ptr[0 + 2 * s->m.b8_stride] =
  
                      motion_ptr[1 + 2 * s->m.b8_stride] =
  
                      motion_ptr[2 + 2 * s->m.b8_stride] =
  
                      motion_ptr[3 + 2 * s->m.b8_stride] = 0;
  
                  }
  
              }
  
  
  
              s->rd_total += score[best];
  
  
  
              for (i = 5; i >= 0; i--)
  
                  avpriv_copy_bits(&s->pb, reorder_buffer[best][i],
  
                                   count[best][i]);
  
              if (best == 0)
  
                  s->hdsp.put_pixels_tab[0][0](decoded, temp, stride, 16);
  
          }
  
          s->m.first_slice_line = 0;
  
      }
  
      return 0;
  
  }
  