/*****************************************************************************
 *
 * This software module was originally developed by
 *
 *   J. Ignacio Ronda (UPM-GTI / ACTS-MoMuSys)
 *
 * and edited by
 *
 *   Angel Pacheco (UPM-GTI / ACTS-MoMuSys)
 *   Robert Danielsen (Telenor / ACTS-MoMuSys)
 *   Fernando Jaureguizar (UPM-GTI / ACTS-MoMuSys)
 *   Luis Ducla-Soares (IST / ACTS-MoMuSys)
 *   Cor Quist (KPN / ACTS-MoMuSys)
 *   Cecile Dufour (LEP / ACTS-MoMuSys)
 *   Bob Eifrig (NextLevel Systems)
 *
 * in the course of development of the MPEG-4 Video (ISO/IEC 14496-2) standard.
 * This software module is an implementation of a part of one or more MPEG-4
 * Video (ISO/IEC 14496-2) tools as specified by the MPEG-4 Video (ISO/IEC
 * 14496-2) standard.
 *
 * ISO/IEC gives users of the MPEG-4 Video (ISO/IEC 14496-2) standard free
 * license to this software module or modifications thereof for use in hardware
 * or software products claiming conformance to the MPEG-4 Video (ISO/IEC
 * 14496-2) standard.
 *
 * Those intending to use this software module in hardware or software products
 * are advised that its use may infringe existing patents. The original
 * developer of this software module and his/her company, the subsequent
 * editors and their companies, and ISO/IEC have no liability for use of this
 * software module or modifications thereof in an implementation. Copyright is
 * not released for non MPEG-4 Video (ISO/IEC 14496-2) Standard conforming
 * products.
 *
 * ACTS-MoMuSys partners retain full right to use the code for his/her own
 * purpose, assign or donate the code to a third party and to inhibit third
 * parties from using the code for non MPEG-4 Video (ISO/IEC 14496-2) Standard
 * conforming products. This copyright notice must be included in all copies or
 * derivative works.
 *
 * Copyright (c) 1997
 *
 *****************************************************************************/

/***********************************************************HeaderBegin*******
 *
 * File:        mot_code.c
 *
 * Author:      J. Ignacio Ronda / Angel Pacheco, UPM-GTI
 *
 * Created:     02.02.96
 *
 * Description: Includes functions needed for the Motion Vector encoding
 *              process. Two of them are also used in the motion estima-
 *              tion, while finding the predicted motion vector
 *
 * Flags:       -D_DEBUG_MV_   : prints the MB modes and the MB motion vectors.
 *
 * Modified:
 *      21.04.96 Robert Danielsen: Reformatted. New headers.
 *      07.06.96 Robert Danielsen: Removed function GetCode.
 *               VLC coding of vector differences is done with a
 *               simpler scheme now. Uses PutMV instead.
 *      02.07.96 Fernando Jaureguizar: Reformatted.
 *      23.07.96 Fernando Jaureguizar: CodeVopMotion() and
 *               Bits_CountMB_Motion() modified to return the number
 *               of bits spent in the motion coding.
 *      18.09.96 Fernando Jaureguizar: Now new B_TRANSP and MB_TRANSP defines
 *               are in mot_util.h. Their calls are modified.
 *      29.04.97 Luis Ducla-Soares: added 1D vector prediction for
 *               error resilient mode.
 *      14.05.97 Fernando Jaureguizar: new commentaries about new f_code
 *               range according to VM7.0
 *      21.05.97 Angel Pacheco: Delete FindPMV8 and FindPMV16. Mods
 *               to have just one function to compute the MVs prediction
 *               in both encoder/decoder (find_pmvs)
 *      16.06.97 Angel Pacheco: unified the TRANSPARENT modes.
 *      13.11.97 Fernando Jaureguizar: formating and new header.
 *      09.03.98 Fernando Jaureguizar: New formating. Deleted not used 
 *               field parameter in FindPMV_field().
 *
 ***********************************************************HeaderEnd*********/

/************************    INCLUDE FILES    ********************************/

