/* * Copyright 2016 Intel Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * SECTION:vp9parser * @short_description: Convenience library for parsing vp9 video bitstream. * * For more details about the structures, you can refer to the * specifications: */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "bitReader.h" #include "vp9quant.h" #include "vp9parser.h" #include #include #include "common/log.h" using YamiParser::BitReader; #define MAX_LOOP_FILTER 63 #define MAX_PROB 255 typedef struct _ReferenceSize { uint32_t width; uint32_t height; } ReferenceSize; typedef struct _Vp9ParserPrivate { int8_t y_dc_delta_q; int8_t uv_dc_delta_q; int8_t uv_ac_delta_q; int16_t y_dequant[QINDEX_RANGE][2]; int16_t uv_dequant[QINDEX_RANGE][2]; /* for loop filters */ int8_t ref_deltas[VP9_MAX_REF_LF_DELTAS]; int8_t mode_deltas[VP9_MAX_MODE_LF_DELTAS]; BOOL segmentation_abs_delta; Vp9SegmentationInfoData segmentation[VP9_MAX_SEGMENTS]; ReferenceSize reference[VP9_REF_FRAMES]; } Vp9ParserPrivate; void init_dequantizer(Vp9Parser* parser); static void init_vp9_parser(Vp9Parser* parser, VP9_BIT_DEPTH bit_depth) { Vp9ParserPrivate* priv = (Vp9ParserPrivate*)parser->priv; memset(parser, 0, sizeof(Vp9Parser)); memset(priv, 0, sizeof(Vp9ParserPrivate)); parser->priv = priv; parser->bit_depth = bit_depth; init_dequantizer(parser); } Vp9Parser* vp9_parser_new() { Vp9Parser* parser = (Vp9Parser*)malloc(sizeof(Vp9Parser)); if (!parser) return NULL; Vp9ParserPrivate* priv = (Vp9ParserPrivate*)malloc(sizeof(Vp9ParserPrivate)); if (!priv) { free(parser); return NULL; } parser->priv = priv; init_vp9_parser(parser, VP9_BITS_8); return parser; } void vp9_parser_free(Vp9Parser* parser) { if (parser) { if (parser->priv) free(parser->priv); free(parser); } } #define vp9_read_bit(br) br->read(1) #define vp9_read_bits(br, bits) br->read(bits) static int32_t vp9_read_signed_bits(BitReader* br, int bits) { assert(bits < 32); const int32_t value = vp9_read_bits(br, bits); return vp9_read_bit(br) ? -value : value; } static BOOL verify_frame_marker(BitReader* br) { #define VP9_FRAME_MARKER 2 uint8_t frame_marker = vp9_read_bits(br, 2); if (frame_marker != VP9_FRAME_MARKER) return FALSE; return TRUE; } static BOOL verify_sync_code(BitReader* const br) { #define VP9_SYNC_CODE_0 0x49 #define VP9_SYNC_CODE_1 0x83 #define VP9_SYNC_CODE_2 0x42 return vp9_read_bits(br, 8) == VP9_SYNC_CODE_0 && vp9_read_bits(br, 8) == VP9_SYNC_CODE_1 && vp9_read_bits(br, 8) == VP9_SYNC_CODE_2; } static VP9_PROFILE read_profile(BitReader* br) { uint8_t profile = vp9_read_bit(br); profile |= vp9_read_bit(br) << 1; if (profile > 2) profile += vp9_read_bit(br); return (VP9_PROFILE)profile; } static void read_frame_size(BitReader* br, uint32_t* width, uint32_t* height) { const uint32_t w = vp9_read_bits(br, 16) + 1; const uint32_t h = vp9_read_bits(br, 16) + 1; *width = w; *height = h; } static void read_display_frame_size(Vp9FrameHdr* frame_hdr, BitReader* br) { frame_hdr->display_size_enabled = vp9_read_bit(br); if (frame_hdr->display_size_enabled) { read_frame_size(br, &frame_hdr->display_width, &frame_hdr->display_height); } } static void read_frame_size_from_refs(const Vp9Parser* parser, Vp9FrameHdr* frame_hdr, BitReader* br) { BOOL found = FALSE; int i; const Vp9ParserPrivate* priv = (Vp9ParserPrivate*)parser->priv; for (i = 0; i < VP9_REFS_PER_FRAME; i++) { found = vp9_read_bit(br); if (found) { uint8_t idx = frame_hdr->ref_frame_indices[i]; frame_hdr->size_from_ref[i] = TRUE; frame_hdr->width = priv->reference[idx].width; frame_hdr->height = priv->reference[idx].height; break; } } if (!found) { read_frame_size(br, &frame_hdr->width, &frame_hdr->height); } } static VP9_INTERP_FILTER read_interp_filter(BitReader* br) { const VP9_INTERP_FILTER filter_map[] = { VP9_EIGHTTAP_SMOOTH, VP9_EIGHTTAP, VP9_EIGHTTAP_SHARP, VP9_BILINEAR }; return vp9_read_bit(br) ? VP9_SWITCHABLE : filter_map[vp9_read_bits(br, 2)]; } static void read_loopfilter(Vp9LoopFilter* lf, BitReader* br) { lf->filter_level = vp9_read_bits(br, 6); lf->sharpness_level = vp9_read_bits(br, 3); lf->mode_ref_delta_update = 0; lf->mode_ref_delta_enabled = vp9_read_bit(br); if (lf->mode_ref_delta_enabled) { lf->mode_ref_delta_update = vp9_read_bit(br); if (lf->mode_ref_delta_update) { int i; for (i = 0; i < VP9_MAX_REF_LF_DELTAS; i++) { lf->update_ref_deltas[i] = vp9_read_bit(br); if (lf->update_ref_deltas[i]) lf->ref_deltas[i] = vp9_read_signed_bits(br, 6); } for (i = 0; i < VP9_MAX_MODE_LF_DELTAS; i++) { lf->update_mode_deltas[i] = vp9_read_bit(br); if (lf->update_mode_deltas[i]) lf->mode_deltas[i] = vp9_read_signed_bits(br, 6); } } } } static int8_t read_delta_q(BitReader* br) { return vp9_read_bit(br) ? vp9_read_signed_bits(br, 4) : 0; } static void read_quantization(Vp9FrameHdr* frame_hdr, BitReader* br) { frame_hdr->base_qindex = vp9_read_bits(br, QINDEX_BITS); frame_hdr->y_dc_delta_q = read_delta_q(br); frame_hdr->uv_dc_delta_q = read_delta_q(br); frame_hdr->uv_ac_delta_q = read_delta_q(br); } static void read_segmentation(Vp9SegmentationInfo* seg, BitReader* br) { int i; seg->update_map = FALSE; seg->update_data = FALSE; seg->enabled = vp9_read_bit(br); if (!seg->enabled) return; seg->update_map = vp9_read_bit(br); if (seg->update_map) { for (i = 0; i < VP9_SEG_TREE_PROBS; i++) { seg->update_tree_probs[i] = vp9_read_bit(br); seg->tree_probs[i] = seg->update_tree_probs[i] ? vp9_read_bits(br, 8) : MAX_PROB; } seg->temporal_update = vp9_read_bit(br); if (seg->temporal_update) { for (i = 0; i < VP9_PREDICTION_PROBS; i++) { seg->update_pred_probs[i] = vp9_read_bit(br); seg->pred_probs[i] = seg->update_pred_probs[i] ? vp9_read_bits(br, 8) : MAX_PROB; } } else { for (i = 0; i < VP9_PREDICTION_PROBS; i++) { seg->pred_probs[i] = MAX_PROB; } } } seg->update_data = vp9_read_bit(br); if (seg->update_data) { /* clear all features */ memset(seg->data, 0, sizeof(seg->data)); seg->abs_delta = vp9_read_bit(br); for (i = 0; i < VP9_MAX_SEGMENTS; i++) { Vp9SegmentationInfoData* seg_data = seg->data + i; uint8_t data; /* SEG_LVL_ALT_Q */ seg_data->alternate_quantizer_enabled = vp9_read_bit(br); if (seg_data->alternate_quantizer_enabled) { data = vp9_read_bits(br, 8); seg_data->alternate_quantizer = vp9_read_bit(br) ? -data : data; } /* SEG_LVL_ALT_LF */ seg_data->alternate_loop_filter_enabled = vp9_read_bit(br); if (seg_data->alternate_loop_filter_enabled) { data = vp9_read_bits(br, 6); seg_data->alternate_loop_filter = vp9_read_bit(br) ? -data : data; } /* SEG_LVL_REF_FRAME */ seg_data->reference_frame_enabled = vp9_read_bit(br); if (seg_data->reference_frame_enabled) { seg_data->reference_frame = vp9_read_bits(br, 2); } seg_data->reference_skip = vp9_read_bit(br); } } } #define MIN_TILE_WIDTH_B64 4 #define MAX_TILE_WIDTH_B64 64 uint32_t get_max_lb_tile_cols(uint32_t sb_cols) { int log2 = 0; while ((sb_cols >> log2) >= MIN_TILE_WIDTH_B64) ++log2; if (log2) log2--; return log2; } uint32_t get_min_lb_tile_cols(uint32_t sb_cols) { uint32_t log2 = 0; while ((uint64_t)(MAX_TILE_WIDTH_B64 << log2) < sb_cols) ++log2; return log2; } /* align to 64, follow specification 6.2.6 Compute image size syntax */ #define SB_ALIGN(w) (((w) + 63) >> 6) static BOOL read_tile_info(Vp9FrameHdr* frame_hdr, BitReader* br) { const uint32_t sb_cols = SB_ALIGN(frame_hdr->width); uint32_t min_lb_tile_cols = get_min_lb_tile_cols(sb_cols); uint32_t max_lb_tile_cols = get_max_lb_tile_cols(sb_cols); uint32_t max_ones = max_lb_tile_cols - min_lb_tile_cols; /* columns */ frame_hdr->log2_tile_columns = min_lb_tile_cols; while (max_ones-- && vp9_read_bit(br)) frame_hdr->log2_tile_columns++; /* row */ frame_hdr->log2_tile_rows = vp9_read_bit(br); if (frame_hdr->log2_tile_rows) frame_hdr->log2_tile_rows += vp9_read_bit(br); return TRUE; } static void loop_filter_update(Vp9Parser* parser, const Vp9LoopFilter* lf) { Vp9ParserPrivate* priv = (Vp9ParserPrivate*)parser->priv; int i; for (i = 0; i < VP9_MAX_REF_LF_DELTAS; i++) { if (lf->update_ref_deltas[i]) priv->ref_deltas[i] = lf->ref_deltas[i]; } for (i = 0; i < VP9_MAX_MODE_LF_DELTAS; i++) { if (lf->update_mode_deltas[i]) priv->mode_deltas[i] = lf->mode_deltas[i]; } } BOOL compare_and_set(int8_t* dest, const int8_t src) { const int8_t old = *dest; *dest = src; return old != src; } void init_dequantizer(Vp9Parser* parser) { Vp9ParserPrivate* priv = (Vp9ParserPrivate*)parser->priv; int q; for (q = 0; q < QINDEX_RANGE; q++) { priv->y_dequant[q][0] = vp9_dc_quant(parser->bit_depth, q, priv->y_dc_delta_q); priv->y_dequant[q][1] = vp9_ac_quant(parser->bit_depth, q, 0); priv->uv_dequant[q][0] = vp9_dc_quant(parser->bit_depth, q, priv->uv_dc_delta_q); priv->uv_dequant[q][1] = vp9_ac_quant(parser->bit_depth, q, priv->uv_ac_delta_q); } } static void quantization_update(Vp9Parser* parser, const Vp9FrameHdr* frame_hdr) { BOOL update = FALSE; Vp9ParserPrivate* priv = (Vp9ParserPrivate*)parser->priv; update |= compare_and_set(&priv->y_dc_delta_q, frame_hdr->y_dc_delta_q); update |= compare_and_set(&priv->uv_dc_delta_q, frame_hdr->uv_dc_delta_q); update |= compare_and_set(&priv->uv_ac_delta_q, frame_hdr->uv_ac_delta_q); if (update) { init_dequantizer(parser); } parser->lossless_flag = frame_hdr->base_qindex == 0 && frame_hdr->y_dc_delta_q == 0 && frame_hdr->uv_dc_delta_q == 0 && frame_hdr->uv_ac_delta_q == 0; } uint8_t seg_get_base_qindex(const Vp9Parser* parser, const Vp9FrameHdr* frame_hdr, int segid) { int seg_base = frame_hdr->base_qindex; Vp9ParserPrivate* priv = (Vp9ParserPrivate*)parser->priv; const Vp9SegmentationInfoData* seg = priv->segmentation + segid; /* DEBUG("id = %d, seg_base = %d, seg enable = %d, alt eanble = %d, abs = %d, alt= %d\n",segid, seg_base, frame_hdr->segmentation.enabled, seg->alternate_quantizer_enabled, priv->segmentation_abs_delta, seg->alternate_quantizer); */ if (frame_hdr->segmentation.enabled && seg->alternate_quantizer_enabled) { if (priv->segmentation_abs_delta) seg_base = seg->alternate_quantizer; else seg_base += seg->alternate_quantizer; } return clamp(seg_base, 0, MAXQ); } uint8_t seg_get_filter_level(const Vp9Parser* parser, const Vp9FrameHdr* frame_hdr, int segid) { int seg_filter = frame_hdr->loopfilter.filter_level; Vp9ParserPrivate* priv = (Vp9ParserPrivate*)parser->priv; const Vp9SegmentationInfoData* seg = priv->segmentation + segid; if (frame_hdr->segmentation.enabled && seg->alternate_loop_filter_enabled) { if (priv->segmentation_abs_delta) seg_filter = seg->alternate_loop_filter; else seg_filter += seg->alternate_loop_filter; } return clamp(seg_filter, 0, MAX_LOOP_FILTER); } /*save segmentation info from frame header to parser*/ static void segmentation_save(Vp9Parser* parser, const Vp9FrameHdr* frame_hdr) { const Vp9SegmentationInfo* info = &frame_hdr->segmentation; if (!info->enabled) return; if (info->update_map) { ASSERT(sizeof(parser->mb_segment_tree_probs) == sizeof(info->tree_probs)); ASSERT(sizeof(parser->segment_pred_probs) == sizeof(info->pred_probs)); memcpy(parser->mb_segment_tree_probs, info->tree_probs, sizeof(info->tree_probs)); memcpy(parser->segment_pred_probs, info->pred_probs, sizeof(info->pred_probs)); } if (info->update_data) { Vp9ParserPrivate* priv = (Vp9ParserPrivate*)parser->priv; priv->segmentation_abs_delta = info->abs_delta; ASSERT(sizeof(priv->segmentation) == sizeof(info->data)); memcpy(priv->segmentation, info->data, sizeof(info->data)); } } static void segmentation_update(Vp9Parser* parser, const Vp9FrameHdr* frame_hdr) { int i = 0; const Vp9ParserPrivate* priv = (Vp9ParserPrivate*)parser->priv; const Vp9LoopFilter* lf = &frame_hdr->loopfilter; int default_filter = lf->filter_level; const int scale = 1 << (default_filter >> 5); segmentation_save(parser, frame_hdr); for (i = 0; i < VP9_MAX_SEGMENTS; i++) { uint8_t q = seg_get_base_qindex(parser, frame_hdr, i); Vp9Segmentation* seg = parser->segmentation + i; const Vp9SegmentationInfoData* info = priv->segmentation + i; seg->luma_dc_quant_scale = priv->y_dequant[q][0]; seg->luma_ac_quant_scale = priv->y_dequant[q][1]; seg->chroma_dc_quant_scale = priv->uv_dequant[q][0]; seg->chroma_ac_quant_scale = priv->uv_dequant[q][1]; if (lf->filter_level) { uint8_t filter = seg_get_filter_level(parser, frame_hdr, i); if (!lf->mode_ref_delta_enabled) { memset(seg->filter_level, filter, sizeof(seg->filter_level)); } else { int ref, mode; const int intra_filter = filter + priv->ref_deltas[VP9_INTRA_FRAME] * scale; seg->filter_level[VP9_INTRA_FRAME][0] = clamp(intra_filter, 0, MAX_LOOP_FILTER); for (ref = VP9_LAST_FRAME; ref < VP9_MAX_REF_FRAMES; ++ref) { for (mode = 0; mode < VP9_MAX_MODE_LF_DELTAS; ++mode) { const int inter_filter = filter + priv->ref_deltas[ref] * scale + priv->mode_deltas[mode] * scale; seg->filter_level[ref][mode] = clamp(inter_filter, 0, MAX_LOOP_FILTER); } } } } seg->reference_frame_enabled = info->reference_frame_enabled; ; seg->reference_frame = info->reference_frame; seg->reference_skip = info->reference_skip; } } static void reference_update(Vp9Parser* parser, const Vp9FrameHdr* const frame_hdr) { uint8_t flag = 1; uint8_t refresh_frame_flags; int i; Vp9ParserPrivate* priv = (Vp9ParserPrivate*)parser->priv; ReferenceSize* reference = priv->reference; if (frame_hdr->frame_type == VP9_KEY_FRAME) { refresh_frame_flags = 0xff; } else { refresh_frame_flags = frame_hdr->refresh_frame_flags; } for (i = 0; i < VP9_REF_FRAMES; i++) { if (refresh_frame_flags & flag) { reference[i].width = frame_hdr->width; reference[i].height = frame_hdr->height; } flag <<= 1; } } static inline int key_or_intra_only(const Vp9FrameHdr* frame_hdr) { return frame_hdr->frame_type == VP9_KEY_FRAME || frame_hdr->intra_only; } static void set_default_lf_deltas(Vp9Parser* parser) { Vp9ParserPrivate* priv = (Vp9ParserPrivate*)parser->priv; priv->ref_deltas[VP9_INTRA_FRAME] = 1; priv->ref_deltas[VP9_LAST_FRAME] = 0; priv->ref_deltas[VP9_GOLDEN_FRAME] = -1; priv->ref_deltas[VP9_ALTREF_FRAME] = -1; priv->mode_deltas[0] = 0; priv->mode_deltas[1] = 0; } static void set_default_segmentation_info(Vp9Parser* parser) { Vp9ParserPrivate* priv = (Vp9ParserPrivate*)parser->priv; memset(priv->segmentation, 0, sizeof(priv->segmentation)); priv->segmentation_abs_delta = FALSE; } static void setup_past_independence(Vp9Parser* parser, Vp9FrameHdr* const frame_hdr) { set_default_lf_deltas(parser); set_default_segmentation_info(parser); memset(frame_hdr->ref_frame_sign_bias, 0, sizeof(frame_hdr->ref_frame_sign_bias)); } static Vp9ParseResult vp9_parser_update(Vp9Parser* parser, Vp9FrameHdr* const frame_hdr) { if (frame_hdr->frame_type == VP9_KEY_FRAME) { init_vp9_parser(parser, frame_hdr->bit_depth); } if (key_or_intra_only(frame_hdr) || frame_hdr->error_resilient_mode) { setup_past_independence(parser, frame_hdr); } loop_filter_update(parser, &frame_hdr->loopfilter); quantization_update(parser, frame_hdr); segmentation_update(parser, frame_hdr); reference_update(parser, frame_hdr); return VP9_PARSER_OK; } static Vp9ParseResult vp9_color_config(Vp9Parser* parser, Vp9FrameHdr* frame_hdr, BitReader* br) { if (frame_hdr->profile >= VP9_PROFILE_2) { frame_hdr->bit_depth = vp9_read_bit(br) ? VP9_BITS_12 : VP9_BITS_10; if (VP9_BITS_12 == frame_hdr->bit_depth) { ERROR("vp9 12 bits-depth is unsupported by now!"); return VP9_PARSER_UNSUPPORTED; } } else { frame_hdr->bit_depth = VP9_BITS_8; } frame_hdr->color_space = (VP9_COLOR_SPACE)vp9_read_bits(br, 3); if (frame_hdr->color_space != VP9_SRGB) { vp9_read_bit(br); //color_range if (frame_hdr->profile == VP9_PROFILE_1 || frame_hdr->profile == VP9_PROFILE_3) { frame_hdr->subsampling_x = vp9_read_bit(br); frame_hdr->subsampling_y = vp9_read_bit(br); if (vp9_read_bit(br)) { //reserved_zero ERROR("reserved bit"); return VP9_PARSER_ERROR; } } else { frame_hdr->subsampling_y = frame_hdr->subsampling_x = 1; } } else { ERROR("do not support SRGB"); return VP9_PARSER_UNSUPPORTED; } return VP9_PARSER_OK; } Vp9ParseResult vp9_parse_frame_header(Vp9Parser* parser, Vp9FrameHdr* frame_hdr, const uint8_t* data, uint32_t size) { #define FRAME_CONTEXTS_BITS 2 BitReader bit_reader(data, size); BitReader* br = &bit_reader; memset(frame_hdr, 0, sizeof(*frame_hdr)); /* Uncompressed Data Chunk */ if (!verify_frame_marker(br)) goto error; frame_hdr->profile = read_profile(br); if (frame_hdr->profile > MAX_VP9_PROFILES) goto error; frame_hdr->show_existing_frame = vp9_read_bit(br); if (frame_hdr->show_existing_frame) { frame_hdr->frame_to_show = vp9_read_bits(br, VP9_REF_FRAMES_LOG2); return VP9_PARSER_OK; } frame_hdr->frame_type = (VP9_FRAME_TYPE)vp9_read_bit(br); frame_hdr->show_frame = vp9_read_bit(br); frame_hdr->error_resilient_mode = vp9_read_bit(br); if (frame_hdr->frame_type == VP9_KEY_FRAME) { if (!verify_sync_code(br)) goto error; if (vp9_color_config(parser, frame_hdr, br) != VP9_PARSER_OK) goto error; read_frame_size(br, &frame_hdr->width, &frame_hdr->height); read_display_frame_size(frame_hdr, br); } else { frame_hdr->intra_only = frame_hdr->show_frame ? 0 : vp9_read_bit(br); frame_hdr->reset_frame_context = frame_hdr->error_resilient_mode ? 0 : vp9_read_bits(br, 2); if (frame_hdr->intra_only) { if (!verify_sync_code(br)) goto error; if (frame_hdr->profile > VP9_PROFILE_0) { if (vp9_color_config(parser, frame_hdr, br) != VP9_PARSER_OK) goto error; } else { frame_hdr->color_space = VP9_BT_601; frame_hdr->subsampling_y = frame_hdr->subsampling_x = 1; frame_hdr->bit_depth = VP9_BITS_8; } frame_hdr->refresh_frame_flags = vp9_read_bits(br, VP9_REF_FRAMES); read_frame_size(br, &frame_hdr->width, &frame_hdr->height); read_display_frame_size(frame_hdr, br); } else { int i; frame_hdr->refresh_frame_flags = vp9_read_bits(br, VP9_REF_FRAMES); for (i = 0; i < VP9_REFS_PER_FRAME; i++) { frame_hdr->ref_frame_indices[i] = vp9_read_bits(br, VP9_REF_FRAMES_LOG2); frame_hdr->ref_frame_sign_bias[i] = vp9_read_bit(br); } read_frame_size_from_refs(parser, frame_hdr, br); read_display_frame_size(frame_hdr, br); frame_hdr->allow_high_precision_mv = vp9_read_bit(br); frame_hdr->mcomp_filter_type = read_interp_filter(br); } } if (!frame_hdr->error_resilient_mode) { frame_hdr->refresh_frame_context = vp9_read_bit(br); frame_hdr->frame_parallel_decoding_mode = vp9_read_bit(br); } else { frame_hdr->frame_parallel_decoding_mode = TRUE; } frame_hdr->frame_context_idx = vp9_read_bits(br, FRAME_CONTEXTS_BITS); read_loopfilter(&frame_hdr->loopfilter, br); read_quantization(frame_hdr, br); read_segmentation(&frame_hdr->segmentation, br); if (!read_tile_info(frame_hdr, br)) goto error; frame_hdr->first_partition_size = vp9_read_bits(br, 16); if (!frame_hdr->first_partition_size) goto error; frame_hdr->frame_header_length_in_bytes = (br->getPos() + 7) / 8; return vp9_parser_update(parser, frame_hdr); error: return VP9_PARSER_ERROR; }