static inline void dv_decode_video_segment(DVVideoContext *s,

                                           const uint8_t *buf_ptr1,

                                           const uint16_t *mb_pos_ptr)

{

    int quant, dc, dct_mode, class1, j;

    int mb_index, mb_x, mb_y, v, last_index;

    int y_stride, i;

    DCTELEM *block, *block1;

    int c_offset;

    uint8_t *y_ptr;

    const uint8_t *buf_ptr;

    PutBitContext pb, vs_pb;

    GetBitContext gb;

    BlockInfo mb_data[5 * DV_MAX_BPM], *mb, *mb1;

    DECLARE_ALIGNED_16(DCTELEM, sblock[5*DV_MAX_BPM][64]);

    DECLARE_ALIGNED_8(uint8_t, mb_bit_buffer[80 + 4]); /* allow some slack */

    DECLARE_ALIGNED_8(uint8_t, vs_bit_buffer[5 * 80 + 4]); /* allow some slack */

    const int log2_blocksize= 3-s->avctx->lowres;

    int is_field_mode[5];



    assert((((int)mb_bit_buffer)&7)==0);

    assert((((int)vs_bit_buffer)&7)==0);



    memset(sblock, 0, sizeof(sblock));



    /* pass 1 : read DC and AC coefficients in blocks */

    buf_ptr = buf_ptr1;

    block1 = &sblock[0][0];

    mb1 = mb_data;

    init_put_bits(&vs_pb, vs_bit_buffer, 5 * 80);

    for(mb_index = 0; mb_index < 5; mb_index++, mb1 += s->sys->bpm, block1 += s->sys->bpm * 64) {

        /* skip header */

        quant = buf_ptr[3] & 0x0f;

        buf_ptr += 4;

        init_put_bits(&pb, mb_bit_buffer, 80);

        mb = mb1;

        block = block1;

        is_field_mode[mb_index] = 0;

        for(j = 0;j < s->sys->bpm; j++) {

            last_index = s->sys->block_sizes[j];

            init_get_bits(&gb, buf_ptr, last_index);



            /* get the dc */

            dc = get_sbits(&gb, 9);

            dct_mode = get_bits1(&gb);

            class1 = get_bits(&gb, 2);

            if (DV_PROFILE_IS_HD(s->sys)) {

                mb->idct_put = s->idct_put[0];

                mb->scan_table = s->dv_zigzag[0];

                mb->factor_table = s->dv100_idct_factor[((s->sys->height == 720)<<1)|(j >= 4)][class1][quant];

                is_field_mode[mb_index] |= !j && dct_mode;

            } else {

                mb->idct_put = s->idct_put[dct_mode && log2_blocksize==3];

                mb->scan_table = s->dv_zigzag[dct_mode];

                mb->factor_table = s->dv_idct_factor[class1 == 3][dct_mode]

                    [quant + dv_quant_offset[class1]];

            }

            dc = dc << 2;

            /* convert to unsigned because 128 is not added in the

               standard IDCT */

            dc += 1024;

            block[0] = dc;

            buf_ptr += last_index >> 3;

            mb->pos = 0;

            mb->partial_bit_count = 0;



#ifdef VLC_DEBUG

            printf("MB block: %d, %d ", mb_index, j);

#endif

            dv_decode_ac(&gb, mb, block);



            /* write the remaining bits  in a new buffer only if the

               block is finished */

            if (mb->pos >= 64)

                bit_copy(&pb, &gb);



            block += 64;

            mb++;

        }



        /* pass 2 : we can do it just after */

#ifdef VLC_DEBUG

        printf("***pass 2 size=%d MB#=%d\n", put_bits_count(&pb), mb_index);

#endif

        block = block1;

        mb = mb1;

        init_get_bits(&gb, mb_bit_buffer, put_bits_count(&pb));

        flush_put_bits(&pb);

        for(j = 0;j < s->sys->bpm; j++, block += 64, mb++) {

            if (mb->pos < 64 && get_bits_left(&gb) > 0) {

                dv_decode_ac(&gb, mb, block);

                /* if still not finished, no need to parse other blocks */

                if (mb->pos < 64)

                    break;

            }

        }

        /* all blocks are finished, so the extra bytes can be used at

           the video segment level */

        if (j >= s->sys->bpm)

            bit_copy(&vs_pb, &gb);

    }



    /* we need a pass other the whole video segment */

#ifdef VLC_DEBUG

    printf("***pass 3 size=%d\n", put_bits_count(&vs_pb));

#endif

    block = &sblock[0][0];

    mb = mb_data;

    init_get_bits(&gb, vs_bit_buffer, put_bits_count(&vs_pb));

    flush_put_bits(&vs_pb);

    for(mb_index = 0; mb_index < 5; mb_index++) {

        for(j = 0;j < s->sys->bpm; j++) {

            if (mb->pos < 64) {

#ifdef VLC_DEBUG

                printf("start %d:%d\n", mb_index, j);

#endif

                dv_decode_ac(&gb, mb, block);

            }

            if (mb->pos >= 64 && mb->pos < 127)

                av_log(NULL, AV_LOG_ERROR, "AC EOB marker is absent pos=%d\n", mb->pos);

            block += 64;

            mb++;

        }

    }



    /* compute idct and place blocks */

    block = &sblock[0][0];

    mb = mb_data;

    for(mb_index = 0; mb_index < 5; mb_index++) {

        v = *mb_pos_ptr++;

        mb_x = v & 0xff;

        mb_y = v >> 8;

        /* We work with 720p frames split in half. The odd half-frame (chan==2,3) is displaced :-( */

        if (s->sys->height == 720 && !(s->buf[1]&0x0C)) {

               mb_y -= (mb_y>17)?18:-72; /* shifting the Y coordinate down by 72/2 macroblocks */

        }



        /* idct_put'ting luminance */

        if ((s->sys->pix_fmt == PIX_FMT_YUV420P) ||

            (s->sys->pix_fmt == PIX_FMT_YUV411P && mb_x >= (704 / 8)) ||

            (s->sys->height >= 720 && mb_y != 134)) {

            y_stride = (s->picture.linesize[0]<<((!is_field_mode[mb_index])*log2_blocksize)) - (2<<log2_blocksize);

        } else {

            y_stride = 0;

        }

        y_ptr = s->picture.data[0] + ((mb_y * s->picture.linesize[0] + mb_x)<<log2_blocksize);

        for(j = 0; j < 2; j++, y_ptr += y_stride) {

            for (i=0; i<2; i++, block += 64, mb++, y_ptr += (1<<log2_blocksize))

                 if (s->sys->pix_fmt == PIX_FMT_YUV422P && s->sys->width == 720 && i)

                     y_ptr -= (1<<log2_blocksize);

                 else

                     mb->idct_put(y_ptr, s->picture.linesize[0]<<is_field_mode[mb_index], block);

        }



        /* idct_put'ting chrominance */

        c_offset = (((mb_y>>(s->sys->pix_fmt == PIX_FMT_YUV420P)) * s->picture.linesize[1] +

                     (mb_x>>((s->sys->pix_fmt == PIX_FMT_YUV411P)?2:1)))<<log2_blocksize);

        for(j=2; j; j--) {

            uint8_t *c_ptr = s->picture.data[j] + c_offset;

            if (s->sys->pix_fmt == PIX_FMT_YUV411P && mb_x >= (704 / 8)) {

                  uint64_t aligned_pixels[64/8];

                  uint8_t *pixels = (uint8_t*)aligned_pixels;

                  uint8_t *c_ptr1, *ptr1;

                  int x, y;

                  mb->idct_put(pixels, 8, block);

                  for(y = 0; y < (1<<log2_blocksize); y++, c_ptr += s->picture.linesize[j], pixels += 8) {

                      ptr1= pixels + (1<<(log2_blocksize-1));

                      c_ptr1 = c_ptr + (s->picture.linesize[j]<<log2_blocksize);

                      for(x=0; x < (1<<(log2_blocksize-1)); x++) {

                          c_ptr[x]= pixels[x];

                          c_ptr1[x]= ptr1[x];

                      }

                  }

                  block += 64; mb++;

            } else {

                  y_stride = (mb_y == 134) ? (1<<log2_blocksize) :

                                             s->picture.linesize[j]<<((!is_field_mode[mb_index])*log2_blocksize);

                  for (i=0; i<(1<<(s->sys->bpm==8)); i++, block += 64, mb++, c_ptr += y_stride)

                       mb->idct_put(c_ptr, s->picture.linesize[j]<<is_field_mode[mb_index], block);

            }

        }

    }

}