#include "momusys.h"
#include "mom_structs.h"
#include "vm_common_defs.h"
#include "mom_access.h"
#include "mom_image.h"
#include "mom_vop.h"
#include "mom_bitstream_i.h"

#include "mot_util.h"
#include "mot_est.h"

#include "putvlc.h"

/* ------------------------------------------------------------------------- */

/* Specific macros (include references to internal vars. of the functions) */

/* 16x16 MV obtainment */
#define MBV_H(h,v)      (ph[2*(v)*2*hdim+2*(h)])
#define MBV_V(h,v)      (pv[2*(v)*2*hdim+2*(h)])

/* 8x8 MV obtainment */
#define BV_H(h,v,h2,v2) (ph[(2*(v)+(v2))*2*hdim+2*(h)+(h2)])
#define BV_V(h,v,h2,v2) (pv[(2*(v)+(v2))*2*hdim+2*(h)+(h2)])

/* MB mode obtainment */
#define MB_MODE(h,v)    ( ((h)<0||(h)>=hdim||(v)<0||(v)>=vdim \
                           ? MBM_OUT  \
                           : (pm[(v)*hdim+(h)])) )

/* ------------------------------------------------------------------------- */

/***********************************************************CommentBegin******
 *
 * -- ScaleMVD -- Scales MVD component acording to the MV range
 *
 * Author :
 *      UPM-GTI - Fernando Jaureguizar
 *
 * Created :
 *      08.05.96
 *
 * Purpose :
 *      Scales a Motion Vector Difference (MVD) component (x or y) according
 *      to the MV range. The maximum range that can be represented is
 *      determined by the f_code encoded in the VOP header. Two values,
 *      vlc_code_mag and residual, are generated.
 *
 * Arguments in :
 *      Int   f_code          MV range in 1/2 units: 1=32,2=64,...,7=2048
 *      Int   diff_vector     MV Diff. component in 1/2 units
 *
 * Arguments in/out :
 *
 *
 * Arguments out :
 *      Int   *residual        Value to be FLC coded
 *      Int   *vlc_code_mag    Value to be VLC coded
 *
 * Return values :
 *      none
 *
 * Side effects :
 *
 *
 * Description :
 *      1) The range of the MV's is computed according to the f_code.
 *      2) The range of the MVD component is reduced to fall in the
 *         correct range.
 *      3) Two values are generated:
 *         vlc_code_mag: It will be VLC coded in other function.
 *         residual    : It will be FLC coded in other function.
 *
 * See also :
 *
 *
 * Modified :
 *
 *
 ***********************************************************CommentEnd********/

Void              
ScaleMVD (
   Int  f_code,       /* <-- MV range in 1/2 units: 1=32,2=64,...,7=2048     */
   Int  diff_vector,  /* <-- MV Difference commponent in 1/2 units           */
   Int  *residual,    /* --> value to be FLC coded                           */
   Int  *vlc_code_mag /* --> value to be VLC coded                           */
   )
{
  Int   range;
  Int   scale_factor;
  Int   r_size;
  Int   low;
  Int   high;
  Int   aux;

  r_size = f_code-1;
  scale_factor = 1<<r_size;
  range = 32*scale_factor;
  low   = -range;
  high  =  range-1;
  if (diff_vector < low)
    {
    diff_vector += 2*range;
    }
  else if (diff_vector > high)
    {
    diff_vector -= 2*range;
    }

  if (diff_vector < low || diff_vector > high)
    {
    fprintf(stderr,"Error in ScaleMVD(): Invalid MV Difference\n");
    }

  if (diff_vector==0)
    {
    *vlc_code_mag = 0;
    *residual = 0;
    }
  else if (scale_factor==1)
    {
    *vlc_code_mag = diff_vector;
    *residual = 0;
    }
  else
    {
    aux = ABS(diff_vector) + scale_factor - 1;
    *vlc_code_mag = aux>>r_size;

    if (diff_vector<0)
      *vlc_code_mag = -*vlc_code_mag;

    *residual = aux & (scale_factor-1);
    }
}

