C_RESULT p264_write_picture_layer( video_controller_t* controller, video_stream_t* stream )
{
  uint32_t format = 0, resolution = 0, width, height;

  p264_codec_t* p264_codec = (p264_codec_t*) controller->video_codec;
  p264_picture_layer_t* picture_layer = &p264_codec->picture_layer;

  width   = controller->width;
  height  = controller->height;

  while( format == 0 )
  {
    if( width == QQCIF_WIDTH )
      format = UVLC_FORMAT_CIF;

    if( width == QQVGA_WIDTH )
      format = UVLC_FORMAT_VGA;

    width   >>= 1;
    height  >>= 1;

    resolution ++;
  }

  picture_layer->format     = format;
  picture_layer->resolution = resolution;

  video_write_data( stream, picture_layer->format, 2 );
  video_write_data( stream, picture_layer->resolution, 3 );
  video_write_data( stream, picture_layer->picture_type, 3 );
  video_write_data( stream, picture_layer->quant, 6 );
  video_write_data( stream, controller->num_frames, 32 );

  return C_OK;
}
// write 16 intra_4x4 mode. Data should contains prediction on intra_4x4 (see p264 standard)
// example : data = [ pred (1bits) | code (3bits) ]
// if pred == 0 the prediction made over up and left block is correct. Thus no intra code has to bee transmitted
// if pred != 1, the prediction is wrong. The intra 4x4 mode should be transmitted using only 3 bits (see p264 standard)
void p264_write_intra_4x4 (video_stream_t* const stream, intra_4x4_mode_t* data)
{
    uint32_t i=16;
    while(i--)
    {
        if (((*data)&0x08) == 0)
        {
            // the prediction is good, signal it
            video_write_data (stream,0,1);
        }
        else
        {
            // the prediction is false, transmit the intra 4x4 mode
            video_write_data (stream,*data,4);
        }
        data++;
    }
}
void p264_write_block( video_stream_t* const stream, int16_t* data, uint32_t length)
{
    int32_t code, run, num_coeff;

    // count number of DC coeff
    num_coeff = 0;
    int16_t * p_data = data;

    while (length--)
    {
        if (*p_data++ != 0)
            num_coeff++;
    }

    if (num_coeff == 0)
    {
        video_write_data( stream, 1, 1 ); // signal that there's no coeff
    }
    else
    {
        video_write_data( stream, 0, 1 ); // signal that there are coeffs

        run = 0;
        while( num_coeff > 0 )
        {
            code = *data++;
            if( code == 0 )
            {
                run ++;
            }
            else
            {
                num_coeff--;
                p264_encode( stream, code, run, num_coeff );
                run = 0;
            }
        }
    }
}
예제 #4
0
C_RESULT video_encode_picture( video_controller_t* controller, const vp_api_picture_t* picture, bool_t* got_image )
{
  vp_api_picture_t blockline = { 0 };

  controller->mode  = VIDEO_ENCODE;

  video_controller_set_format( controller, picture->width, picture->height );

  blockline                   = *picture;
  blockline.height            = MB_HEIGHT_Y;
  blockline.complete          = 1;
  blockline.vision_complete   = 0;

  // Reset internal stream for new blockline/picture
  controller->in_stream.used  = 0;
  controller->in_stream.index = 0;

  while( !controller->picture_complete )
  {
    video_encode_blockline( controller, &blockline, blockline.blockline == (controller->num_blockline-1) );

    blockline.y_buf  += MB_HEIGHT_Y * picture->y_line_size;
    blockline.cb_buf += MB_HEIGHT_C * picture->cb_line_size;
    blockline.cr_buf += MB_HEIGHT_C * picture->cr_line_size;

    blockline.blockline++;
  }

  if( picture->complete )
  {
    video_write_data( &controller->in_stream, 0, controller->in_stream.length+1 );
    controller->in_stream.length = 32;
    controller->picture_complete = 0;
    *got_image = TRUE;
  }

  return C_OK;
}
예제 #5
0
void uvlc_encode( video_stream_t* const stream, int32_t level, int32_t run, int32_t not_last )
{
  int32_t sign, length, data, value_code, value_length;

  /// Encode number of zeros
  data = run;

  length      = 0;
  value_code  = 1;

  if( data > 0 )
  {
    length = 32 - clz(data);      // compute number of bits used in run ( = length of run )
    data  -= 1 << ( length - 1 ); // compute value of run
  }

  value_length  = length + 1;

  length -= 1;
  if( length > 0 )
  {
    PACK_BITS( value_code, value_length, data, length );
  }

  /// Encode level
  data = level;

  // sign handling
  sign = 0;
  if( data < 0 )
  {
    data = -data;
    sign = 1;
  }

  // TODO Check saturation & if level == -128
  length = 32 - clz(data);  // number of bits used in level ( = length of level )
  if( length > 1 )
  {
    data   -= 1 << (length - 1);
    length += 1;
  }

  PACK_BITS( value_code, value_length, 1, length );

  VP_OS_ASSERT( length != 2 );

  length -= 2;
  if(length > 0)
  {
    PACK_BITS( value_code, value_length, data, length );
  }

  PACK_BITS( value_code, value_length, sign, 1 );

  /// Encode last
  // add sequence for end of block if required
  if( not_last == 0 )
  {
    PACK_BITS( value_code, value_length, 0x5, 3 );
  }

  /// Write output
  video_write_data( stream, value_code, value_length );
}
C_RESULT p264_write_gob_layer( video_stream_t* stream, p264_gob_layer_t* gob )
{
  video_write_data( stream, gob->quant, 6 );

  return C_OK;
}
예제 #7
0
C_RESULT vlib_stage_encoding_transform(vlib_stage_encoding_config_t *cfg, vp_api_io_data_t *in, vp_api_io_data_t *out)
{
  static int32_t local_subsampl = 0;

  vp_os_mutex_lock(&out->lock);

  if( out->status == VP_API_STATUS_INIT )
  {
    out->numBuffers   = 1;
    out->buffers      = (int8_t**)(int8_t*)&cfg->controller.in_stream.bytes;
    out->indexBuffer  = 0;

    out->status = VP_API_STATUS_PROCESSING;

    cfg->current_size = 0;
  }

  if( local_subsampl == 0 && out->status == VP_API_STATUS_PROCESSING )
  {
    RTMON_USTART(VIDEO_VLIB_ENCODE_EVENT);
    if(cfg->block_mode_enable)
      video_encode_blockline( &cfg->controller, cfg->picture, cfg->picture->complete );
    else
      video_encode_picture( &cfg->controller, cfg->picture, (bool_t*)&cfg->picture->complete );
    RTMON_USTOP(VIDEO_VLIB_ENCODE_EVENT);

    if(cfg->picture->complete)
    {
      RTMON_UVAL(ENCODED_PICTURE_UVAL, cfg->controller.num_frames);
      local_subsampl++;
    }

    cfg->current_size = cfg->controller.in_stream.used;

    if( cfg->controller.in_stream.length != 32 )
    {
      // flush & reset internal stream
      video_write_data( &cfg->controller.in_stream, 0, cfg->controller.in_stream.length+1 );
      cfg->controller.in_stream.length = 32;
    }
    out->size = cfg->controller.in_stream.used;

    RTMON_UVAL(ENCODED_BLOCKLINE_SIZE_UVAL, out->size);

    cfg->controller.in_stream.used  = 0;
    cfg->controller.in_stream.index = 0;
  }
  else
  {
    out->size = 0;

    if( cfg->picture->complete )
    {
      local_subsampl++;
    }
  }

  if(local_subsampl >= (int32_t)cfg->subsampl)
    local_subsampl = 0;

  vp_os_mutex_unlock( &out->lock );

  return C_OK;
}
C_RESULT p264_write_mb_layer(video_controller_t* controller, video_stream_t* stream, video_macroblock_t* mb, int32_t num_macro_blocks )
{
    int16_t* data;
    //uint32_t code;
    uint32_t i;


    while( num_macro_blocks > 0 )
    {
        //PRINT ("p264_write_mb_layer : stream size %d  stream used %d\n",stream->size,stream->used);

        if (controller->picture_type == VIDEO_PICTURE_INTER)
        {
            // write all partition
            for (i=0; i<mb->nb_partition; i++)
            {
                video_write_data( stream,mb->inter_partition_mode[i],3);
            }

            // write all motion vector
            for (i=0; i<mb->nb_partition; i++)
            {
                int32_t s_code;
                s_code = (int32_t)mb->inter_MV[i].x;
                p264_encode_int(stream, s_code);
                s_code = (int32_t)mb->inter_MV[i].y;
                p264_encode_int(stream, s_code);
            }

            // write residual data as an intra4x4
            // write all 4x4 block luma AC coeff
            i=16;
            data = ((MB_p264_t*)mb->data)->inter.AC_Y;
            while(i--)
            {
                p264_write_block( stream, data, 16);
                data += BLOCK_SIZE2;
            }

            // write 4 DC U coeff
            p264_write_block(stream,((MB_p264_t*)mb->data)->inter.DC_U,4);

            // write AC U coeff
            i=4;
            data = &((MB_p264_t*)mb->data)->inter.AC_U[1];
            while(i--)
            {
                p264_write_block( stream, data, 15);
                data += BLOCK_SIZE2;
            }

            // write 4 DC V coeff
            p264_write_block(stream,((MB_p264_t*)mb->data)->inter.DC_V,4);

            // write AC V coeff
            i=4;
            data = &((MB_p264_t*)mb->data)->inter.AC_V[1];
            while(i--)
            {
                p264_write_block( stream, data, 15);
                data += BLOCK_SIZE2;
            }
        }
        else
        {
            // write MB intra type (16x16 or 4x4)
            video_write_data( stream, mb->intra_type, 1 );
            // write intra chroma type
            video_write_data (stream, mb->intra_chroma_8x8_mode,2);
            if (mb->intra_type == INTRA_4x4)
            {
                // write all luma 4x4 prediction modes
                p264_write_intra_4x4(stream,mb->intra_4x4_mode);

                // write all 4x4 block luma AC coeff
                i=16;
                data = ((MB_p264_t*)mb->data)->intra_4x4.AC_Y;
                while(i--)
                {
                    p264_write_block( stream, data, 16);
                    data += BLOCK_SIZE2;
                }

                // write 4 DC U coeff
                p264_write_block(stream,((MB_p264_t*)mb->data)->intra_4x4.DC_U,4);

                // write AC U coeff
                i=4;
                data = &((MB_p264_t*)mb->data)->intra_4x4.AC_U[1];
                while(i--)
                {
                    p264_write_block( stream, data, 15);
                    data += BLOCK_SIZE2;
                }

                // write 4 DC V coeff
                p264_write_block(stream,((MB_p264_t*)mb->data)->intra_4x4.DC_V,4);

                // write AC V coeff
                i=4;
                data = &((MB_p264_t*)mb->data)->intra_4x4.AC_V[1];
                while(i--)
                {
                    p264_write_block( stream, data, 15);
                    data += BLOCK_SIZE2;
                }
            }
            else
            {
                // write luma 16x16 prediction mode
                video_write_data(stream, mb->intra_luma_16x16_mode,2);

                // write 16 DC luma
                p264_write_block( stream, ((MB_p264_t*)mb->data)->intra_16x16.DC_Y, 16);

                // write 16 luma AC coeff block
                i=16;
                data = &((MB_p264_t*)mb->data)->intra_16x16.AC_Y[1];
                while(i--)
                {
                    p264_write_block( stream, data, 15);
                    data += BLOCK_SIZE2;
                }

                // write 4 DC U coeff
                p264_write_block(stream,((MB_p264_t*)mb->data)->intra_16x16.DC_U,4);

                // write AC U coeff
                i=4;
                data = &((MB_p264_t*)mb->data)->intra_16x16.AC_U[1];
                while(i--)
                {
                    p264_write_block( stream, data, 15);
                    data += BLOCK_SIZE2;
                }

                // write 4 DC V coeff
                p264_write_block(stream,((MB_p264_t*)mb->data)->intra_16x16.DC_V,4);

                // write AC V coeff
                i=4;
                data = &((MB_p264_t*)mb->data)->intra_16x16.AC_V[1];
                while(i--)
                {
                    p264_write_block( stream, data, 15);
                    data += BLOCK_SIZE2;
                }
            }
        }
        mb ++;
        num_macro_blocks --;
    }
    return C_OK;
}