| /* 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); |
| } |
| else |
| { |
| pi->mb_skip_coeff = 0; |
| } |
| |
| 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; |
| } |