/***********************************************************CommentBegin******
 *
 * -- Bits_CountMB_Motion --
 *
 * Author :
 *      KPN Research - Cor Quist
 *
 * Created :
 *
 *
 * Purpose :
 *      Encodes the MV's Images acording to modes and alpha Images
 *      (see notes below). The codewords are appended to the bitstream.
 *      Included in text_code.h .
 *
 * Arguments in :
 *      Image   *mot_h    motion vectors (Float) - per block
 *      Image   *mot_v    motion vectors (Float) - per block
 *      Image   *alpha    macroblocks modes (SInt) - per block
 *      Image   *modes    macroblocks modes (SInt) - per MB
 *      Int     h         coordinate of the MB
 *      Int     v         coordinate of the MB
 *      Int     f_code    MV range in 1/2 units 1=32,2=64,...,7=2048
 *      Int     error_res_disable
 *      Int     after_marker
 *      Int     **slice_nb
 *
 * Arguments in/out :
 *      Image   *bs       output (SInt)
 *
 * Arguments out :
 *
 *
 * Return values :
 *      Int     mv_bits   Returns the number of bits sent to the bitstream
 *
 * Side effects :
 *
 *
 * Description :
 *      1) No checking is made for the consistence of image sizes
 *      2) It assumes the output image has been previously allocated.
 *      3) Transparent MB's are not coded (no codeword is transmited).
 *      4) Motion vectors for 8x8 transparent blocks within
 *         non-totally-transparent MB's are transmitted as MV (0,0) (not MVD
 *         (0,0)). This is made in the  hope that this MV's are neither
 *         employed for block reconstruction nor for MV prediction.
 *
 * See also :
 *
 *
 * Modified :
 *      09.05.96 Fernando Jaureguizar: according to VM 2.1
 *      07.06.96 Robert Danielsen: Changed from using GetCode to PutMV.
 *      23.07.96 Fernando Jaureguizar: now returns Int instead of Void.
 *      28.08.96 Fernando Jaureguizar: transparent 8x8 blocks according
 *               to VM 3.1.
 *      10.09.96 Fernando Jaureguizar: transparent MB's are not coded
 *               according to VM 3.1.
 *      29.04.97 Luis Ducla-Soares: added parameters "error_res_disable"
 *               and "after_marker" to function. This enables the use of
 *               1D motion vector prediction and to set the prediction to
 *               zero after resync markers.
 *      07.11.97 Luis Ducla-Soares: added new argument "slice_nb" and made
 *               changes related to error resilience.
 *      11.12.97 Bob Eifrig: added code to write field motion vectors
 *
 ***********************************************************CommentEnd********/

