From 18c83b3714d252d6309d67b5ded534132d2b9ec9 Mon Sep 17 00:00:00 2001 From: Dmitry Kovalev <dkovalev@google.com> Date: Tue, 28 May 2013 18:07:54 -0700 Subject: [PATCH] Compressed/uncompressed frame header changes. Adding API to read/write uncompressed frame header bits (it is not final yet). Separate functions to read/write uncompressed header. Moving clr_type, error_resilient_mode, refresh_frame_context, frame_parallel_decoding_mode, frame_context_idx from compressed partition to uncompressed frame header. Change-Id: Id3ed8a387980c652ae147549412f4ec24a0a5bd0 --- vp9/common/vp9_common.h | 5 + vp9/common/vp9_header.h | 39 ------ vp9/common/vp9_modecont.h | 2 + vp9/common/vp9_onyxc_int.h | 4 - vp9/decoder/vp9_decodframe.c | 194 ++++++++++++++--------------- vp9/decoder/vp9_read_bit_buffer.h | 50 ++++++++ vp9/encoder/vp9_bitstream.c | 145 +++++++++------------ vp9/encoder/vp9_onyx_if.c | 3 - vp9/encoder/vp9_write_bit_buffer.h | 42 +++++++ vp9/vp9_common.mk | 1 - vp9/vp9_dx_iface.c | 20 +-- vp9/vp9cx.mk | 1 + vp9/vp9dx.mk | 1 + 13 files changed, 264 insertions(+), 243 deletions(-) delete mode 100644 vp9/common/vp9_header.h create mode 100644 vp9/decoder/vp9_read_bit_buffer.h create mode 100644 vp9/encoder/vp9_write_bit_buffer.h diff --git a/vp9/common/vp9_common.h b/vp9/common/vp9_common.h index b6252d93e3..5c97f98633 100644 --- a/vp9/common/vp9_common.h +++ b/vp9/common/vp9_common.h @@ -60,4 +60,9 @@ static INLINE int multiple16(int value) { return (value + 15) & ~15; } +#define SYNC_CODE_0 0x49 +#define SYNC_CODE_1 0x83 +#define SYNC_CODE_2 0x42 + + #endif // VP9_COMMON_VP9_COMMON_H_ diff --git a/vp9/common/vp9_header.h b/vp9/common/vp9_header.h deleted file mode 100644 index 96b04e7d78..0000000000 --- a/vp9/common/vp9_header.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2010 The WebM project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef VP9_COMMON_VP9_HEADER_H_ -#define VP9_COMMON_VP9_HEADER_H_ - -/* 24 bits total */ -typedef struct { - unsigned int type: 1; - unsigned int version: 3; - unsigned int show_frame: 1; - - /* Allow 2^20 bytes = 8 megabits for first partition */ - - unsigned int first_partition_length_in_bytes: 19; - -#ifdef PACKET_TESTING - unsigned int frame_number; - unsigned int update_gold: 1; - unsigned int uses_gold: 1; - unsigned int update_last: 1; - unsigned int uses_last: 1; -#endif -} VP9_HEADER; - -#ifdef PACKET_TESTING -#define VP9_HEADER_SIZE 8 -#else -#define VP9_HEADER_SIZE 3 -#endif - -#endif // VP9_COMMON_VP9_HEADER_H_ diff --git a/vp9/common/vp9_modecont.h b/vp9/common/vp9_modecont.h index 24f1a6cb32..30deb72d3e 100644 --- a/vp9/common/vp9_modecont.h +++ b/vp9/common/vp9_modecont.h @@ -11,6 +11,8 @@ #ifndef VP9_COMMON_VP9_MODECONT_H_ #define VP9_COMMON_VP9_MODECONT_H_ +#include "vp9/common/vp9_entropy.h" + extern const int vp9_default_mode_contexts[INTER_MODE_CONTEXTS][4]; #endif // VP9_COMMON_VP9_MODECONT_H_ diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h index c277ea3cb0..b148a6377b 100644 --- a/vp9/common/vp9_onyxc_int.h +++ b/vp9/common/vp9_onyxc_int.h @@ -24,10 +24,6 @@ #include "vp9/common/vp9_postproc.h" #endif -/*#ifdef PACKET_TESTING*/ -#include "vp9/common/vp9_header.h" -/*#endif*/ - /* Create/destroy static data structures. */ void vp9_initialize_common(void); diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c index 70e0c87598..a4a8226a03 100644 --- a/vp9/decoder/vp9_decodframe.c +++ b/vp9/decoder/vp9_decodframe.c @@ -10,29 +10,30 @@ #include <assert.h> -#include "vp9/decoder/vp9_onyxd_int.h" +#include "./vp9_rtcd.h" +#include "vpx_mem/vpx_mem.h" +#include "vpx_scale/vpx_scale.h" + +#include "vp9/common/vp9_extend.h" +#include "vp9/common/vp9_modecont.h" #include "vp9/common/vp9_common.h" -#include "vp9/common/vp9_header.h" #include "vp9/common/vp9_reconintra.h" #include "vp9/common/vp9_reconinter.h" #include "vp9/common/vp9_entropy.h" -#include "vp9/decoder/vp9_decodframe.h" -#include "vp9/decoder/vp9_detokenize.h" #include "vp9/common/vp9_invtrans.h" #include "vp9/common/vp9_alloccommon.h" #include "vp9/common/vp9_entropymode.h" #include "vp9/common/vp9_quant_common.h" -#include "vpx_scale/vpx_scale.h" +#include "vp9/common/vp9_seg_common.h" +#include "vp9/common/vp9_tile_common.h" -#include "vp9/decoder/vp9_decodemv.h" -#include "vp9/common/vp9_extend.h" -#include "vp9/common/vp9_modecont.h" -#include "vpx_mem/vpx_mem.h" #include "vp9/decoder/vp9_dboolhuff.h" +#include "vp9/decoder/vp9_decodframe.h" +#include "vp9/decoder/vp9_detokenize.h" +#include "vp9/decoder/vp9_decodemv.h" +#include "vp9/decoder/vp9_onyxd_int.h" +#include "vp9/decoder/vp9_read_bit_buffer.h" -#include "vp9/common/vp9_seg_common.h" -#include "vp9/common/vp9_tile_common.h" -#include "./vp9_rtcd.h" // #define DEC_DEBUG #ifdef DEC_DEBUG @@ -743,32 +744,24 @@ static INTERPOLATIONFILTERTYPE read_mcomp_filter_type(vp9_reader *r) { : vp9_read_literal(r, 2); } -static const uint8_t *read_frame_size(VP9_COMMON *const pc, const uint8_t *data, - const uint8_t *data_end, - int *width, int *height) { - if (data + 4 < data_end) { - const int w = read_le16(data); - const int h = read_le16(data + 2); - if (w <= 0) - vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, - "Invalid frame width"); - - if (h <= 0) - vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, - "Invalid frame height"); - *width = w; - *height = h; - data += 4; - } else { - vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, - "Failed to read frame size"); - } - return data; +static void read_frame_size(VP9_COMMON *cm, + struct vp9_read_bit_buffer *rb, + int *width, int *height) { + const int w = vp9_rb_read_literal(rb, 16); + const int h = vp9_rb_read_literal(rb, 16); + if (w <= 0) + vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, + "Invalid frame width"); + + if (h <= 0) + vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, + "Invalid frame height"); + *width = w; + *height = h; } -static const uint8_t *setup_frame_size(VP9D_COMP *pbi, int scaling_active, - const uint8_t *data, - const uint8_t *data_end) { +static void setup_frame_size(VP9D_COMP *pbi, int scaling_active, + struct vp9_read_bit_buffer *rb) { // If error concealment is enabled we should only parse the new size // if we have enough data. Otherwise we will end up with the wrong size. VP9_COMMON *const pc = &pbi->common; @@ -778,9 +771,9 @@ static const uint8_t *setup_frame_size(VP9D_COMP *pbi, int scaling_active, int height = pc->height; if (scaling_active) - data = read_frame_size(pc, data, data_end, &display_width, &display_height); + read_frame_size(pc, rb, &display_width, &display_height); - data = read_frame_size(pc, data, data_end, &width, &height); + read_frame_size(pc, rb, &width, &height); if (pc->width != width || pc->height != height) { if (!pbi->initial_width || !pbi->initial_height) { @@ -806,8 +799,6 @@ static const uint8_t *setup_frame_size(VP9D_COMP *pbi, int scaling_active, vp9_update_frame_size(pc); } - - return data; } static void update_frame_context(FRAME_CONTEXT *fc) { @@ -937,59 +928,78 @@ static void decode_tiles(VP9D_COMP *pbi, } } -int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) { - vp9_reader header_bc, residual_bc; - VP9_COMMON *const pc = &pbi->common; - MACROBLOCKD *const xd = &pbi->mb; - const uint8_t *data = pbi->source; - const uint8_t *data_end = data + pbi->source_sz; - size_t first_partition_size = 0; - YV12_BUFFER_CONFIG *new_fb = &pc->yv12_fb[pc->new_fb_idx]; - int i; - xd->corrupted = 0; // start with no corruption of current frame - new_fb->corrupted = 0; +static void error_handler(void *data, int bit_offset) { + VP9_COMMON *const cm = (VP9_COMMON *)data; + vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, "Truncated packet"); +} + +size_t read_uncompressed_header(VP9D_COMP *pbi, + struct vp9_read_bit_buffer *rb) { + VP9_COMMON *const cm = &pbi->common; + + int scaling_active; + cm->last_frame_type = cm->frame_type; + cm->frame_type = (FRAME_TYPE) vp9_rb_read_bit(rb); + cm->version = vp9_rb_read_literal(rb, 3); + cm->show_frame = vp9_rb_read_bit(rb); + scaling_active = vp9_rb_read_bit(rb); + cm->subsampling_x = vp9_rb_read_bit(rb); + cm->subsampling_y = vp9_rb_read_bit(rb); + + if (cm->frame_type == KEY_FRAME) { + if (vp9_rb_read_literal(rb, 8) != SYNC_CODE_0 || + vp9_rb_read_literal(rb, 8) != SYNC_CODE_1 || + vp9_rb_read_literal(rb, 8) != SYNC_CODE_2) { + vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM, + "Invalid frame sync code"); + } + } + setup_frame_size(pbi, scaling_active, rb); - if (data_end - data < 3) { - vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, "Truncated packet"); + cm->frame_context_idx = vp9_rb_read_literal(rb, NUM_FRAME_CONTEXTS_LG2); + cm->clr_type = (YUV_TYPE)vp9_rb_read_bit(rb); + + cm->error_resilient_mode = vp9_rb_read_bit(rb); + if (!cm->error_resilient_mode) { + cm->refresh_frame_context = vp9_rb_read_bit(rb); + cm->frame_parallel_decoding_mode = vp9_rb_read_bit(rb); } else { - int scaling_active; - pc->last_frame_type = pc->frame_type; - pc->frame_type = (FRAME_TYPE)(data[0] & 1); - pc->version = (data[0] >> 1) & 7; - pc->show_frame = (data[0] >> 4) & 1; - scaling_active = (data[0] >> 5) & 1; - pc->subsampling_x = (data[0] >> 6) & 1; - pc->subsampling_y = (data[0] >> 7) & 1; - first_partition_size = read_le16(data + 1); - - if (!read_is_valid(data, first_partition_size, data_end)) - vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, - "Truncated packet or corrupt partition 0 length"); + cm->refresh_frame_context = 0; + cm->frame_parallel_decoding_mode = 1; + } - data += 3; + return vp9_rb_read_literal(rb, 16); +} - vp9_setup_version(pc); +int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) { + int i; + vp9_reader header_bc, residual_bc; + VP9_COMMON *const pc = &pbi->common; + MACROBLOCKD *const xd = &pbi->mb; + YV12_BUFFER_CONFIG *new_fb = &pc->yv12_fb[pc->new_fb_idx]; + const uint8_t *data = pbi->source; + const uint8_t *data_end = pbi->source + pbi->source_sz; - if (pc->frame_type == KEY_FRAME) { - // When error concealment is enabled we should only check the sync - // code if we have enough bits available - if (data + 3 < data_end) { - if (data[0] != 0x49 || data[1] != 0x83 || data[2] != 0x42) - vpx_internal_error(&pc->error, VPX_CODEC_UNSUP_BITSTREAM, - "Invalid frame sync code"); - } - data += 3; - } + struct vp9_read_bit_buffer rb = { data, data_end, 0, + pc, error_handler }; + const size_t first_partition_size = read_uncompressed_header(pbi, &rb); + const int keyframe = pc->frame_type == KEY_FRAME; - data = setup_frame_size(pbi, scaling_active, data, data_end); - } + data += vp9_rb_bytes_read(&rb); + xd->corrupted = 0; + new_fb->corrupted = 0; - if ((!pbi->decoded_key_frame && pc->frame_type != KEY_FRAME) || + if ((!pbi->decoded_key_frame && !keyframe) || pc->width == 0 || pc->height == 0) { return -1; } + vp9_setup_version(pc); + if (!read_is_valid(data, first_partition_size, data_end)) + vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, + "Truncated packet or corrupt partition 0 length"); + init_frame(pbi); // Reset the frame pointers to the current frame size @@ -1001,9 +1011,6 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) { vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR, "Failed to allocate bool decoder 0"); - pc->clr_type = (YUV_TYPE)vp9_read_bit(&header_bc); - pc->error_resilient_mode = vp9_read_bit(&header_bc); - setup_loopfilter(pc, xd, &header_bc); setup_quantization(pbi, &header_bc); @@ -1025,7 +1032,7 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) { // 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. - if (pc->frame_type == KEY_FRAME) { + if (keyframe) { for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) pc->active_ref_idx[i] = pc->new_fb_idx; } else { @@ -1050,15 +1057,6 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) { vp9_setup_interp_filters(xd, pc->mcomp_filter_type, pc); } - if (!pc->error_resilient_mode) { - pc->refresh_frame_context = vp9_read_bit(&header_bc); - pc->frame_parallel_decoding_mode = vp9_read_bit(&header_bc); - } else { - pc->refresh_frame_context = 0; - pc->frame_parallel_decoding_mode = 1; - } - - pc->frame_context_idx = vp9_read_literal(&header_bc, NUM_FRAME_CONTEXTS_LG2); pc->fc = pc->frame_contexts[pc->frame_context_idx]; setup_segmentation(pc, xd, &header_bc); @@ -1068,7 +1066,7 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) { setup_txfm_mode(pc, xd->lossless, &header_bc); // Read inter mode probability context updates - if (pc->frame_type != KEY_FRAME) { + if (!keyframe) { int i, j; for (i = 0; i < INTER_MODE_CONTEXTS; ++i) for (j = 0; j < 4; ++j) @@ -1076,7 +1074,7 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) { pc->fc.vp9_mode_contexts[i][j] = vp9_read_prob(&header_bc); } // Is this needed ? - if (pc->frame_type == KEY_FRAME) + if (keyframe) vp9_default_coef_probs(pc); update_frame_context(&pc->fc); @@ -1109,7 +1107,7 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) { new_fb->corrupted = vp9_reader_has_error(&header_bc) | xd->corrupted; if (!pbi->decoded_key_frame) { - if (pc->frame_type == KEY_FRAME && !new_fb->corrupted) + if (keyframe && !new_fb->corrupted) pbi->decoded_key_frame = 1; else vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, @@ -1120,7 +1118,7 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) { if (!pc->error_resilient_mode && !pc->frame_parallel_decoding_mode) { vp9_adapt_coef_probs(pc); - if (pc->frame_type != KEY_FRAME) { + if (!keyframe) { vp9_adapt_mode_probs(pc); vp9_adapt_mode_context(pc); vp9_adapt_nmv_probs(pc, xd->allow_high_precision_mv); diff --git a/vp9/decoder/vp9_read_bit_buffer.h b/vp9/decoder/vp9_read_bit_buffer.h new file mode 100644 index 0000000000..fa2dbee8d5 --- /dev/null +++ b/vp9/decoder/vp9_read_bit_buffer.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef VP9_READ_BIT_BUFFER_ +#define VP9_READ_BIT_BUFFER_ + +typedef void (*vp9_rb_error_handler)(void *data, int bit_offset); + +struct vp9_read_bit_buffer { + const uint8_t *bit_buffer; + const uint8_t *bit_buffer_end; + size_t bit_offset; + + void *error_handler_data; + vp9_rb_error_handler error_handler; +}; + +static size_t vp9_rb_bytes_read(struct vp9_read_bit_buffer *rb) { + return rb->bit_offset / CHAR_BIT + (rb->bit_offset % CHAR_BIT > 0); +} + +static int vp9_rb_read_bit(struct vp9_read_bit_buffer *rb) { + const int off = rb->bit_offset; + const int p = off / CHAR_BIT; + const int q = CHAR_BIT - 1 - off % CHAR_BIT; + if (rb->bit_buffer + p >= rb->bit_buffer_end) { + rb->error_handler(rb->error_handler_data, rb->bit_offset); + return 0; + } else { + const int bit = (rb->bit_buffer[p] & (1 << q)) >> q; + rb->bit_offset = off + 1; + return bit; + } +} + +static int vp9_rb_read_literal(struct vp9_read_bit_buffer *rb, int bits) { + int value = 0, bit; + for (bit = bits - 1; bit >= 0; bit--) + value |= vp9_rb_read_bit(rb) << bit; + return value; +} + +#endif // VP9_READ_BIT_BUFFER_ diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 15253406d9..b19bf3a331 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -12,26 +12,28 @@ #include <stdio.h> #include <limits.h> -#include "vp9/common/vp9_header.h" -#include "vp9/encoder/vp9_encodemv.h" +#include "vpx/vpx_encoder.h" +#include "vpx_mem/vpx_mem.h" + #include "vp9/common/vp9_entropymode.h" #include "vp9/common/vp9_entropymv.h" #include "vp9/common/vp9_findnearmv.h" #include "vp9/common/vp9_tile_common.h" -#include "vp9/encoder/vp9_mcomp.h" -#include "vp9/common/vp9_systemdependent.h" -#include "vp9/common/vp9_pragmas.h" -#include "vpx/vpx_encoder.h" -#include "vpx_mem/vpx_mem.h" -#include "vp9/encoder/vp9_bitstream.h" -#include "vp9/encoder/vp9_segmentation.h" - #include "vp9/common/vp9_seg_common.h" #include "vp9/common/vp9_pred_common.h" #include "vp9/common/vp9_entropy.h" #include "vp9/common/vp9_entropymv.h" #include "vp9/common/vp9_mvref_common.h" #include "vp9/common/vp9_treecoder.h" +#include "vp9/common/vp9_systemdependent.h" +#include "vp9/common/vp9_pragmas.h" + +#include "vp9/encoder/vp9_mcomp.h" +#include "vp9/encoder/vp9_encodemv.h" +#include "vp9/encoder/vp9_bitstream.h" +#include "vp9/encoder/vp9_segmentation.h" +#include "vp9/encoder/vp9_write_bit_buffer.h" + #if defined(SECTIONBITS_OUTPUT) unsigned __int64 Sectionbits[500]; @@ -1278,10 +1280,6 @@ static void update_coef_probs(VP9_COMP* const cpi, vp9_writer* const bc) { } } -#ifdef PACKET_TESTING -FILE *vpxlogc = 0; -#endif - static void decide_kf_ymode_entropy(VP9_COMP *cpi) { int mode_cost[MB_MODE_COUNT]; int bestcost = INT_MAX; @@ -1482,60 +1480,63 @@ static void encode_segmentation(VP9_COMP *cpi, vp9_writer *w) { } } -void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) { - int i; - VP9_HEADER oh; - VP9_COMMON *const pc = &cpi->common; - vp9_writer header_bc, residual_bc; - MACROBLOCKD *const xd = &cpi->mb.e_mbd; - int extra_bytes_packed = 0; - uint8_t *cx_data = dest; +void write_uncompressed_header(VP9_COMMON *cm, + struct vp9_write_bit_buffer *wb) { + const int scaling_active = cm->width != cm->display_width || + cm->height != cm->display_height; - oh.show_frame = (int) pc->show_frame; - oh.type = (int)pc->frame_type; - oh.version = pc->version; - oh.first_partition_length_in_bytes = 0; + vp9_wb_write_bit(wb, cm->frame_type); + vp9_wb_write_literal(wb, cm->version, 3); + vp9_wb_write_bit(wb, cm->show_frame); + vp9_wb_write_bit(wb, scaling_active); + vp9_wb_write_bit(wb, cm->subsampling_x); + vp9_wb_write_bit(wb, cm->subsampling_y); - cx_data += 3; + if (cm->frame_type == KEY_FRAME) { + vp9_wb_write_literal(wb, SYNC_CODE_0, 8); + vp9_wb_write_literal(wb, SYNC_CODE_1, 8); + vp9_wb_write_literal(wb, SYNC_CODE_2, 8); + } -#if defined(SECTIONBITS_OUTPUT) - Sectionbits[active_section = 1] += sizeof(VP9_HEADER) * 8 * 256; -#endif + if (scaling_active) { + vp9_wb_write_literal(wb, cm->display_width, 16); + vp9_wb_write_literal(wb, cm->display_height, 16); + } - compute_update_table(); + vp9_wb_write_literal(wb, cm->width, 16); + vp9_wb_write_literal(wb, cm->height, 16); - /* every keyframe send startcode, width, height, scale factor, clamp - * and color type. - */ - if (oh.type == KEY_FRAME) { - // Start / synch code - cx_data[0] = 0x49; - cx_data[1] = 0x83; - cx_data[2] = 0x42; - extra_bytes_packed = 3; - cx_data += extra_bytes_packed; - } + vp9_wb_write_literal(wb, cm->frame_context_idx, NUM_FRAME_CONTEXTS_LG2); + vp9_wb_write_bit(wb, cm->clr_type); - if (pc->width != pc->display_width || pc->height != pc->display_height) { - write_le16(cx_data, pc->display_width); - write_le16(cx_data + 2, pc->display_height); - cx_data += 4; - extra_bytes_packed += 4; + vp9_wb_write_bit(wb, cm->error_resilient_mode); + if (!cm->error_resilient_mode) { + vp9_wb_write_bit(wb, cm->refresh_frame_context); + vp9_wb_write_bit(wb, cm->frame_parallel_decoding_mode); } +} + +void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) { + int i, bytes_packed; + VP9_COMMON *const pc = &cpi->common; + vp9_writer header_bc, residual_bc; + MACROBLOCKD *const xd = &cpi->mb.e_mbd; - write_le16(cx_data, pc->width); - write_le16(cx_data + 2, pc->height); - extra_bytes_packed += 4; - cx_data += 4; + uint8_t *cx_data = dest; + struct vp9_write_bit_buffer wb = {dest, 0}; + struct vp9_write_bit_buffer first_partition_size_wb; - vp9_start_encode(&header_bc, cx_data); + write_uncompressed_header(pc, &wb); + first_partition_size_wb = wb; + vp9_wb_write_literal(&wb, 0, 16); // don't know in advance first part. size - // TODO(jkoleszar): remove these two unused bits? - vp9_write_bit(&header_bc, pc->clr_type); + bytes_packed = vp9_rb_bytes_written(&wb); + cx_data += bytes_packed; - // error resilient mode - vp9_write_bit(&header_bc, pc->error_resilient_mode); + compute_update_table(); + + vp9_start_encode(&header_bc, cx_data); encode_loopfilter(pc, xd, &header_bc); @@ -1617,14 +1618,6 @@ void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) { vp9_write_literal(&header_bc, (pc->mcomp_filter_type), 2); } - if (!pc->error_resilient_mode) { - vp9_write_bit(&header_bc, pc->refresh_frame_context); - vp9_write_bit(&header_bc, pc->frame_parallel_decoding_mode); - } - - vp9_write_literal(&header_bc, pc->frame_context_idx, - NUM_FRAME_CONTEXTS_LG2); - #ifdef ENTROPY_STATS if (pc->frame_type == INTER_FRAME) active_section = 0; @@ -1820,27 +1813,11 @@ void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) { vp9_stop_encode(&header_bc); - oh.first_partition_length_in_bytes = header_bc.pos; - - /* update frame tag */ - { - int scaling = (pc->width != pc->display_width || - pc->height != pc->display_height); - int v = (oh.first_partition_length_in_bytes << 8) | - (pc->subsampling_y << 7) | - (pc->subsampling_x << 6) | - (scaling << 5) | - (oh.show_frame << 4) | - (oh.version << 1) | - oh.type; - - assert(oh.first_partition_length_in_bytes <= 0xffff); - dest[0] = v; - dest[1] = v >> 8; - dest[2] = v >> 16; - } - *size = VP9_HEADER_SIZE + extra_bytes_packed + header_bc.pos; + // first partition size + assert(header_bc.pos <= 0xffff); + vp9_wb_write_literal(&first_partition_size_wb, header_bc.pos, 16); + *size = bytes_packed + header_bc.pos; if (pc->frame_type == KEY_FRAME) { decide_kf_ymode_entropy(cpi); diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index d42bcbb7e0..e2f24848f8 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -258,9 +258,6 @@ void vp9_initialize_enc() { init_done = 1; } } -#ifdef PACKET_TESTING -extern FILE *vpxlogc; -#endif static void setup_features(VP9_COMP *cpi) { MACROBLOCKD *xd = &cpi->mb.e_mbd; diff --git a/vp9/encoder/vp9_write_bit_buffer.h b/vp9/encoder/vp9_write_bit_buffer.h new file mode 100644 index 0000000000..18cf403669 --- /dev/null +++ b/vp9/encoder/vp9_write_bit_buffer.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef VP9_BIT_WRITE_BUFFER_H_ +#define VP9_BIT_WRITE_BUFFER_H_ + +#include "vpx/vpx_integer.h" + +struct vp9_write_bit_buffer { + uint8_t *bit_buffer; + size_t bit_offset; +}; + +static size_t vp9_rb_bytes_written(struct vp9_write_bit_buffer *wb) { + return wb->bit_offset / CHAR_BIT + (wb->bit_offset % CHAR_BIT > 0); +} + +static void vp9_wb_write_bit(struct vp9_write_bit_buffer *wb, int bit) { + const int off = wb->bit_offset; + const int p = off / CHAR_BIT; + const int q = CHAR_BIT - 1 - off % CHAR_BIT; + wb->bit_buffer[p] &= ~(1 << q); + wb->bit_buffer[p] |= bit << q; + wb->bit_offset = off + 1; +} + +static void vp9_wb_write_literal(struct vp9_write_bit_buffer *wb, + int data, int bits) { + int bit; + for (bit = bits - 1; bit >= 0; bit--) + vp9_wb_write_bit(wb, (data >> bit) & 1); +} + + +#endif // VP9_BIT_WRITE_BUFFER_H_ diff --git a/vp9/vp9_common.mk b/vp9/vp9_common.mk index 147804d033..732891449e 100644 --- a/vp9/vp9_common.mk +++ b/vp9/vp9_common.mk @@ -38,7 +38,6 @@ VP9_COMMON_SRCS-yes += common/vp9_entropymv.h VP9_COMMON_SRCS-yes += common/vp9_enums.h VP9_COMMON_SRCS-yes += common/vp9_extend.h VP9_COMMON_SRCS-yes += common/vp9_findnearmv.h -VP9_COMMON_SRCS-yes += common/vp9_header.h VP9_COMMON_SRCS-yes += common/vp9_idct.h VP9_COMMON_SRCS-yes += common/vp9_invtrans.h VP9_COMMON_SRCS-yes += common/vp9_loopfilter.h diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c index ee11304029..b5aa10d522 100644 --- a/vp9/vp9_dx_iface.c +++ b/vp9/vp9_dx_iface.c @@ -215,26 +215,19 @@ static vpx_codec_err_t vp8_peek_si(const uint8_t *data, if (data + data_sz <= data) res = VPX_CODEC_INVALID_PARAM; else { - /* Parse uncompresssed part of key frame header. - * 3 bytes:- including version, frame type and an offset - * 3 bytes:- sync code (0x49, 0x83, 0x42) - * 4 bytes:- including image width and height in the lowest 14 bits - * of each 2-byte value. - */ si->is_kf = 0; - if (data_sz >= 10 && !(data[0] & 0x01)) { /* I-Frame */ - const uint8_t *c = data + 3; + if (data_sz >= 8 && !(data[0] & 0x80)) { /* I-Frame */ + const uint8_t *c = data + 1; si->is_kf = 1; - /* vet via sync code */ - if (c[0] != 0x49 || c[1] != 0x83 || c[2] != 0x42) + if (c[0] != SYNC_CODE_0 || c[1] != SYNC_CODE_1 || c[2] != SYNC_CODE_2) res = VPX_CODEC_UNSUP_BITSTREAM; - si->w = (c[3] | (c[4] << 8)); - si->h = (c[5] | (c[6] << 8)); + si->w = (c[3] << 8) | c[4]; + si->h = (c[5] << 8) | c[6]; - /*printf("w=%d, h=%d\n", si->w, si->h);*/ + // printf("w=%d, h=%d\n", si->w, si->h); if (!(si->h | si->w)) res = VPX_CODEC_UNSUP_BITSTREAM; } else @@ -242,7 +235,6 @@ static vpx_codec_err_t vp8_peek_si(const uint8_t *data, } return res; - } static vpx_codec_err_t vp8_get_si(vpx_codec_alg_priv_t *ctx, diff --git a/vp9/vp9cx.mk b/vp9/vp9cx.mk index 42ab02d31a..86fd088508 100644 --- a/vp9/vp9cx.mk +++ b/vp9/vp9cx.mk @@ -28,6 +28,7 @@ VP9_CX_SRCS-yes += encoder/vp9_encodemv.c VP9_CX_SRCS-yes += encoder/vp9_firstpass.c VP9_CX_SRCS-yes += encoder/vp9_block.h VP9_CX_SRCS-yes += encoder/vp9_boolhuff.h +VP9_CX_SRCS-yes += encoder/vp9_write_bit_buffer.h VP9_CX_SRCS-yes += encoder/vp9_bitstream.h VP9_CX_SRCS-yes += encoder/vp9_encodeintra.h VP9_CX_SRCS-yes += encoder/vp9_encodemb.h diff --git a/vp9/vp9dx.mk b/vp9/vp9dx.mk index 3be0b6dde6..7ae3219ca2 100644 --- a/vp9/vp9dx.mk +++ b/vp9/vp9dx.mk @@ -24,6 +24,7 @@ VP9_DX_SRCS-yes += decoder/vp9_decodframe.c VP9_DX_SRCS-yes += decoder/vp9_decodframe.h VP9_DX_SRCS-yes += decoder/vp9_detokenize.c VP9_DX_SRCS-yes += decoder/vp9_dboolhuff.h +VP9_DX_SRCS-yes += decoder/vp9_read_bit_buffer.h VP9_DX_SRCS-yes += decoder/vp9_decodemv.h VP9_DX_SRCS-yes += decoder/vp9_detokenize.h VP9_DX_SRCS-yes += decoder/vp9_onyxd.h -- GitLab