blob: c2c0565d911c35f64b7622c9610e623e96089daf [file] [log] [blame]
/* INTEL CONFIDENTIAL
* Copyright (c) 2012 Intel Corporation. All rights reserved.
* Copyright (c) Imagination Technologies Limited, UK
*
* The source code contained or described herein and all documents
* related to the source code ("Material") are owned by Intel
* Corporation or its suppliers or licensors. Title to the
* Material remains with Intel Corporation or its suppliers and
* licensors. The Material contains trade secrets and proprietary
* and confidential information of Intel or its suppliers and
* licensors. The Material is protected by worldwide copyright and
* trade secret laws and treaty provisions. No part of the Material
* may be used, copied, reproduced, modified, published, uploaded,
* posted, transmitted, distributed, or disclosed in any way without
* Intel's prior express written permission.
*
* No license under any patent, copyright, trade secret or other
* intellectual property right is granted to or conferred upon you
* by disclosure or delivery of the Materials, either expressly, by
* implication, inducement, estoppel or otherwise. Any license
* under such intellectual property rights must be express and
* approved by Intel in writing.
*
*/
#include "vp8_tables.h"
#include "vp8parse.h"
#include <vbp_trace.h>
static const uint8_t kVp8SyncCodeByte[] = {0x9d, 0x01, 0x2a};
void vp8_init_Info(vp8_Info *pi)
{
memset(pi, 0, sizeof(vp8_Info));
/* Initialise the parser */
pi->decoded_frame_number = 0;
pi->refresh_entropy_lf = 1;
}
int32_t vp8_parse_frame_tag(FrameTagHeader *frame_tag, uint8_t *data, uint32_t data_sz)
{
if (data_sz < 3)
{
return VP8_CORRUPT_FRAME;
}
/* 1-bit frame type */
frame_tag->frame_type = (FRAME_TYPE)(data[0] & 1);
/* 3-bit version number */
frame_tag->version = (data[0] >> 1) & 7;
if (frame_tag->version > 3)
{
return VP8_UNSUPPORTED_VERSION ;
}
/* 1-bit show frame flag */
frame_tag->show_frame = (data[0] >> 4) & 1;
/* 19-bit field containing the sie of the first data partition in bytes */
frame_tag->first_part_size = (data[0] | (data[1] << 8) | (data[2] << 16)) >> 5;
return VP8_NO_ERROR;
}
void vp8_init_frame(vp8_Info *pi)
{
pi->golden_copied = BufferCopied_NoneToGolden;
pi->altref_copied = BufferCopied_NoneToAltref;
if (pi->frame_tag.frame_type == KEY_FRAME)
{
/* Various keyframe initializations */
/* vp8_prob data initialization */
memcpy(pi->FrameContext.B_Mode_Prob, VP8_BMode_Const, sizeof(VP8_BMode_Const));
memcpy(pi->FrameContext.Y_Mode_Prob, VP8_YMode_Const, sizeof(VP8_YMode_Const));
memcpy(pi->FrameContext.UV_Mode_Prob, VP8_UVMode_Const, sizeof(VP8_UVMode_Const));
memcpy(pi->FrameContext.MVContext, VP8_MV_DefaultMVContext, sizeof(VP8_MV_DefaultMVContext));
memcpy(pi->FrameContext.DCT_Coefficients, VP8_Coefficient_Default_Probabilites, sizeof(VP8_Coefficient_Default_Probabilites));
/* reset the segment feature data to 0 with delta coding (Default state)*/
memset(pi->Segmentation.FeatureData, 0, sizeof(pi->Segmentation.FeatureData));
pi->Segmentation.AbsDelta = SEGMENT_DELTADATA;
/* reset the mode ref deltasa for loop filter */
memset(pi->LoopFilter.DeltasRef, 0, sizeof(pi->LoopFilter.DeltasRef));
memset(pi->LoopFilter.DeltasMode, 0, sizeof(pi->LoopFilter.DeltasMode));
/* All buffers are implicitly updated on key frames */
pi->refresh_gf = 1;
pi->refresh_af = 1;
pi->sign_bias_golden = 0;
pi->sign_bias_alternate = 0;
}
else if (pi->frame_tag.frame_type == INTER_FRAME)
{
pi->refresh_gf = 0;
pi->refresh_af = 0;
}
}
/* This function provides vp8_prob and value infomation for implementing
* segment adaptive adjustments to default decoder behaviors.
* The data parsed here applies to the entire frame. The adjustments can be
* quantization level or loop filter strength.
* */
void vp8_parse_segmentation_adjustments_data(vp8_Info *pi)
{
int i,j;
BOOL_CODER *bc = &(pi->bool_coder);
const int *const mb_feature_data_bits = VP8_MB_FeatureDataBits;
/* Is segmentation enabled */
pi->Segmentation.Enabled = (uint8_t)vp8_decode_bool(bc, 128); //chapter 9.2 - macroblock uses segments ? 1: 0
if(pi->Segmentation.Enabled)
{
/* Signal whether or not the segmentation map is being explicitly updated this frame */
pi->Segmentation.UpdateMap = (uint8_t)vp8_decode_bool(bc, 128);
pi->Segmentation.UpdateData = (uint8_t)vp8_decode_bool(bc, 128);
if (pi->Segmentation.UpdateData)
{
pi->Segmentation.AbsDelta = (uint8_t)vp8_decode_bool(bc, 128);
memset(pi->Segmentation.FeatureData, 0, sizeof(pi->Segmentation.FeatureData));
/* For each segmentation feature (Quant and loop filter level) */
for (i = 0; i < MB_LVL_MAX; ++i)
{
for (j = 0; j < MAX_MB_SEGMENTS; ++j)
{
/* Frame level data */
if (vp8_decode_bool(bc, 128))
{
/* Parse magnitude */
pi->Segmentation.FeatureData[i][j] = (int8_t) vp8_read_bits(bc, mb_feature_data_bits[i]) ;
/* Parse sign data */
if (vp8_decode_bool(bc, 128))
{
pi->Segmentation.FeatureData[i][j] = -pi->Segmentation.FeatureData[i][j];
}
}
else
{
pi->Segmentation.FeatureData[i][j] = 0;
}
}
}
}
if (pi->Segmentation.UpdateMap)
{
/* Which macro block level features are enabled */
memset(pi->Segmentation.TreeProbs, 255, sizeof(pi->Segmentation.TreeProbs));
/* Read the probs used to decode the segment id for each macro block */
for (i = 0; i < MB_FEATURE_TREE_PROBS; ++i)
{
/* If not explicitly set value is defaulted to 255 by memset above */
if (vp8_decode_bool(bc, 128))
{
pi->Segmentation.TreeProbs[i] = (uint8_t)vp8_read_bits(bc, 8);
}
}
}
}
}
/* VP8 supprots two types of loop filter. The data parsed in the header
* to support the selection of the type, strength and sharpness behavior
* of the loop filter used for the current frame.
*/
void vp8_parse_loop_filter_type_level(vp8_Info *pi)
{
BOOL_CODER *bc = &(pi->bool_coder);
/* Read the loop filter level and type */
pi->LoopFilter.Type = (LoopFilterType)vp8_decode_bool(bc, 128);
pi->LoopFilter.Level = (uint8_t)vp8_read_bits(bc, 6);
pi->LoopFilter.Sharpness = (uint8_t)vp8_read_bits(bc, 3);
}
/* This function provides flag and value information for implmenting
* per-macroblock loop filter level adjustments to default decoder
* behaviors. Data parsed here applies to the entire frame.
*/
void vp8_parse_loop_filter_adjustments_data(vp8_Info *pi)
{
int i;
BOOL_CODER *bc = &(pi->bool_coder);
/* Read in loop filter deltas applied at the MB level based on mode or ref frame */
pi->LoopFilter.DeltaUpdate = 0;
pi->LoopFilter.DeltaEnabled = (uint8_t)vp8_decode_bool(bc, 128);
if (pi->LoopFilter.DeltaEnabled)
{
/* Do the deltas need to be updated */
pi->LoopFilter.DeltaUpdate = (uint8_t)vp8_decode_bool(bc, 128);
if (pi->LoopFilter.DeltaUpdate)
{
/* Update based on reference */
for (i = 0; i < MAX_REF_LF_DELTAS; ++i)
{
if (vp8_decode_bool(bc, 128))
{
pi->LoopFilter.DeltasRef[i] = (int8_t)vp8_read_bits(bc, 6);
/* Parse sign */
if (vp8_decode_bool(bc, 128))
{
pi->LoopFilter.DeltasRef[i] = -1 * pi->LoopFilter.DeltasRef[i];
}
}
}
/* Update based on macroblock mode */
for (i = 0; i < MAX_MODE_LF_DELTAS; ++i)
{
if (vp8_decode_bool(bc, 128))
{
pi->LoopFilter.DeltasMode[i] = (int8_t)vp8_read_bits(bc, 6);
/* Parse sign */
if (vp8_decode_bool(bc, 128))
{
pi->LoopFilter.DeltasMode[i] = -1 * pi->LoopFilter.DeltasMode[i];
}
}
} /* End for (i = 0; i < MAX_MODE_LF_DELTAS; ++i) */
} /* End if (pi->LoopFilter.DeltaUpdate) */
}
}
/* Token partition and partition data offsets */
void vp8_parse_token_partition_data(vp8_Info *pi, uint8_t *cx_size)
{
BOOL_CODER *bc = &(pi->bool_coder);
uint8_t *partition = NULL;
uint8_t *source_end = pi->source + pi->source_sz;
uint32_t partition_size = 0, i = 0;
uint8_t *partition_size_ptr = NULL;
/* Parse number of token partitions to use */
pi->partition_count = 1 << (uint8_t)vp8_read_bits(bc, 2);
/* Set up pointers to the first partition */
partition = cx_size;
if (pi->partition_count > 1)
{
/* Each partition offset is written in 3 bytes */
partition += 3 * (pi->partition_count - 1);
}
for (i = 0; i < pi->partition_count; i++)
{
partition_size_ptr = cx_size + i * 3;
if (i < pi->partition_count - 1)
{
pi->partition_size[i] = vp8_read_partition_size(partition_size_ptr);
}
else
{
/* Last offset can be calculated implictly */
pi->partition_size[i] = source_end - partition;
}
partition += pi->partition_size[i];
}
}
int32_t vp8_read_partition_size(uint8_t *cx_size)
{
uint32_t size = cx_size[0] + (cx_size[1] << 8) + (cx_size[2] << 16);
return size;
}
int read_q_delta(BOOL_CODER *bool_coder)
{
int q_delta = 0;
/* presence flag */
if (vp8_decode_bool(bool_coder, 128))
{
/* magnitude */
q_delta = (uint8_t)vp8_read_bits(bool_coder, 4) ;
/* sign */
if (vp8_decode_bool(bool_coder, 128))
{
q_delta = -q_delta;
}
}
return q_delta;
}
/* Read the default quantizers */
void vp8_parse_dequantization_indices(vp8_Info *pi)
{
BOOL_CODER *bc = &(pi->bool_coder);
/* AC 1st order Q = default as a baseline for other 5 items */
pi->Quantization.Y1_AC = (int8_t)vp8_read_bits(bc, 7);
pi->Quantization.Y1_DC_Delta = (int8_t)read_q_delta(bc);
pi->Quantization.Y2_DC_Delta = (int8_t)read_q_delta(bc);
pi->Quantization.Y2_AC_Delta = (int8_t)read_q_delta(bc);
pi->Quantization.UV_DC_Delta = (int8_t)read_q_delta(bc);
pi->Quantization.UV_AC_Delta = (int8_t)read_q_delta(bc);
}
/* Determine if the golden frame or ARF buffer should be updated and how.
* For all non key frames the GF and ARF refresh flags and sign bias
* flags must be set explicitly.
*/
void vp8_parse_gf_af_refresh_flags(vp8_Info *pi)
{
BOOL_CODER *bc = &(pi->bool_coder);
/* Read Golden and AltRef frame refresh */
pi->refresh_gf = (uint8_t)vp8_decode_bool(bc, 128);
pi->refresh_af = (uint8_t)vp8_decode_bool(bc, 128);
/* If not refreshed using the current reconstructed frame */
if (0 == pi->refresh_gf)
{
/* 2 bit indicating which buffer is copied to golden frame */
pi->golden_copied = (GoldenBufferCopiedType)(int8_t)vp8_read_bits(bc, 2);
}
else
{
/* No buffer is copied */
pi->golden_copied = (GoldenBufferCopiedType)0;
}
if (0 == pi->refresh_af)
{
/* 2 bit indicating which buffer is copied to alternative frame */
pi->altref_copied = (AltRefBufferCopiedType)vp8_read_bits(bc, 2);
}
else
{
pi->altref_copied = (AltRefBufferCopiedType)0;
}
pi->sign_bias_golden = (uint8_t)vp8_decode_bool(bc, 128);
pi->sign_bias_alternate = (uint8_t)vp8_decode_bool(bc, 128);
}
void vp8_parse_coef_probs_tree(vp8_Info *pi)
{
int i, j, k, l;
BOOL_CODER *bc = &(pi->bool_coder);
/* DCT coeffienct probability tree update */
for (i = 0; i < BLOCK_TYPES; i++)
{
for (j = 0; j < COEF_BANDS; j++)
{
for (k = 0; k < PREV_COEF_CONTEXTS; k++)
{
for (l = 0; l < MAX_COEF_TOKENS - 1; l++)
{
if (vp8_decode_bool(bc, VP8_Coefficient_Update_Probabilites[i][j][k][l]))
{
pi->FrameContext.DCT_Coefficients[i][j][k][l] = (vp8_prob)vp8_read_bits(bc, 8);
}
}
}
}
}
}
/* Parse remaining non-key-frame only data from frame header */
void vp8_parse_mb_mv_info(vp8_Info *pi)
{
// read_mvcontexts
int i = 0;
BOOL_CODER *bc = &(pi->bool_coder);
do
{
const vp8_prob *up = VP8_MV_UpdateProbs[i];
vp8_prob *p = pi->FrameContext.MVContext[i];
vp8_prob *const pstop = p + VP8_MV_Pcount;
do
{
if (vp8_decode_bool(bc , *up++ ))
{
const vp8_prob x = (vp8_prob)vp8_read_bits(bc, 7);
*p = x ? x << 1 : 1;
}
}
while (++p < pstop);
}
while (++i < 2);
}
/* Parse remaining non-key-frame only data from frame header */
void vp8_parse_yuv_probs_update(vp8_Info *pi)
{
BOOL_CODER *bc = &(pi->bool_coder);
/* Read probabilities */
pi->prob_intra = (vp8_prob)vp8_read_bits(bc, 8);
pi->prob_lf = (vp8_prob)vp8_read_bits(bc, 8);
pi->prob_gf = (vp8_prob)vp8_read_bits(bc, 8);
pi->y_prob_valid = (uint8_t)vp8_decode_bool(bc , 128);
if (1 == pi->y_prob_valid)
{
pi->FrameContext.Y_Mode_Prob[0] = (vp8_prob)vp8_read_bits(bc, 8);
pi->FrameContext.Y_Mode_Prob[1] = (vp8_prob)vp8_read_bits(bc, 8);
pi->FrameContext.Y_Mode_Prob[2] = (vp8_prob)vp8_read_bits(bc, 8);
pi->FrameContext.Y_Mode_Prob[3] = (vp8_prob)vp8_read_bits(bc, 8);
}
pi->c_prob_valid = (uint8_t)vp8_decode_bool(bc , 128);
if (1 == pi->c_prob_valid)
{
pi->FrameContext.UV_Mode_Prob[0] = (vp8_prob)vp8_read_bits(bc, 8);
pi->FrameContext.UV_Mode_Prob[1] = (vp8_prob)vp8_read_bits(bc, 8);
pi->FrameContext.UV_Mode_Prob[2] = (vp8_prob)vp8_read_bits(bc, 8);
}
}
void vp8_parse_remaining_frame_header_data(vp8_Info *pi)
{
BOOL_CODER *bc = &(pi->bool_coder);
/* MB no coefficients skip */
pi->mb_no_coeff_skip = (uint8_t)vp8_decode_bool(bc, 128);
if (1 == pi->mb_no_coeff_skip)
{
pi->prob_skip_false = (vp8_prob)vp8_read_bits(bc, 8);
}
if (pi->frame_tag.frame_type == INTER_FRAME)
{
vp8_parse_yuv_probs_update(pi);
/* Read motion vector info */
vp8_parse_mb_mv_info(pi);
}
}
void vp8_translate_parse_status(vp8_Status status)
{
switch (status)
{
case VP8_UNSUPPORTED_VERSION:
ETRACE("Parser returns VP8_UNSUPPORTED_VERSION");
break;
case VP8_UNSUPPORTED_BITSTREAM:
ETRACE("Parser returns VP8_UNSUPPORTED_BITSTREAM");
break;
case VP8_INVALID_FRAME_SYNC_CODE:
ETRACE("Parser returns VP8_INVALID_FRAME_SYNC_CODE");
break;
case VP8_UNEXPECTED_END_OF_BITSTREAM:
ETRACE("Parser returns VP8_UNEXPECTED_END_OF_BITSTREAM");
break;
case VP8_CORRUPT_FRAME:
ETRACE("Parser returns VP8_CORRUPT_FRAME");
break;
case VP8_MEMORY_ERROR:
ETRACE("Parser returns MEMORY_ERROR");
break;
case VP8_NO_INITIALIZATION:
ETRACE("Parser returns VP8_NO_INITIALIZATION");
break;
case VP8_UNKNOWN_ERROR:
ETRACE("Parser returns VP8_UNKNOWN_ERROR");
break;
}
return;
}
/* Parse VP8 frame header */
int32_t vp8_parse_frame_header(vp8_viddec_parser *parser)
{
vp8_Status ret = VP8_NO_ERROR;
vp8_Info *pi = &(parser->info);
uint8_t *data = pi->source;
uint32_t data_sz = pi->source_sz;
if (0 == pi->refresh_entropy_lf)
{
memcpy(&(pi->FrameContext), &(pi->LastFrameContext), sizeof(FrameContextData));
}
/* Step 1 : parse frame tag containing 3 bytes*/
ret = vp8_parse_frame_tag(&(pi->frame_tag), data, data_sz);
if (ret != VP8_NO_ERROR)
{
vp8_translate_parse_status(ret);
return ret;
}
/* Pointer advances 3 bytes */
data += 3;
/* Start the frame data offset */
pi->frame_data_offset = 3;
/* Step 2 : parse key frame parameters*/
if (pi->frame_tag.frame_type == KEY_FRAME)
{
/* Check sync code containg 3 bytes*/
if ((data[0] != kVp8SyncCodeByte[0]) || (data[1] != kVp8SyncCodeByte[1]) || (data[2] != kVp8SyncCodeByte[2]))
{
ret = VP8_INVALID_FRAME_SYNC_CODE;
vp8_translate_parse_status(ret);
return ret;
}
pi->width = (data[3] | (data[4] << 8)) & 0x3fff;
pi->horiz_scale = data[4] >> 6;
pi->height = (data[5] | (data[6] << 8)) & 0x3fff;
pi->vert_scale = data[6] >> 6;
/* Pointer advances 7 bytes in this case*/
data += 7;
pi->frame_data_offset += 7;
}
if (0 == pi->width || 0 == pi->height)
{
ret = VP8_UNSUPPORTED_BITSTREAM;
vp8_translate_parse_status(ret);
return ret;
}
/* Initialize frame parameters*/
vp8_init_frame(pi);
/* Initialize bool coder */
BOOL_CODER *bc = &(pi->bool_coder);
vp8_start_decode(bc, (uint8_t*)data);
/* Parse key frame parameters */
if (pi->frame_tag.frame_type == KEY_FRAME)
{
pi->clr_type = (YUV_TYPE)vp8_decode_bool(bc, 128);
pi->clamp_type = (CLAMP_TYPE)vp8_decode_bool(bc, 128);
}
/* Step 3 : parse macroblock-level segmentation flag */
vp8_parse_segmentation_adjustments_data(pi);
/* Step 4 : parse loop filter type and levels */
vp8_parse_loop_filter_type_level(pi);
/* Step 5 : parse macroblock-level loop filter adjustments */
vp8_parse_loop_filter_adjustments_data(pi);
/* Step 6: parse token partition and partition data offsets */
vp8_parse_token_partition_data(pi, data + pi->frame_tag.first_part_size);
/* Step 7: parse dequantization indices */
vp8_parse_dequantization_indices(pi);
/* For key frames, both golden frame and altref frame are refreshed/replaced by the current reconstructed frame, by default */
if (pi->frame_tag.frame_type == INTER_FRAME)
{
/* Step 8: parse golden frame and altref frame refresh flags */
vp8_parse_gf_af_refresh_flags(pi);
}
/* Step 9: update proability to decode DCT coef */
pi->refresh_entropy = (uint8_t)vp8_decode_bool(bc, 128);
if (pi->refresh_entropy == 0)
{
memcpy(&(pi->LastFrameContext), &(pi->FrameContext), sizeof(FrameContextData));
}
/* Step 10: refresh last frame buffer */
pi->refresh_lf = (pi->frame_tag.frame_type == KEY_FRAME) || (uint8_t)(vp8_decode_bool(bc, 128));
/* Step 11: read coef vp8_prob tree */
vp8_parse_coef_probs_tree(pi);
/* Step 12: read remaining frame header data */
vp8_parse_remaining_frame_header_data(pi);
/* Hold the current offset in the bitstream */
pi->frame_data_offset += pi->bool_coder.pos;
/* Get the frame header bits */
pi->header_bits = pi->frame_data_offset * 8 - 16 - pi->bool_coder.count;
pi->refresh_entropy_lf = pi->refresh_entropy;
return ret;
}