Int
Bits_CountMB_Motion(
   Image   *mot_h, /* <-- motion vectors (Float) - per block    */
   Image   *mot_v, /* <-- motion vectors (Float) - per block    */
   Image   *alpha, /* <-- macroblocks modes (SInt) - per block  */
   Image   *modes, /* <-- macroblocks modes (SInt) - per MB     */
   Int     h,      /* <-- horizontal coordinate of the MB       */
   Int     v,      /* <-- vertical coordinate of the MB         */
   Int     f_code, /* <-- MV range in 1/2 units 1=32,2=64,...,7=2048 */
   Image   *bs,    /* --> output (SInt)                         */
   Int     error_res_disable,
   Int     after_marker,
   Int     **slice_nb,
   Int arbitrary_shape
   )
{
  Int     vdim, hdim;  /* Dimensions in macroblocks */
  Float   *ph, *pv;    /* Motion vectors            */
  SInt    *pm;         /* Modes                     */
  SInt    *pa;         /* Alpha                     */
  Int     mode;
  Int     bits_mot = 0;

  /* From switch statement */
  Int     i,pos,error_flag=0,mvx=0,mvy=0;
  Float   pred_h, pred_v;
  Float   diff_h, diff_v;
  Int     bh, bv;

  vdim=(Int)GetImageSizeY(modes);
  hdim=(Int)GetImageSizeX(modes);
  ph=(Float*)GetImageData(mot_h);
  pv=(Float*)GetImageData(mot_v);
  pm=(SInt*)GetImageData(modes);
  pa=(SInt*)GetImageData(alpha);

  switch (mode=MB_MODE(h,v))
    {
    case MBM_INTRA:
#ifdef _DEBUG_MV_
      fprintf(stdout," **[%2d,%2d] = MB_INTRA   \n",h,v);
#endif
      break;
    case MBM_INTER16:
      /* Prediction obtainment */
      if (error_res_disable)         /* LDS: 07.11.97 - added this test */
        {
        pos=2*hdim*2*v+2*h;
        pa[pos]=(pa[pos]!=MBM_TRANSPARENT)?MBM_INTER16:MBM_TRANSPARENT;
        pos++;
        pa[pos]=(pa[pos]!=MBM_TRANSPARENT)?MBM_INTER16:MBM_TRANSPARENT;
        pos=pos+2*hdim;
        pa[pos]=(pa[pos]!=MBM_TRANSPARENT)?MBM_INTER16:MBM_TRANSPARENT;
        pos--;   
        pa[pos]=(pa[pos]!=MBM_TRANSPARENT)?MBM_INTER16:MBM_TRANSPARENT;

        /* MVP/Noel */
        find_pmvs(mot_h,mot_v,modes,alpha/*??*/,h,v,0,MBM_TRANSPARENT,
                  &error_flag,&mvx,&mvy);
        }
      else
        {
        pos=2*hdim*2*v+2*h;
        pa[pos]=(pa[pos]!=MBM_TRANSPARENT)?MBM_INTER16:MBM_TRANSPARENT;
        pos++;
        pa[pos]=(pa[pos]!=MBM_TRANSPARENT)?MBM_INTER16:MBM_TRANSPARENT;
        pos=pos+2*hdim;
        pa[pos]=(pa[pos]!=MBM_TRANSPARENT)?MBM_INTER16:MBM_TRANSPARENT;
        pos--;   
        pa[pos]=(pa[pos]!=MBM_TRANSPARENT)?MBM_INTER16:MBM_TRANSPARENT;

        find_pmvsErrRes(mot_h,mot_v,modes,alpha/*??*/,h,v,0,MBM_TRANSPARENT,
                        &error_flag,&mvx,&mvy,slice_nb,arbitrary_shape);
        }
      pred_h=((Float)mvx)/2;
      pred_v=((Float)mvy)/2;
      
      diff_h=MBV_H(h,v)- pred_h;
      diff_v=MBV_V(h,v)- pred_v;

      /* Encoding */
      bits_mot += WriteMVcomponent(f_code, (Int)(2*(MBV_H(h,v) - pred_h)), bs);
      bits_mot += WriteMVcomponent(f_code, (Int)(2*(MBV_V(h,v) - pred_v)), bs);
#ifdef _DEBUG_MV_
      fprintf(stdout," **[%2d,%2d] = MB_INTERx1V[0](%5.1f,%5.1f)\n",
              h, v, MBV_H(h,v), MBV_V(h,v));
#endif
      break;
    case MBM_INTER8:
      i=1;
      for (bv=0; bv<=1; bv++)
        for (bh=0; bh<=1; bh++)
          {
          if (error_res_disable)  /* LDS: 07.11.97 - added this test */
            {
            if(!B_TRANSP(pa, 2*hdim, h, v, bh, bv, MBM_TRANSPARENT)) 
              BV(pa, 2*hdim, h, v, bh, bv) = MBM_INTER8; 

            /* MVP/Noel */
            find_pmvs(mot_h,mot_v,modes,alpha/*??*/,h,v,i,MBM_TRANSPARENT, 
                      &error_flag,&mvx,&mvy); 
            }
          else
            {
            if(!B_TRANSP(pa, 2*hdim, h, v, bh, bv, MBM_TRANSPARENT)) 
              BV(pa, 2*hdim, h, v, bh, bv) = MBM_INTER8; 

            find_pmvsErrRes(mot_h,mot_v,modes,alpha/*??*/,h,v,i,
                            MBM_TRANSPARENT, &error_flag,&mvx,&mvy,
                            slice_nb,arbitrary_shape); 
            }
          pred_h=((Float)mvx)/2;
          pred_v=((Float)mvy)/2;

          i++;

          if (!B_TRANSP(pa, 2*hdim, h, v, bh, bv, MBM_TRANSPARENT))
            {
            diff_h=BV_H(h,v,bh,bv)-pred_h;
            diff_v=BV_V(h,v,bh,bv)-pred_v;

            /* Encoding */
            bits_mot += WriteMVcomponent(f_code, (Int)(2*diff_h), bs);
            bits_mot += WriteMVcomponent(f_code, (Int)(2*diff_v), bs);
            }
          /* else no info is transmited for 8x8 transparent blocks*/
#ifdef _DEBUG_MV_
          {
          Int aux =0;
          if (bv == 1) aux += 2;
          if (bh == 1) aux += 1;
                   
          if (!B_TRANSP(pa, 2*hdim, h, v, bh, bv, MBM_TRANSPARENT))
            {
            if (aux == 0)
              fprintf(stdout," **[%2d,%2d] = MB_INTERx4V[%d](%5.1f,%5.1f)\n",
                      h, v, aux, BV_H(h,v,bh,bv), BV_V(h,v,bh,bv));
            else
              fprintf(stdout,"%s**[%2d,%2d] = MB_INTERx4V[%d](%5.1f,%5.1f)\n",
                       "                         ", h, v, aux,
            BV_H(h,v,bh,bv), BV_V(h,v,bh,bv));
            }
          else
            {
            if (aux == 0)
              fprintf(stdout," **[%2d,%2d] = B_TRANSP   [%d]\n", h, v, aux);
            else
              fprintf(stdout,"%s**[%2d,%2d] = B_TRANSP   [%d]\n",
                      "                         ", h, v, aux);
            }
          }
#endif
          }
      break;

    case MBM_FIELD00:
    case MBM_FIELD01:
    case MBM_FIELD10:
    case MBM_FIELD11:
      /* Prediction obtainment (top field) */
      if (after_marker)
        pred_h = pred_v = 0.0;
      else
        FindPMV_field(ph, pv, pm, pa, hdim, vdim, h, v, &pred_h, &pred_v);
 
      /* Encoding (top field) */
      bits_mot += WriteMVcomponent(f_code,(Int)(2*(BV_H(h,v,0,0) - pred_h)),bs);
      bits_mot += WriteMVcomponent(f_code,(Int)BV_V(h,v,0,0) - (Int)pred_v,bs);
 
      /* Prediction obtainment (bottom field) */
      if (after_marker)
        pred_h = pred_v = 0.0;
      else
        FindPMV_field(ph, pv, pm, pa, hdim, vdim, h, v, &pred_h, &pred_v);
 
      /* Encoding (bottom field) */
      bits_mot += WriteMVcomponent(f_code,(Int)(2*(BV_H(h,v,1,0) - pred_h)),bs);
      bits_mot += WriteMVcomponent(f_code,(Int)BV_V(h,v,1,0) - (Int)pred_v,bs);
 
#ifdef _DEBUG_MV_
      fprintf(stdout,"%2d,%2d: MV-top=(%5.1f,%3d.0)-(%5.1f,%3d.0) "
              "MV-bot=(%5.1f,%3d.0)-(%5.1f,%3d.0) ",
              h, v, BV_H(h,v,0,0), (Int)BV_V(h,v,0,0),pred_h,(Int)pred_v,
              BV_H(h,v,1,0),(Int)BV_V(h,v,1,0),diff_h,(Int)diff_v);
#endif
      break;

    case MBM_TRANSPARENT:
#ifdef _DEBUG_MV_
      fprintf(stdout," **[%2d,%2d] = MB_TRANSP  \n",h,v);
#endif
      break;
    case MBM_SPRITE: 
#ifdef _DEBUG_MV_
      fprintf(stdout," **[%2d,%2d] = MB_SPRITE  \n");
#endif
      break;
    default:
      fprintf(stderr, "Bits_CountMB_Motion: Mode not supported: %d\n", mode);
      fprintf(stderr, "vdim, hdim, v, h :%d,%d,%d,%d\n", (int)vdim, (int)hdim,
              (int)v, (int)h);
      exit(1);
    }
  return bits_mot;
}

/***********************************************************CommentBegin******
 *
 * -- FindPMV_field -- Finds the predicted MV for the 16x8 field block
 *
 * Author :
 *      Bob Eifrig
 *
 * Created :
 *      24.01.97
 *
 * Purpose :
 *      Finds the predicted MV for the 16x8 field block
 *
 * Arguments in :
 *      Float   *ph,       horizontal predicted MVs
 *      Float   *pv,       vertical predicted MVs
 *      SInt    *pm,       macroblocks modes
 *      SInt    *pa,       subsampled (8x8) alpha plane
 *      Int     hdim,      horizontal dimensions (macroblocks)
 *      Int     vdim,      vertical dimensions (macroblocks)
 *      Int     h,         horizontal macroblock coordinate in macroblocks
 *      Int     v,         vertical macroblock coordinate in macroblocks
 *
 * Arguments in/out :
 *
 *
 * Arguments out :
 *      Float   *pred_h,   horizontal MV predicted
 *      Float   *pred_v    vertical MV predicted
 *
 * Return values :
 *      none
 *
 * Side effects :
 *
 *
 * Description :
 *
 *
 * See also :
 *
 *
 * Modified :
 *      xx.xx.xx X. Chen: Deleted field input parameter. Modifications to
 *               follow CE P-14.
 *
 ***********************************************************CommentEnd********/
 
Void
FindPMV_field(
   Float   *ph,     /* <-- horizontal predicted MVs                        */
   Float   *pv,     /* <-- vertical predicted MVs                          */
   SInt    *pm,     /* <-- macroblocks modes                               */
   SInt    *pa,     /* <-- subsampled (8x8) alpha plane                    */
   Int     hdim,    /* <-- horizontal dimensions (macroblocks)             */
   Int     vdim,    /* <-- vertical dimensions (macroblocks)               */
   Int     h,       /* <-- horizontal macroblock coordinate in macroblocks */
   Int     v,       /* <-- vertical macroblock coordinate in macroblocks   */
   Float   *pred_h, /* --> horizontal predicted MV                         */
   Float   *pred_v  /* --> vertical predicted MV                           */
   )
{
  Int     m[4];            /* Modes of the macroblocks used for prediction */
  Float   mv_v[4];         /* MV used for prediction: vertical             */
  Float   mv_h[4];         /* MV used for prediction: horizontal           */
  Int     t, i;
  Float   avail_mv_h=(Float)0.0,
          avail_mv_v=(Float)0.0;
  Int     in_count=0;      /* Number of available predictions              */
  Int     mv_coord_MB_v[4],
          mv_coord_MB_h[4];/* Coordinates of MV's for pred.                */
  Int     mv_coord_B_v[4],
          mv_coord_B_h[4];
 
  if (h<0 || h>=hdim || v<0 || v>=vdim)
    {
    fprintf(stderr, "FindPMV_Field: out of bounds\n");
    exit(1);
    }
 
  mv_coord_MB_v[1] = v;
  mv_coord_MB_h[1] = h-1;
  mv_coord_MB_v[2] = v-1;
  mv_coord_MB_h[2] = h;
  mv_coord_MB_v[3] = v-1;
  mv_coord_MB_h[3] = h+1;
 
  mv_coord_B_v[1]  = 0;
  mv_coord_B_h[1]  = 1;
  mv_coord_B_v[2]  = 1;
  mv_coord_B_h[2]  = 0;
  mv_coord_B_v[3]  = 1;
  mv_coord_B_h[3]  = 0;
 
  for (i=1; i<=3; i++)
    {
    m[i]=MB_MODE(mv_coord_MB_h[i],mv_coord_MB_v[i]);
    if (m[i] != MBM_OUT &&
        !MB_TRANSP(pa,2*hdim,mv_coord_MB_h[i],mv_coord_MB_v[i],MBM_TRANSPARENT))
      {
      switch (m[i])
        {
        case MBM_INTER16:
        case MBM_INTER8:
          mv_v[i]=BV_V(mv_coord_MB_h[i],mv_coord_MB_v[i],
                       mv_coord_B_h[i], mv_coord_B_v[i]);
          mv_h[i]=BV_H(mv_coord_MB_h[i],mv_coord_MB_v[i],
                       mv_coord_B_h[i], mv_coord_B_v[i]);
          break;
        case MBM_FIELD00:
        case MBM_FIELD01:
        case MBM_FIELD10:
        case MBM_FIELD11:
          t = (Int)(2*BV_V(mv_coord_MB_h[i],mv_coord_MB_v[i],0,0) +
                2*BV_V(mv_coord_MB_h[i],mv_coord_MB_v[i],1,0));
          mv_v[i] = (Float)(0.5 * ((t & 3) ? ((t >> 1) | 1) : (t >> 1)));
          t = (Int)(2*BV_H(mv_coord_MB_h[i],mv_coord_MB_v[i],0,0) +
                2*BV_H(mv_coord_MB_h[i],mv_coord_MB_v[i],1,0));
          mv_h[i] = (Float)(0.5 * ((t & 3) ? ((t >> 1) | 1) : (t >> 1)));
          /*  change by X. Chen to follow CE P-14  */
      /*  mv_v[i] = BV_V(mv_coord_MB_h[i],mv_coord_MB_v[i],field,0);
          mv_h[i] = BV_H(mv_coord_MB_h[i],mv_coord_MB_v[i],field,0); */
          break;
        default:
          mv_v[i]=(Float)0.0;
          mv_h[i]=(Float)0.0;
          break;
        }
      avail_mv_h = mv_h[i];
      avail_mv_v = mv_v[i];
      in_count++;
      }
    else
      mv_v[i]=mv_h[i]=(Float)0.0;
    }
 
  /* Only one prediction available */
  if (in_count==1)
    {
    mv_v[1] = mv_v[2] = mv_v[3] = avail_mv_v;
    mv_h[1] = mv_h[2] = mv_h[3] = avail_mv_h;
    }
 
  *pred_v=MEDIAN(mv_v[1],mv_v[2],mv_v[3]);
  *pred_h=MEDIAN(mv_h[1],mv_h[2],mv_h[3]);
}

/***********************************************************CommentBegin******
 *
 * -- WriteMVcomponent -- Encodes a single motion vector component
 *
 * Author :
 *      Bob Eifrig
 *
 * Created :
 *      24.01.97
 *
 * Purpose :
 *      Scales the motion vector difference, VLC the most significant part,
 *      then outputs the residual (least significant part) as a FLC.
 *
 * Arguments in :
 *      Int   f_code,         Range for MV, (1/2/3) => (32/64/128) 1/2 units
 *      Float diff_vector,    MV Diff. component (in 1/2 units (in field))
 *      Image bs              Bitstream output
 *
 * Arguments in/out :
 *
 *
 * Arguments out :
 *
 *
 * Return values :
 *      The number of bits for this encoding
 *
 * Side effects :
 *      The encoded motion vector is added to the bitstream
 *
 * Description :
 *
 *
 * Modified :
 *
 *
 ***********************************************************CommentEnd********/
 
Int
WriteMVcomponent(
   Int     f_code,
   Int     dmv,
   Image   *bs
   )
{
  Int   residual, vlc_code_mag, bits, entry;
 
  ScaleMVD(f_code, dmv, &residual, &vlc_code_mag);
 
  if (vlc_code_mag < 0)
    entry = vlc_code_mag + 65;
  else
    entry = vlc_code_mag;

  bits = PutMV (entry, bs);

  if ((f_code != 1) && (vlc_code_mag != 0))
    {
    BitstreamPutBits(bs, residual, f_code-1);
    bits += f_code - 1;
    }
  return(bits);
}
