mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-09 00:37:32 +09:00
Import aom library
This is the reference implementation for the Alliance for Open Media's av1 video code. The commit used was 4d668d7feb1f8abd809d1bca0418570a7f142a36.
This commit is contained in:
parent
eb8cd130a8
commit
edc8d83307
989 changed files with 470949 additions and 0 deletions
138
third_party/aom/av1/decoder/accounting.c
vendored
Normal file
138
third_party/aom/av1/decoder/accounting.c
vendored
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "aom/aom_integer.h"
|
||||
#include "./accounting.h"
|
||||
|
||||
static int aom_accounting_hash(const char *str) {
|
||||
uint32_t val;
|
||||
const unsigned char *ustr;
|
||||
val = 0;
|
||||
ustr = (const unsigned char *)str;
|
||||
/* This is about the worst hash one can design, but it should be good enough
|
||||
here. */
|
||||
while (*ustr) val += *ustr++;
|
||||
return val % AOM_ACCOUNTING_HASH_SIZE;
|
||||
}
|
||||
|
||||
/* Dictionary lookup based on an open-addressing hash table. */
|
||||
int aom_accounting_dictionary_lookup(Accounting *accounting, const char *str) {
|
||||
int hash;
|
||||
int len;
|
||||
AccountingDictionary *dictionary;
|
||||
dictionary = &accounting->syms.dictionary;
|
||||
hash = aom_accounting_hash(str);
|
||||
while (accounting->hash_dictionary[hash] != -1) {
|
||||
if (strcmp(dictionary->strs[accounting->hash_dictionary[hash]], str) == 0) {
|
||||
return accounting->hash_dictionary[hash];
|
||||
}
|
||||
hash++;
|
||||
if (hash == AOM_ACCOUNTING_HASH_SIZE) hash = 0;
|
||||
}
|
||||
/* No match found. */
|
||||
assert(dictionary->num_strs + 1 < MAX_SYMBOL_TYPES);
|
||||
accounting->hash_dictionary[hash] = dictionary->num_strs;
|
||||
len = strlen(str);
|
||||
dictionary->strs[dictionary->num_strs] = malloc(len + 1);
|
||||
snprintf(dictionary->strs[dictionary->num_strs], len + 1, "%s", str);
|
||||
dictionary->num_strs++;
|
||||
return dictionary->num_strs - 1;
|
||||
}
|
||||
|
||||
void aom_accounting_init(Accounting *accounting) {
|
||||
int i;
|
||||
accounting->num_syms_allocated = 1000;
|
||||
accounting->syms.syms =
|
||||
malloc(sizeof(AccountingSymbol) * accounting->num_syms_allocated);
|
||||
accounting->syms.dictionary.num_strs = 0;
|
||||
assert(AOM_ACCOUNTING_HASH_SIZE > 2 * MAX_SYMBOL_TYPES);
|
||||
for (i = 0; i < AOM_ACCOUNTING_HASH_SIZE; i++)
|
||||
accounting->hash_dictionary[i] = -1;
|
||||
aom_accounting_reset(accounting);
|
||||
}
|
||||
|
||||
void aom_accounting_reset(Accounting *accounting) {
|
||||
accounting->syms.num_syms = 0;
|
||||
accounting->syms.num_binary_syms = 0;
|
||||
accounting->syms.num_multi_syms = 0;
|
||||
accounting->context.x = -1;
|
||||
accounting->context.y = -1;
|
||||
accounting->last_tell_frac = 0;
|
||||
}
|
||||
|
||||
void aom_accounting_clear(Accounting *accounting) {
|
||||
int i;
|
||||
AccountingDictionary *dictionary;
|
||||
free(accounting->syms.syms);
|
||||
dictionary = &accounting->syms.dictionary;
|
||||
for (i = 0; i < dictionary->num_strs; i++) {
|
||||
free(dictionary->strs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void aom_accounting_set_context(Accounting *accounting, int16_t x, int16_t y) {
|
||||
accounting->context.x = x;
|
||||
accounting->context.y = y;
|
||||
}
|
||||
|
||||
void aom_accounting_record(Accounting *accounting, const char *str,
|
||||
uint32_t bits) {
|
||||
AccountingSymbol sym;
|
||||
// Reuse previous symbol if it has the same context and symbol id.
|
||||
if (accounting->syms.num_syms) {
|
||||
AccountingSymbol *last_sym;
|
||||
last_sym = &accounting->syms.syms[accounting->syms.num_syms - 1];
|
||||
if (memcmp(&last_sym->context, &accounting->context,
|
||||
sizeof(AccountingSymbolContext)) == 0) {
|
||||
uint32_t id;
|
||||
id = aom_accounting_dictionary_lookup(accounting, str);
|
||||
if (id == last_sym->id) {
|
||||
last_sym->bits += bits;
|
||||
last_sym->samples++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
sym.context = accounting->context;
|
||||
sym.samples = 1;
|
||||
sym.bits = bits;
|
||||
sym.id = aom_accounting_dictionary_lookup(accounting, str);
|
||||
assert(sym.id <= 255);
|
||||
if (accounting->syms.num_syms == accounting->num_syms_allocated) {
|
||||
accounting->num_syms_allocated *= 2;
|
||||
accounting->syms.syms =
|
||||
realloc(accounting->syms.syms,
|
||||
sizeof(AccountingSymbol) * accounting->num_syms_allocated);
|
||||
assert(accounting->syms.syms != NULL);
|
||||
}
|
||||
accounting->syms.syms[accounting->syms.num_syms++] = sym;
|
||||
}
|
||||
|
||||
void aom_accounting_dump(Accounting *accounting) {
|
||||
int i;
|
||||
AccountingSymbol *sym;
|
||||
printf("\n----- Number of recorded syntax elements = %d -----\n",
|
||||
accounting->syms.num_syms);
|
||||
printf("----- Total number of symbol calls = %d (%d binary) -----\n",
|
||||
accounting->syms.num_multi_syms + accounting->syms.num_binary_syms,
|
||||
accounting->syms.num_binary_syms);
|
||||
for (i = 0; i < accounting->syms.num_syms; i++) {
|
||||
sym = &accounting->syms.syms[i];
|
||||
printf("%s x: %d, y: %d bits: %f samples: %d\n",
|
||||
accounting->syms.dictionary.strs[sym->id], sym->context.x,
|
||||
sym->context.y, (float)sym->bits / 8.0, sym->samples);
|
||||
}
|
||||
}
|
||||
83
third_party/aom/av1/decoder/accounting.h
vendored
Normal file
83
third_party/aom/av1/decoder/accounting.h
vendored
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
#ifndef AOM_ACCOUNTING_H_
|
||||
#define AOM_ACCOUNTING_H_
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#define AOM_ACCOUNTING_HASH_SIZE (1021)
|
||||
|
||||
/* Max number of entries for symbol types in the dictionary (increase as
|
||||
necessary). */
|
||||
#define MAX_SYMBOL_TYPES (256)
|
||||
|
||||
/*The resolution of fractional-precision bit usage measurements, i.e.,
|
||||
3 => 1/8th bits.*/
|
||||
#define AOM_ACCT_BITRES (3)
|
||||
|
||||
typedef struct {
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
} AccountingSymbolContext;
|
||||
|
||||
typedef struct {
|
||||
AccountingSymbolContext context;
|
||||
uint32_t id;
|
||||
/** Number of bits in units of 1/8 bit. */
|
||||
uint32_t bits;
|
||||
uint32_t samples;
|
||||
} AccountingSymbol;
|
||||
|
||||
/** Dictionary for translating strings into id. */
|
||||
typedef struct {
|
||||
char *(strs[MAX_SYMBOL_TYPES]);
|
||||
int num_strs;
|
||||
} AccountingDictionary;
|
||||
|
||||
typedef struct {
|
||||
/** All recorded symbols decoded. */
|
||||
AccountingSymbol *syms;
|
||||
/** Number of syntax actually recorded. */
|
||||
int num_syms;
|
||||
/** Raw symbol decoding calls for non-binary values. */
|
||||
int num_multi_syms;
|
||||
/** Raw binary symbol decoding calls. */
|
||||
int num_binary_syms;
|
||||
/** Dictionary for translating strings into id. */
|
||||
AccountingDictionary dictionary;
|
||||
} AccountingSymbols;
|
||||
|
||||
typedef struct Accounting Accounting;
|
||||
|
||||
struct Accounting {
|
||||
AccountingSymbols syms;
|
||||
/** Size allocated for symbols (not all may be used). */
|
||||
int num_syms_allocated;
|
||||
int16_t hash_dictionary[AOM_ACCOUNTING_HASH_SIZE];
|
||||
AccountingSymbolContext context;
|
||||
uint32_t last_tell_frac;
|
||||
};
|
||||
|
||||
void aom_accounting_init(Accounting *accounting);
|
||||
void aom_accounting_reset(Accounting *accounting);
|
||||
void aom_accounting_clear(Accounting *accounting);
|
||||
void aom_accounting_set_context(Accounting *accounting, int16_t x, int16_t y);
|
||||
int aom_accounting_dictionary_lookup(Accounting *accounting, const char *str);
|
||||
void aom_accounting_record(Accounting *accounting, const char *str,
|
||||
uint32_t bits);
|
||||
void aom_accounting_dump(Accounting *accounting);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
#endif // AOM_ACCOUNTING_H_
|
||||
35
third_party/aom/av1/decoder/decint.h
vendored
Normal file
35
third_party/aom/av1/decoder/decint.h
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#if !defined(_decint_H)
|
||||
# define _decint_H (1)
|
||||
# include "av1/common/pvq_state.h"
|
||||
# include "aom_dsp/bitreader.h"
|
||||
# include "aom_dsp/entdec.h"
|
||||
|
||||
typedef struct daala_dec_ctx daala_dec_ctx;
|
||||
|
||||
typedef struct daala_dec_ctx od_dec_ctx;
|
||||
|
||||
|
||||
struct daala_dec_ctx {
|
||||
/* Stores context-adaptive CDFs for PVQ. */
|
||||
od_state state;
|
||||
/* AOM entropy decoder. */
|
||||
aom_reader *r;
|
||||
int use_activity_masking;
|
||||
/* Mode of quantization matrice : FLAT (0) or HVS (1) */
|
||||
int qm;
|
||||
};
|
||||
|
||||
#endif
|
||||
5159
third_party/aom/av1/decoder/decodeframe.c
vendored
Normal file
5159
third_party/aom/av1/decoder/decodeframe.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
39
third_party/aom/av1/decoder/decodeframe.h
vendored
Normal file
39
third_party/aom/av1/decoder/decodeframe.h
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AV1_DECODER_DECODEFRAME_H_
|
||||
#define AV1_DECODER_DECODEFRAME_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct AV1Decoder;
|
||||
struct aom_read_bit_buffer;
|
||||
|
||||
#if CONFIG_REFERENCE_BUFFER
|
||||
/* Placeholder for now */
|
||||
void read_sequence_header(SequenceHeader *seq_params);
|
||||
#endif
|
||||
|
||||
int av1_read_sync_code(struct aom_read_bit_buffer *const rb);
|
||||
void av1_read_frame_size(struct aom_read_bit_buffer *rb, int *width,
|
||||
int *height);
|
||||
BITSTREAM_PROFILE av1_read_profile(struct aom_read_bit_buffer *rb);
|
||||
|
||||
void av1_decode_frame(struct AV1Decoder *pbi, const uint8_t *data,
|
||||
const uint8_t *data_end, const uint8_t **p_data_end);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // AV1_DECODER_DECODEFRAME_H_
|
||||
2405
third_party/aom/av1/decoder/decodemv.c
vendored
Normal file
2405
third_party/aom/av1/decoder/decodemv.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
44
third_party/aom/av1/decoder/decodemv.h
vendored
Normal file
44
third_party/aom/av1/decoder/decodemv.h
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AV1_DECODER_DECODEMV_H_
|
||||
#define AV1_DECODER_DECODEMV_H_
|
||||
|
||||
#include "aom_dsp/bitreader.h"
|
||||
|
||||
#include "av1/decoder/decoder.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void av1_read_mode_info(AV1Decoder *const pbi, MACROBLOCKD *xd,
|
||||
#if CONFIG_SUPERTX
|
||||
int supertx_enabled,
|
||||
#endif
|
||||
|
||||
int mi_row, int mi_col, aom_reader *r, int x_mis,
|
||||
int y_mis);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
void av1_read_tx_type(const AV1_COMMON *const cm, MACROBLOCKD *xd,
|
||||
#if CONFIG_SUPERTX
|
||||
int supertx_enabled,
|
||||
#endif
|
||||
#if CONFIG_TXK_SEL
|
||||
int block, int plane,
|
||||
#endif
|
||||
aom_reader *r);
|
||||
|
||||
#endif // AV1_DECODER_DECODEMV_H_
|
||||
583
third_party/aom/av1/decoder/decoder.c
vendored
Normal file
583
third_party/aom/av1/decoder/decoder.c
vendored
Normal file
|
|
@ -0,0 +1,583 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "./av1_rtcd.h"
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
#include "./aom_scale_rtcd.h"
|
||||
|
||||
#include "aom_mem/aom_mem.h"
|
||||
#include "aom_ports/system_state.h"
|
||||
#include "aom_ports/aom_once.h"
|
||||
#include "aom_ports/aom_timer.h"
|
||||
#include "aom_scale/aom_scale.h"
|
||||
#include "aom_util/aom_thread.h"
|
||||
|
||||
#include "av1/common/alloccommon.h"
|
||||
#include "av1/common/av1_loopfilter.h"
|
||||
#include "av1/common/onyxc_int.h"
|
||||
#include "av1/common/quant_common.h"
|
||||
#include "av1/common/reconinter.h"
|
||||
#include "av1/common/reconintra.h"
|
||||
|
||||
#include "av1/decoder/decodeframe.h"
|
||||
#include "av1/decoder/decoder.h"
|
||||
|
||||
#if !CONFIG_PVQ
|
||||
#include "av1/decoder/detokenize.h"
|
||||
#endif
|
||||
|
||||
static void initialize_dec(void) {
|
||||
static volatile int init_done = 0;
|
||||
|
||||
if (!init_done) {
|
||||
av1_rtcd();
|
||||
aom_dsp_rtcd();
|
||||
aom_scale_rtcd();
|
||||
av1_init_intra_predictors();
|
||||
#if CONFIG_EXT_INTER
|
||||
av1_init_wedge_masks();
|
||||
#endif // CONFIG_EXT_INTER
|
||||
init_done = 1;
|
||||
#if CONFIG_EC_MULTISYMBOL
|
||||
av1_indices_from_tree(av1_intra_mode_ind, av1_intra_mode_inv,
|
||||
av1_intra_mode_tree);
|
||||
av1_indices_from_tree(av1_switchable_interp_ind, av1_switchable_interp_inv,
|
||||
av1_switchable_interp_tree);
|
||||
#if CONFIG_EXT_TX
|
||||
int s;
|
||||
for (s = 1; s < EXT_TX_SETS_INTRA; ++s)
|
||||
av1_indices_from_tree(av1_ext_tx_intra_ind[s], av1_ext_tx_intra_inv[s],
|
||||
av1_ext_tx_intra_tree[s]);
|
||||
for (s = 1; s < EXT_TX_SETS_INTER; ++s)
|
||||
av1_indices_from_tree(av1_ext_tx_inter_ind[s], av1_ext_tx_inter_inv[s],
|
||||
av1_ext_tx_inter_tree[s]);
|
||||
#else
|
||||
av1_indices_from_tree(av1_ext_tx_ind, av1_ext_tx_inv, av1_ext_tx_tree);
|
||||
#endif
|
||||
av1_indices_from_tree(av1_inter_mode_ind, av1_inter_mode_inv,
|
||||
av1_inter_mode_tree);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void av1_dec_setup_mi(AV1_COMMON *cm) {
|
||||
cm->mi = cm->mip + cm->mi_stride + 1;
|
||||
cm->mi_grid_visible = cm->mi_grid_base + cm->mi_stride + 1;
|
||||
memset(cm->mi_grid_base, 0,
|
||||
cm->mi_stride * (cm->mi_rows + 1) * sizeof(*cm->mi_grid_base));
|
||||
}
|
||||
|
||||
static int av1_dec_alloc_mi(AV1_COMMON *cm, int mi_size) {
|
||||
cm->mip = aom_calloc(mi_size, sizeof(*cm->mip));
|
||||
if (!cm->mip) return 1;
|
||||
cm->mi_alloc_size = mi_size;
|
||||
cm->mi_grid_base = (MODE_INFO **)aom_calloc(mi_size, sizeof(MODE_INFO *));
|
||||
if (!cm->mi_grid_base) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void av1_dec_free_mi(AV1_COMMON *cm) {
|
||||
aom_free(cm->mip);
|
||||
cm->mip = NULL;
|
||||
aom_free(cm->mi_grid_base);
|
||||
cm->mi_grid_base = NULL;
|
||||
}
|
||||
|
||||
AV1Decoder *av1_decoder_create(BufferPool *const pool) {
|
||||
AV1Decoder *volatile const pbi = aom_memalign(32, sizeof(*pbi));
|
||||
AV1_COMMON *volatile const cm = pbi ? &pbi->common : NULL;
|
||||
|
||||
if (!cm) return NULL;
|
||||
|
||||
av1_zero(*pbi);
|
||||
|
||||
if (setjmp(cm->error.jmp)) {
|
||||
cm->error.setjmp = 0;
|
||||
av1_decoder_remove(pbi);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cm->error.setjmp = 1;
|
||||
|
||||
CHECK_MEM_ERROR(cm, cm->fc,
|
||||
(FRAME_CONTEXT *)aom_memalign(32, sizeof(*cm->fc)));
|
||||
CHECK_MEM_ERROR(cm, cm->frame_contexts,
|
||||
(FRAME_CONTEXT *)aom_memalign(
|
||||
32, FRAME_CONTEXTS * sizeof(*cm->frame_contexts)));
|
||||
memset(cm->fc, 0, sizeof(*cm->fc));
|
||||
memset(cm->frame_contexts, 0, FRAME_CONTEXTS * sizeof(*cm->frame_contexts));
|
||||
|
||||
pbi->need_resync = 1;
|
||||
once(initialize_dec);
|
||||
|
||||
// Initialize the references to not point to any frame buffers.
|
||||
memset(&cm->ref_frame_map, -1, sizeof(cm->ref_frame_map));
|
||||
memset(&cm->next_ref_frame_map, -1, sizeof(cm->next_ref_frame_map));
|
||||
|
||||
cm->current_video_frame = 0;
|
||||
pbi->ready_for_new_data = 1;
|
||||
pbi->common.buffer_pool = pool;
|
||||
|
||||
cm->bit_depth = AOM_BITS_8;
|
||||
cm->dequant_bit_depth = AOM_BITS_8;
|
||||
|
||||
cm->alloc_mi = av1_dec_alloc_mi;
|
||||
cm->free_mi = av1_dec_free_mi;
|
||||
cm->setup_mi = av1_dec_setup_mi;
|
||||
|
||||
av1_loop_filter_init(cm);
|
||||
|
||||
#if CONFIG_AOM_QM
|
||||
aom_qm_init(cm);
|
||||
#endif
|
||||
#if CONFIG_LOOP_RESTORATION
|
||||
av1_loop_restoration_precal();
|
||||
#endif // CONFIG_LOOP_RESTORATION
|
||||
#if CONFIG_ACCOUNTING
|
||||
pbi->acct_enabled = 1;
|
||||
aom_accounting_init(&pbi->accounting);
|
||||
#endif
|
||||
|
||||
cm->error.setjmp = 0;
|
||||
|
||||
aom_get_worker_interface()->init(&pbi->lf_worker);
|
||||
|
||||
return pbi;
|
||||
}
|
||||
|
||||
void av1_decoder_remove(AV1Decoder *pbi) {
|
||||
int i;
|
||||
|
||||
if (!pbi) return;
|
||||
|
||||
aom_get_worker_interface()->end(&pbi->lf_worker);
|
||||
aom_free(pbi->lf_worker.data1);
|
||||
aom_free(pbi->tile_data);
|
||||
for (i = 0; i < pbi->num_tile_workers; ++i) {
|
||||
AVxWorker *const worker = &pbi->tile_workers[i];
|
||||
aom_get_worker_interface()->end(worker);
|
||||
}
|
||||
aom_free(pbi->tile_worker_data);
|
||||
aom_free(pbi->tile_worker_info);
|
||||
aom_free(pbi->tile_workers);
|
||||
|
||||
if (pbi->num_tile_workers > 0) {
|
||||
av1_loop_filter_dealloc(&pbi->lf_row_sync);
|
||||
}
|
||||
|
||||
#if CONFIG_ACCOUNTING
|
||||
aom_accounting_clear(&pbi->accounting);
|
||||
#endif
|
||||
|
||||
aom_free(pbi);
|
||||
}
|
||||
|
||||
static int equal_dimensions(const YV12_BUFFER_CONFIG *a,
|
||||
const YV12_BUFFER_CONFIG *b) {
|
||||
return a->y_height == b->y_height && a->y_width == b->y_width &&
|
||||
a->uv_height == b->uv_height && a->uv_width == b->uv_width;
|
||||
}
|
||||
|
||||
aom_codec_err_t av1_copy_reference_dec(AV1Decoder *pbi,
|
||||
AOM_REFFRAME ref_frame_flag,
|
||||
YV12_BUFFER_CONFIG *sd) {
|
||||
AV1_COMMON *cm = &pbi->common;
|
||||
|
||||
/* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
|
||||
* encoder is using the frame buffers for. This is just a stub to keep the
|
||||
* aomenc --test-decode functionality working, and will be replaced in a
|
||||
* later commit that adds AV1-specific controls for this functionality.
|
||||
*/
|
||||
if (ref_frame_flag == AOM_LAST_FLAG) {
|
||||
const YV12_BUFFER_CONFIG *const cfg = get_ref_frame(cm, 0);
|
||||
if (cfg == NULL) {
|
||||
aom_internal_error(&cm->error, AOM_CODEC_ERROR,
|
||||
"No 'last' reference frame");
|
||||
return AOM_CODEC_ERROR;
|
||||
}
|
||||
if (!equal_dimensions(cfg, sd))
|
||||
aom_internal_error(&cm->error, AOM_CODEC_ERROR,
|
||||
"Incorrect buffer dimensions");
|
||||
else
|
||||
aom_yv12_copy_frame(cfg, sd);
|
||||
} else {
|
||||
aom_internal_error(&cm->error, AOM_CODEC_ERROR, "Invalid reference frame");
|
||||
}
|
||||
|
||||
return cm->error.error_code;
|
||||
}
|
||||
|
||||
aom_codec_err_t av1_set_reference_dec(AV1_COMMON *cm,
|
||||
AOM_REFFRAME ref_frame_flag,
|
||||
YV12_BUFFER_CONFIG *sd) {
|
||||
int idx;
|
||||
YV12_BUFFER_CONFIG *ref_buf = NULL;
|
||||
|
||||
// TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
|
||||
// encoder is using the frame buffers for. This is just a stub to keep the
|
||||
// aomenc --test-decode functionality working, and will be replaced in a
|
||||
// later commit that adds AV1-specific controls for this functionality.
|
||||
|
||||
// (Yunqing) The set_reference control depends on the following setting in
|
||||
// encoder.
|
||||
// cpi->lst_fb_idx = 0;
|
||||
// #if CONFIG_EXT_REFS
|
||||
// cpi->lst2_fb_idx = 1;
|
||||
// cpi->lst3_fb_idx = 2;
|
||||
// cpi->gld_fb_idx = 3;
|
||||
// cpi->bwd_fb_idx = 4;
|
||||
// cpi->alt_fb_idx = 5;
|
||||
// #else // CONFIG_EXT_REFS
|
||||
// cpi->gld_fb_idx = 1;
|
||||
// cpi->alt_fb_idx = 2;
|
||||
// #endif // CONFIG_EXT_REFS
|
||||
|
||||
// TODO(zoeliu): To revisit following code and reconsider what assumption we
|
||||
// may take on the reference frame buffer virtual indexes
|
||||
if (ref_frame_flag == AOM_LAST_FLAG) {
|
||||
idx = cm->ref_frame_map[0];
|
||||
#if CONFIG_EXT_REFS
|
||||
} else if (ref_frame_flag == AOM_LAST2_FLAG) {
|
||||
idx = cm->ref_frame_map[1];
|
||||
} else if (ref_frame_flag == AOM_LAST3_FLAG) {
|
||||
idx = cm->ref_frame_map[2];
|
||||
} else if (ref_frame_flag == AOM_GOLD_FLAG) {
|
||||
idx = cm->ref_frame_map[3];
|
||||
} else if (ref_frame_flag == AOM_BWD_FLAG) {
|
||||
idx = cm->ref_frame_map[4];
|
||||
} else if (ref_frame_flag == AOM_ALT_FLAG) {
|
||||
idx = cm->ref_frame_map[5];
|
||||
#else
|
||||
} else if (ref_frame_flag == AOM_GOLD_FLAG) {
|
||||
idx = cm->ref_frame_map[1];
|
||||
} else if (ref_frame_flag == AOM_ALT_FLAG) {
|
||||
idx = cm->ref_frame_map[2];
|
||||
#endif // CONFIG_EXT_REFS
|
||||
} else {
|
||||
aom_internal_error(&cm->error, AOM_CODEC_ERROR, "Invalid reference frame");
|
||||
return cm->error.error_code;
|
||||
}
|
||||
|
||||
if (idx < 0 || idx >= FRAME_BUFFERS) {
|
||||
aom_internal_error(&cm->error, AOM_CODEC_ERROR,
|
||||
"Invalid reference frame map");
|
||||
return cm->error.error_code;
|
||||
}
|
||||
|
||||
// Get the destination reference buffer.
|
||||
ref_buf = &cm->buffer_pool->frame_bufs[idx].buf;
|
||||
|
||||
if (!equal_dimensions(ref_buf, sd)) {
|
||||
aom_internal_error(&cm->error, AOM_CODEC_ERROR,
|
||||
"Incorrect buffer dimensions");
|
||||
} else {
|
||||
// Overwrite the reference frame buffer.
|
||||
aom_yv12_copy_frame(sd, ref_buf);
|
||||
}
|
||||
|
||||
return cm->error.error_code;
|
||||
}
|
||||
|
||||
/* If any buffer updating is signaled it should be done here. */
|
||||
static void swap_frame_buffers(AV1Decoder *pbi) {
|
||||
int ref_index = 0, mask;
|
||||
AV1_COMMON *const cm = &pbi->common;
|
||||
BufferPool *const pool = cm->buffer_pool;
|
||||
RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
|
||||
|
||||
lock_buffer_pool(pool);
|
||||
for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
|
||||
const int old_idx = cm->ref_frame_map[ref_index];
|
||||
// Current thread releases the holding of reference frame.
|
||||
decrease_ref_count(old_idx, frame_bufs, pool);
|
||||
|
||||
// Release the reference frame holding in the reference map for the decoding
|
||||
// of the next frame.
|
||||
if (mask & 1) decrease_ref_count(old_idx, frame_bufs, pool);
|
||||
cm->ref_frame_map[ref_index] = cm->next_ref_frame_map[ref_index];
|
||||
++ref_index;
|
||||
}
|
||||
|
||||
// Current thread releases the holding of reference frame.
|
||||
for (; ref_index < REF_FRAMES && !cm->show_existing_frame; ++ref_index) {
|
||||
const int old_idx = cm->ref_frame_map[ref_index];
|
||||
decrease_ref_count(old_idx, frame_bufs, pool);
|
||||
cm->ref_frame_map[ref_index] = cm->next_ref_frame_map[ref_index];
|
||||
}
|
||||
|
||||
unlock_buffer_pool(pool);
|
||||
pbi->hold_ref_buf = 0;
|
||||
cm->frame_to_show = get_frame_new_buffer(cm);
|
||||
|
||||
// TODO(zoeliu): To fix the ref frame buffer update for the scenario of
|
||||
// cm->frame_parellel_decode == 1
|
||||
if (!cm->frame_parallel_decode || !cm->show_frame) {
|
||||
lock_buffer_pool(pool);
|
||||
--frame_bufs[cm->new_fb_idx].ref_count;
|
||||
unlock_buffer_pool(pool);
|
||||
}
|
||||
|
||||
// Invalidate these references until the next frame starts.
|
||||
for (ref_index = 0; ref_index < INTER_REFS_PER_FRAME; ref_index++) {
|
||||
cm->frame_refs[ref_index].idx = INVALID_IDX;
|
||||
cm->frame_refs[ref_index].buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int av1_receive_compressed_data(AV1Decoder *pbi, size_t size,
|
||||
const uint8_t **psource) {
|
||||
AV1_COMMON *volatile const cm = &pbi->common;
|
||||
BufferPool *volatile const pool = cm->buffer_pool;
|
||||
RefCntBuffer *volatile const frame_bufs = cm->buffer_pool->frame_bufs;
|
||||
const uint8_t *source = *psource;
|
||||
int retcode = 0;
|
||||
cm->error.error_code = AOM_CODEC_OK;
|
||||
|
||||
if (size == 0) {
|
||||
// This is used to signal that we are missing frames.
|
||||
// We do not know if the missing frame(s) was supposed to update
|
||||
// any of the reference buffers, but we act conservative and
|
||||
// mark only the last buffer as corrupted.
|
||||
//
|
||||
// TODO(jkoleszar): Error concealment is undefined and non-normative
|
||||
// at this point, but if it becomes so, [0] may not always be the correct
|
||||
// thing to do here.
|
||||
if (cm->frame_refs[0].idx > 0) {
|
||||
assert(cm->frame_refs[0].buf != NULL);
|
||||
cm->frame_refs[0].buf->corrupted = 1;
|
||||
}
|
||||
}
|
||||
|
||||
pbi->ready_for_new_data = 0;
|
||||
|
||||
// Find a free buffer for the new frame, releasing the reference previously
|
||||
// held.
|
||||
|
||||
// Check if the previous frame was a frame without any references to it.
|
||||
// Release frame buffer if not decoding in frame parallel mode.
|
||||
if (!cm->frame_parallel_decode && cm->new_fb_idx >= 0 &&
|
||||
frame_bufs[cm->new_fb_idx].ref_count == 0)
|
||||
pool->release_fb_cb(pool->cb_priv,
|
||||
&frame_bufs[cm->new_fb_idx].raw_frame_buffer);
|
||||
|
||||
// Find a free frame buffer. Return error if can not find any.
|
||||
cm->new_fb_idx = get_free_fb(cm);
|
||||
if (cm->new_fb_idx == INVALID_IDX) return AOM_CODEC_MEM_ERROR;
|
||||
|
||||
// Assign a MV array to the frame buffer.
|
||||
cm->cur_frame = &pool->frame_bufs[cm->new_fb_idx];
|
||||
|
||||
pbi->hold_ref_buf = 0;
|
||||
if (cm->frame_parallel_decode) {
|
||||
AVxWorker *const worker = pbi->frame_worker_owner;
|
||||
av1_frameworker_lock_stats(worker);
|
||||
frame_bufs[cm->new_fb_idx].frame_worker_owner = worker;
|
||||
// Reset decoding progress.
|
||||
pbi->cur_buf = &frame_bufs[cm->new_fb_idx];
|
||||
pbi->cur_buf->row = -1;
|
||||
pbi->cur_buf->col = -1;
|
||||
av1_frameworker_unlock_stats(worker);
|
||||
} else {
|
||||
pbi->cur_buf = &frame_bufs[cm->new_fb_idx];
|
||||
}
|
||||
|
||||
if (setjmp(cm->error.jmp)) {
|
||||
const AVxWorkerInterface *const winterface = aom_get_worker_interface();
|
||||
int i;
|
||||
|
||||
cm->error.setjmp = 0;
|
||||
pbi->ready_for_new_data = 1;
|
||||
|
||||
// Synchronize all threads immediately as a subsequent decode call may
|
||||
// cause a resize invalidating some allocations.
|
||||
winterface->sync(&pbi->lf_worker);
|
||||
for (i = 0; i < pbi->num_tile_workers; ++i) {
|
||||
winterface->sync(&pbi->tile_workers[i]);
|
||||
}
|
||||
|
||||
lock_buffer_pool(pool);
|
||||
// Release all the reference buffers if worker thread is holding them.
|
||||
if (pbi->hold_ref_buf == 1) {
|
||||
int ref_index = 0, mask;
|
||||
for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
|
||||
const int old_idx = cm->ref_frame_map[ref_index];
|
||||
// Current thread releases the holding of reference frame.
|
||||
decrease_ref_count(old_idx, frame_bufs, pool);
|
||||
|
||||
// Release the reference frame holding in the reference map for the
|
||||
// decoding of the next frame.
|
||||
if (mask & 1) decrease_ref_count(old_idx, frame_bufs, pool);
|
||||
++ref_index;
|
||||
}
|
||||
|
||||
// Current thread releases the holding of reference frame.
|
||||
for (; ref_index < REF_FRAMES && !cm->show_existing_frame; ++ref_index) {
|
||||
const int old_idx = cm->ref_frame_map[ref_index];
|
||||
decrease_ref_count(old_idx, frame_bufs, pool);
|
||||
}
|
||||
pbi->hold_ref_buf = 0;
|
||||
}
|
||||
// Release current frame.
|
||||
decrease_ref_count(cm->new_fb_idx, frame_bufs, pool);
|
||||
unlock_buffer_pool(pool);
|
||||
|
||||
aom_clear_system_state();
|
||||
return -1;
|
||||
}
|
||||
|
||||
cm->error.setjmp = 1;
|
||||
av1_decode_frame(pbi, source, source + size, psource);
|
||||
|
||||
swap_frame_buffers(pbi);
|
||||
|
||||
#if CONFIG_EXT_TILE
|
||||
// For now, we only extend the frame borders when the whole frame is decoded.
|
||||
// Later, if needed, extend the border for the decoded tile on the frame
|
||||
// border.
|
||||
if (pbi->dec_tile_row == -1 && pbi->dec_tile_col == -1)
|
||||
#endif // CONFIG_EXT_TILE
|
||||
aom_extend_frame_inner_borders(cm->frame_to_show);
|
||||
|
||||
aom_clear_system_state();
|
||||
|
||||
if (!cm->show_existing_frame) {
|
||||
cm->last_show_frame = cm->show_frame;
|
||||
|
||||
#if CONFIG_EXT_REFS
|
||||
// NOTE: It is not supposed to ref to any frame not used as reference
|
||||
if (cm->is_reference_frame)
|
||||
#endif // CONFIG_EXT_REFS
|
||||
cm->prev_frame = cm->cur_frame;
|
||||
|
||||
if (cm->seg.enabled && !cm->frame_parallel_decode)
|
||||
av1_swap_current_and_last_seg_map(cm);
|
||||
}
|
||||
|
||||
// Update progress in frame parallel decode.
|
||||
if (cm->frame_parallel_decode) {
|
||||
// Need to lock the mutex here as another thread may
|
||||
// be accessing this buffer.
|
||||
AVxWorker *const worker = pbi->frame_worker_owner;
|
||||
FrameWorkerData *const frame_worker_data = worker->data1;
|
||||
av1_frameworker_lock_stats(worker);
|
||||
|
||||
if (cm->show_frame) {
|
||||
cm->current_video_frame++;
|
||||
}
|
||||
frame_worker_data->frame_decoded = 1;
|
||||
frame_worker_data->frame_context_ready = 1;
|
||||
av1_frameworker_signal_stats(worker);
|
||||
av1_frameworker_unlock_stats(worker);
|
||||
} else {
|
||||
cm->last_width = cm->width;
|
||||
cm->last_height = cm->height;
|
||||
if (cm->show_frame) {
|
||||
cm->current_video_frame++;
|
||||
}
|
||||
}
|
||||
|
||||
cm->error.setjmp = 0;
|
||||
return retcode;
|
||||
}
|
||||
|
||||
int av1_get_raw_frame(AV1Decoder *pbi, YV12_BUFFER_CONFIG *sd) {
|
||||
AV1_COMMON *const cm = &pbi->common;
|
||||
int ret = -1;
|
||||
if (pbi->ready_for_new_data == 1) return ret;
|
||||
|
||||
pbi->ready_for_new_data = 1;
|
||||
|
||||
/* no raw frame to show!!! */
|
||||
if (!cm->show_frame) return ret;
|
||||
|
||||
pbi->ready_for_new_data = 1;
|
||||
*sd = *cm->frame_to_show;
|
||||
ret = 0;
|
||||
aom_clear_system_state();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int av1_get_frame_to_show(AV1Decoder *pbi, YV12_BUFFER_CONFIG *frame) {
|
||||
AV1_COMMON *const cm = &pbi->common;
|
||||
|
||||
if (!cm->show_frame || !cm->frame_to_show) return -1;
|
||||
|
||||
*frame = *cm->frame_to_show;
|
||||
return 0;
|
||||
}
|
||||
|
||||
aom_codec_err_t av1_parse_superframe_index(const uint8_t *data, size_t data_sz,
|
||||
uint32_t sizes[8], int *count,
|
||||
aom_decrypt_cb decrypt_cb,
|
||||
void *decrypt_state) {
|
||||
// A chunk ending with a byte matching 0xc0 is an invalid chunk unless
|
||||
// it is a super frame index. If the last byte of real video compression
|
||||
// data is 0xc0 the encoder must add a 0 byte. If we have the marker but
|
||||
// not the associated matching marker byte at the front of the index we have
|
||||
// an invalid bitstream and need to return an error.
|
||||
|
||||
uint8_t marker;
|
||||
size_t frame_sz_sum = 0;
|
||||
|
||||
assert(data_sz);
|
||||
marker = read_marker(decrypt_cb, decrypt_state, data + data_sz - 1);
|
||||
*count = 0;
|
||||
|
||||
if ((marker & 0xe0) == 0xc0) {
|
||||
const uint32_t frames = (marker & 0x7) + 1;
|
||||
const uint32_t mag = ((marker >> 3) & 0x3) + 1;
|
||||
const size_t index_sz = 2 + mag * (frames - 1);
|
||||
|
||||
// This chunk is marked as having a superframe index but doesn't have
|
||||
// enough data for it, thus it's an invalid superframe index.
|
||||
if (data_sz < index_sz) return AOM_CODEC_CORRUPT_FRAME;
|
||||
|
||||
{
|
||||
const uint8_t marker2 =
|
||||
read_marker(decrypt_cb, decrypt_state, data + data_sz - index_sz);
|
||||
|
||||
// This chunk is marked as having a superframe index but doesn't have
|
||||
// the matching marker byte at the front of the index therefore it's an
|
||||
// invalid chunk.
|
||||
if (marker != marker2) return AOM_CODEC_CORRUPT_FRAME;
|
||||
}
|
||||
|
||||
{
|
||||
// Found a valid superframe index.
|
||||
uint32_t i, j;
|
||||
const uint8_t *x = &data[data_sz - index_sz + 1];
|
||||
|
||||
// Frames has a maximum of 8 and mag has a maximum of 4.
|
||||
uint8_t clear_buffer[28];
|
||||
assert(sizeof(clear_buffer) >= (frames - 1) * mag);
|
||||
if (decrypt_cb) {
|
||||
decrypt_cb(decrypt_state, x, clear_buffer, (frames - 1) * mag);
|
||||
x = clear_buffer;
|
||||
}
|
||||
|
||||
for (i = 0; i < frames - 1; ++i) {
|
||||
uint32_t this_sz = 0;
|
||||
|
||||
for (j = 0; j < mag; ++j) this_sz |= (*x++) << (j * 8);
|
||||
this_sz += 1;
|
||||
sizes[i] = this_sz;
|
||||
frame_sz_sum += this_sz;
|
||||
}
|
||||
sizes[i] = (uint32_t)(data_sz - index_sz - frame_sz_sum);
|
||||
*count = frames;
|
||||
}
|
||||
}
|
||||
return AOM_CODEC_OK;
|
||||
}
|
||||
224
third_party/aom/av1/decoder/decoder.h
vendored
Normal file
224
third_party/aom/av1/decoder/decoder.h
vendored
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AV1_DECODER_DECODER_H_
|
||||
#define AV1_DECODER_DECODER_H_
|
||||
|
||||
#include "./aom_config.h"
|
||||
|
||||
#include "aom/aom_codec.h"
|
||||
#include "aom_dsp/bitreader.h"
|
||||
#include "aom_scale/yv12config.h"
|
||||
#include "aom_util/aom_thread.h"
|
||||
|
||||
#include "av1/common/thread_common.h"
|
||||
#include "av1/common/onyxc_int.h"
|
||||
#include "av1/decoder/dthread.h"
|
||||
#if CONFIG_ACCOUNTING
|
||||
#include "av1/decoder/accounting.h"
|
||||
#endif
|
||||
#if CONFIG_INSPECTION
|
||||
#include "av1/decoder/inspection.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_PVQ
|
||||
#include "aom_dsp/entdec.h"
|
||||
#include "av1/decoder/decint.h"
|
||||
#include "av1/encoder/encodemb.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// TODO(hkuang): combine this with TileWorkerData.
|
||||
typedef struct TileData {
|
||||
AV1_COMMON *cm;
|
||||
aom_reader bit_reader;
|
||||
DECLARE_ALIGNED(16, MACROBLOCKD, xd);
|
||||
/* dqcoeff are shared by all the planes. So planes must be decoded serially */
|
||||
DECLARE_ALIGNED(16, tran_low_t, dqcoeff[MAX_TX_SQUARE]);
|
||||
#if CONFIG_PVQ
|
||||
/* forward transformed predicted image, a reference for PVQ */
|
||||
DECLARE_ALIGNED(16, tran_low_t, pvq_ref_coeff[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
|
||||
#endif
|
||||
#if CONFIG_CFL
|
||||
CFL_CTX cfl;
|
||||
#endif
|
||||
#if CONFIG_EC_ADAPT
|
||||
DECLARE_ALIGNED(16, FRAME_CONTEXT, tctx);
|
||||
#endif
|
||||
#if CONFIG_PALETTE
|
||||
DECLARE_ALIGNED(16, uint8_t, color_index_map[2][MAX_SB_SQUARE]);
|
||||
#endif // CONFIG_PALETTE
|
||||
} TileData;
|
||||
|
||||
typedef struct TileWorkerData {
|
||||
struct AV1Decoder *pbi;
|
||||
aom_reader bit_reader;
|
||||
FRAME_COUNTS counts;
|
||||
DECLARE_ALIGNED(16, MACROBLOCKD, xd);
|
||||
/* dqcoeff are shared by all the planes. So planes must be decoded serially */
|
||||
DECLARE_ALIGNED(16, tran_low_t, dqcoeff[MAX_TX_SQUARE]);
|
||||
#if CONFIG_PVQ
|
||||
/* forward transformed predicted image, a reference for PVQ */
|
||||
DECLARE_ALIGNED(16, tran_low_t, pvq_ref_coeff[OD_TXSIZE_MAX * OD_TXSIZE_MAX]);
|
||||
#endif
|
||||
#if CONFIG_CFL
|
||||
CFL_CTX cfl;
|
||||
#endif
|
||||
#if CONFIG_EC_ADAPT
|
||||
FRAME_CONTEXT tctx;
|
||||
#endif
|
||||
#if CONFIG_PALETTE
|
||||
DECLARE_ALIGNED(16, uint8_t, color_index_map[2][MAX_SB_SQUARE]);
|
||||
#endif // CONFIG_PALETTE
|
||||
struct aom_internal_error_info error_info;
|
||||
} TileWorkerData;
|
||||
|
||||
typedef struct TileBufferDec {
|
||||
const uint8_t *data;
|
||||
size_t size;
|
||||
const uint8_t *raw_data_end; // The end of the raw tile buffer in the
|
||||
// bit stream.
|
||||
int col; // only used with multi-threaded decoding
|
||||
} TileBufferDec;
|
||||
|
||||
typedef struct AV1Decoder {
|
||||
DECLARE_ALIGNED(16, MACROBLOCKD, mb);
|
||||
|
||||
DECLARE_ALIGNED(16, AV1_COMMON, common);
|
||||
|
||||
int ready_for_new_data;
|
||||
|
||||
int refresh_frame_flags;
|
||||
|
||||
// TODO(hkuang): Combine this with cur_buf in macroblockd as they are
|
||||
// the same.
|
||||
RefCntBuffer *cur_buf; // Current decoding frame buffer.
|
||||
|
||||
AVxWorker *frame_worker_owner; // frame_worker that owns this pbi.
|
||||
AVxWorker lf_worker;
|
||||
AVxWorker *tile_workers;
|
||||
TileWorkerData *tile_worker_data;
|
||||
TileInfo *tile_worker_info;
|
||||
int num_tile_workers;
|
||||
|
||||
TileData *tile_data;
|
||||
int allocated_tiles;
|
||||
|
||||
TileBufferDec tile_buffers[MAX_TILE_ROWS][MAX_TILE_COLS];
|
||||
|
||||
AV1LfSync lf_row_sync;
|
||||
|
||||
aom_decrypt_cb decrypt_cb;
|
||||
void *decrypt_state;
|
||||
|
||||
int max_threads;
|
||||
int inv_tile_order;
|
||||
int need_resync; // wait for key/intra-only frame.
|
||||
int hold_ref_buf; // hold the reference buffer.
|
||||
|
||||
int tile_size_bytes;
|
||||
#if CONFIG_EXT_TILE
|
||||
int tile_col_size_bytes;
|
||||
int dec_tile_row, dec_tile_col;
|
||||
#endif // CONFIG_EXT_TILE
|
||||
#if CONFIG_ACCOUNTING
|
||||
int acct_enabled;
|
||||
Accounting accounting;
|
||||
#endif
|
||||
size_t uncomp_hdr_size; // Size of the uncompressed header
|
||||
size_t first_partition_size; // Size of the compressed header
|
||||
#if CONFIG_TILE_GROUPS
|
||||
int tg_size; // Number of tiles in the current tilegroup
|
||||
int tg_start; // First tile in the current tilegroup
|
||||
int tg_size_bit_offset;
|
||||
#endif
|
||||
#if CONFIG_REFERENCE_BUFFER
|
||||
SequenceHeader seq_params;
|
||||
#endif
|
||||
#if CONFIG_INSPECTION
|
||||
aom_inspect_cb inspect_cb;
|
||||
void *inspect_ctx;
|
||||
#endif
|
||||
} AV1Decoder;
|
||||
|
||||
int av1_receive_compressed_data(struct AV1Decoder *pbi, size_t size,
|
||||
const uint8_t **dest);
|
||||
|
||||
int av1_get_raw_frame(struct AV1Decoder *pbi, YV12_BUFFER_CONFIG *sd);
|
||||
|
||||
int av1_get_frame_to_show(struct AV1Decoder *pbi, YV12_BUFFER_CONFIG *frame);
|
||||
|
||||
aom_codec_err_t av1_copy_reference_dec(struct AV1Decoder *pbi,
|
||||
AOM_REFFRAME ref_frame_flag,
|
||||
YV12_BUFFER_CONFIG *sd);
|
||||
|
||||
aom_codec_err_t av1_set_reference_dec(AV1_COMMON *cm,
|
||||
AOM_REFFRAME ref_frame_flag,
|
||||
YV12_BUFFER_CONFIG *sd);
|
||||
|
||||
static INLINE uint8_t read_marker(aom_decrypt_cb decrypt_cb,
|
||||
void *decrypt_state, const uint8_t *data) {
|
||||
if (decrypt_cb) {
|
||||
uint8_t marker;
|
||||
decrypt_cb(decrypt_state, data, &marker, 1);
|
||||
return marker;
|
||||
}
|
||||
return *data;
|
||||
}
|
||||
|
||||
// This function is exposed for use in tests, as well as the inlined function
|
||||
// "read_marker".
|
||||
aom_codec_err_t av1_parse_superframe_index(const uint8_t *data, size_t data_sz,
|
||||
uint32_t sizes[8], int *count,
|
||||
aom_decrypt_cb decrypt_cb,
|
||||
void *decrypt_state);
|
||||
|
||||
struct AV1Decoder *av1_decoder_create(BufferPool *const pool);
|
||||
|
||||
void av1_decoder_remove(struct AV1Decoder *pbi);
|
||||
|
||||
static INLINE void decrease_ref_count(int idx, RefCntBuffer *const frame_bufs,
|
||||
BufferPool *const pool) {
|
||||
if (idx >= 0) {
|
||||
--frame_bufs[idx].ref_count;
|
||||
// A worker may only get a free framebuffer index when calling get_free_fb.
|
||||
// But the private buffer is not set up until finish decoding header.
|
||||
// So any error happens during decoding header, the frame_bufs will not
|
||||
// have valid priv buffer.
|
||||
if (frame_bufs[idx].ref_count == 0 &&
|
||||
frame_bufs[idx].raw_frame_buffer.priv) {
|
||||
pool->release_fb_cb(pool->cb_priv, &frame_bufs[idx].raw_frame_buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_EXT_REFS
|
||||
static INLINE int dec_is_ref_frame_buf(AV1Decoder *const pbi,
|
||||
RefCntBuffer *frame_buf) {
|
||||
AV1_COMMON *const cm = &pbi->common;
|
||||
int i;
|
||||
for (i = 0; i < INTER_REFS_PER_FRAME; ++i) {
|
||||
RefBuffer *const ref_frame = &cm->frame_refs[i];
|
||||
if (ref_frame->idx == INVALID_IDX) continue;
|
||||
if (frame_buf == &cm->buffer_pool->frame_bufs[ref_frame->idx]) break;
|
||||
}
|
||||
return (i < INTER_REFS_PER_FRAME);
|
||||
}
|
||||
#endif // CONFIG_EXT_REFS
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // AV1_DECODER_DECODER_H_
|
||||
286
third_party/aom/av1/decoder/decodetxb.c
vendored
Normal file
286
third_party/aom/av1/decoder/decodetxb.c
vendored
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include "av1/common/scan.h"
|
||||
#include "av1/common/idct.h"
|
||||
#include "av1/common/txb_common.h"
|
||||
#include "av1/decoder/decodemv.h"
|
||||
#include "av1/decoder/decodetxb.h"
|
||||
#include "av1/decoder/dsubexp.h"
|
||||
|
||||
#define ACCT_STR __func__
|
||||
|
||||
static int read_golomb(MACROBLOCKD *xd, aom_reader *r) {
|
||||
int x = 1;
|
||||
int length = 0;
|
||||
int i = 0;
|
||||
|
||||
while (!i) {
|
||||
i = aom_read_bit(r, ACCT_STR);
|
||||
++length;
|
||||
if (length >= 32) {
|
||||
aom_internal_error(xd->error_info, AOM_CODEC_CORRUPT_FRAME,
|
||||
"Invalid length in read_golomb");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < length - 1; ++i) {
|
||||
x <<= 1;
|
||||
x += aom_read_bit(r, ACCT_STR);
|
||||
}
|
||||
|
||||
return x - 1;
|
||||
}
|
||||
|
||||
uint8_t av1_read_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCKD *xd,
|
||||
aom_reader *r, int block, int plane,
|
||||
tran_low_t *tcoeffs, TXB_CTX *txb_ctx,
|
||||
int16_t *max_scan_line, int *eob) {
|
||||
FRAME_COUNTS *counts = xd->counts;
|
||||
TX_SIZE tx_size = get_tx_size(plane, xd);
|
||||
PLANE_TYPE plane_type = get_plane_type(plane);
|
||||
aom_prob *nz_map = cm->fc->nz_map[tx_size][plane_type];
|
||||
aom_prob *eob_flag = cm->fc->eob_flag[tx_size][plane_type];
|
||||
MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
|
||||
const int seg_eob = tx_size_2d[tx_size];
|
||||
int c = 0;
|
||||
int update_eob = -1;
|
||||
const int16_t *const dequant = xd->plane[plane].seg_dequant[mbmi->segment_id];
|
||||
const int shift = av1_get_tx_scale(tx_size);
|
||||
const int bwl = b_width_log2_lookup[txsize_to_bsize[tx_size]] + 2;
|
||||
int cul_level = 0;
|
||||
unsigned int(*nz_map_count)[SIG_COEF_CONTEXTS][2];
|
||||
uint8_t txb_mask[32 * 32] = { 0 };
|
||||
|
||||
nz_map_count = (counts) ? &counts->nz_map[tx_size][plane_type] : NULL;
|
||||
|
||||
memset(tcoeffs, 0, sizeof(*tcoeffs) * seg_eob);
|
||||
|
||||
int all_zero =
|
||||
aom_read(r, cm->fc->txb_skip[tx_size][txb_ctx->txb_skip_ctx], ACCT_STR);
|
||||
if (xd->counts)
|
||||
++xd->counts->txb_skip[tx_size][txb_ctx->txb_skip_ctx][all_zero];
|
||||
|
||||
*eob = 0;
|
||||
if (all_zero) {
|
||||
*max_scan_line = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_TXK_SEL
|
||||
av1_read_tx_type(cm, xd, block, plane, r);
|
||||
#endif
|
||||
TX_TYPE tx_type = get_tx_type(plane_type, xd, block, tx_size);
|
||||
const SCAN_ORDER *const scan_order =
|
||||
get_scan(cm, tx_size, tx_type, is_inter_block(mbmi));
|
||||
const int16_t *scan = scan_order->scan;
|
||||
|
||||
for (c = 0; c < seg_eob; ++c) {
|
||||
int is_nz;
|
||||
int coeff_ctx = get_nz_map_ctx(tcoeffs, txb_mask, scan[c], bwl);
|
||||
int eob_ctx = get_eob_ctx(tcoeffs, scan[c], bwl);
|
||||
|
||||
if (c < seg_eob - 1)
|
||||
is_nz = aom_read(r, nz_map[coeff_ctx], tx_size);
|
||||
else
|
||||
is_nz = 1;
|
||||
|
||||
// set non-zero coefficient map.
|
||||
tcoeffs[scan[c]] = is_nz;
|
||||
|
||||
if (c == seg_eob - 1) {
|
||||
++c;
|
||||
break;
|
||||
}
|
||||
|
||||
if (counts) ++(*nz_map_count)[coeff_ctx][is_nz];
|
||||
|
||||
if (is_nz) {
|
||||
int is_eob = aom_read(r, eob_flag[eob_ctx], tx_size);
|
||||
if (counts) ++counts->eob_flag[tx_size][plane_type][eob_ctx][is_eob];
|
||||
if (is_eob) break;
|
||||
}
|
||||
txb_mask[scan[c]] = 1;
|
||||
}
|
||||
|
||||
*eob = AOMMIN(seg_eob, c + 1);
|
||||
*max_scan_line = *eob;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < NUM_BASE_LEVELS; ++i) {
|
||||
aom_prob *coeff_base = cm->fc->coeff_base[tx_size][plane_type][i];
|
||||
|
||||
update_eob = 0;
|
||||
for (c = *eob - 1; c >= 0; --c) {
|
||||
tran_low_t *v = &tcoeffs[scan[c]];
|
||||
int sign;
|
||||
int ctx;
|
||||
|
||||
if (*v <= i) continue;
|
||||
|
||||
ctx = get_base_ctx(tcoeffs, scan[c], bwl, i + 1);
|
||||
|
||||
if (aom_read(r, coeff_base[ctx], tx_size)) {
|
||||
*v = i + 1;
|
||||
cul_level += i + 1;
|
||||
|
||||
if (counts) ++counts->coeff_base[tx_size][plane_type][i][ctx][1];
|
||||
|
||||
if (c == 0) {
|
||||
int dc_sign_ctx = txb_ctx->dc_sign_ctx;
|
||||
sign = aom_read(r, cm->fc->dc_sign[plane_type][dc_sign_ctx], tx_size);
|
||||
if (counts) ++counts->dc_sign[plane_type][dc_sign_ctx][sign];
|
||||
} else {
|
||||
sign = aom_read_bit(r, ACCT_STR);
|
||||
}
|
||||
if (sign) *v = -(*v);
|
||||
continue;
|
||||
}
|
||||
*v = i + 2;
|
||||
if (counts) ++counts->coeff_base[tx_size][plane_type][i][ctx][0];
|
||||
|
||||
// update the eob flag for coefficients with magnitude above 1.
|
||||
update_eob = AOMMAX(update_eob, c);
|
||||
}
|
||||
}
|
||||
|
||||
for (c = update_eob; c >= 0; --c) {
|
||||
tran_low_t *v = &tcoeffs[scan[c]];
|
||||
int sign;
|
||||
int idx;
|
||||
int ctx;
|
||||
|
||||
if (*v <= NUM_BASE_LEVELS) continue;
|
||||
|
||||
if (c == 0) {
|
||||
int dc_sign_ctx = txb_ctx->dc_sign_ctx;
|
||||
sign = aom_read(r, cm->fc->dc_sign[plane_type][dc_sign_ctx], tx_size);
|
||||
if (counts) ++counts->dc_sign[plane_type][dc_sign_ctx][sign];
|
||||
} else {
|
||||
sign = aom_read_bit(r, ACCT_STR);
|
||||
}
|
||||
|
||||
ctx = get_level_ctx(tcoeffs, scan[c], bwl);
|
||||
|
||||
if (cm->fc->coeff_lps[tx_size][plane_type][ctx] == 0) exit(0);
|
||||
|
||||
for (idx = 0; idx < COEFF_BASE_RANGE; ++idx) {
|
||||
if (aom_read(r, cm->fc->coeff_lps[tx_size][plane_type][ctx], tx_size)) {
|
||||
*v = (idx + 1 + NUM_BASE_LEVELS);
|
||||
if (sign) *v = -(*v);
|
||||
cul_level += abs(*v);
|
||||
|
||||
if (counts) ++counts->coeff_lps[tx_size][plane_type][ctx][1];
|
||||
break;
|
||||
}
|
||||
if (counts) ++counts->coeff_lps[tx_size][plane_type][ctx][0];
|
||||
}
|
||||
if (idx < COEFF_BASE_RANGE) continue;
|
||||
|
||||
// decode 0-th order Golomb code
|
||||
*v = read_golomb(xd, r) + COEFF_BASE_RANGE + 1 + NUM_BASE_LEVELS;
|
||||
if (sign) *v = -(*v);
|
||||
cul_level += abs(*v);
|
||||
}
|
||||
|
||||
for (c = 0; c < *eob; ++c) {
|
||||
int16_t dqv = (c == 0) ? dequant[0] : dequant[1];
|
||||
tran_low_t *v = &tcoeffs[scan[c]];
|
||||
int sign = (*v) < 0;
|
||||
*v = (abs(*v) * dqv) >> shift;
|
||||
if (sign) *v = -(*v);
|
||||
}
|
||||
|
||||
cul_level = AOMMIN(63, cul_level);
|
||||
|
||||
// DC value
|
||||
set_dc_sign(&cul_level, tcoeffs[0]);
|
||||
|
||||
return cul_level;
|
||||
}
|
||||
|
||||
uint8_t av1_read_coeffs_txb_facade(AV1_COMMON *cm, MACROBLOCKD *xd,
|
||||
aom_reader *r, int row, int col, int block,
|
||||
int plane, tran_low_t *tcoeffs,
|
||||
int16_t *max_scan_line, int *eob) {
|
||||
MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
|
||||
struct macroblockd_plane *pd = &xd->plane[plane];
|
||||
|
||||
const BLOCK_SIZE bsize = mbmi->sb_type;
|
||||
#if CONFIG_CB4X4
|
||||
#if CONFIG_CHROMA_2X2
|
||||
const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
|
||||
#else
|
||||
const BLOCK_SIZE plane_bsize =
|
||||
AOMMAX(BLOCK_4X4, get_plane_block_size(bsize, pd));
|
||||
#endif // CONFIG_CHROMA_2X2
|
||||
#else // CONFIG_CB4X4
|
||||
const BLOCK_SIZE plane_bsize =
|
||||
get_plane_block_size(AOMMAX(BLOCK_8X8, bsize), pd);
|
||||
#endif // CONFIG_CB4X4
|
||||
|
||||
TX_SIZE tx_size = get_tx_size(plane, xd);
|
||||
TXB_CTX txb_ctx;
|
||||
get_txb_ctx(plane_bsize, tx_size, plane, pd->above_context + col,
|
||||
pd->left_context + row, &txb_ctx);
|
||||
uint8_t cul_level = av1_read_coeffs_txb(cm, xd, r, block, plane, tcoeffs,
|
||||
&txb_ctx, max_scan_line, eob);
|
||||
#if CONFIG_ADAPT_SCAN
|
||||
PLANE_TYPE plane_type = get_plane_type(plane);
|
||||
TX_TYPE tx_type = get_tx_type(plane_type, xd, block, tx_size);
|
||||
if (xd->counts && *eob > 0)
|
||||
av1_update_scan_count_facade(cm, xd->counts, tx_size, tx_type, pd->dqcoeff,
|
||||
*eob);
|
||||
#endif
|
||||
av1_set_contexts(xd, pd, plane, tx_size, cul_level, col, row);
|
||||
return cul_level;
|
||||
}
|
||||
|
||||
static void read_txb_probs(FRAME_CONTEXT *fc, const TX_SIZE tx_size,
|
||||
aom_reader *r) {
|
||||
int plane, ctx, level;
|
||||
|
||||
if (aom_read_bit(r, ACCT_STR) == 0) return;
|
||||
|
||||
for (ctx = 0; ctx < TXB_SKIP_CONTEXTS; ++ctx)
|
||||
av1_diff_update_prob(r, &fc->txb_skip[tx_size][ctx], ACCT_STR);
|
||||
|
||||
for (plane = 0; plane < PLANE_TYPES; ++plane)
|
||||
for (ctx = 0; ctx < SIG_COEF_CONTEXTS; ++ctx)
|
||||
av1_diff_update_prob(r, &fc->nz_map[tx_size][plane][ctx], ACCT_STR);
|
||||
|
||||
for (plane = 0; plane < PLANE_TYPES; ++plane)
|
||||
for (ctx = 0; ctx < EOB_COEF_CONTEXTS; ++ctx)
|
||||
av1_diff_update_prob(r, &fc->eob_flag[tx_size][plane][ctx], ACCT_STR);
|
||||
|
||||
for (level = 0; level < NUM_BASE_LEVELS; ++level)
|
||||
for (plane = 0; plane < PLANE_TYPES; ++plane)
|
||||
for (ctx = 0; ctx < COEFF_BASE_CONTEXTS; ++ctx)
|
||||
av1_diff_update_prob(r, &fc->coeff_base[tx_size][plane][level][ctx],
|
||||
ACCT_STR);
|
||||
|
||||
for (plane = 0; plane < PLANE_TYPES; ++plane)
|
||||
for (ctx = 0; ctx < LEVEL_CONTEXTS; ++ctx)
|
||||
av1_diff_update_prob(r, &fc->coeff_lps[tx_size][plane][ctx], ACCT_STR);
|
||||
}
|
||||
|
||||
void av1_read_txb_probs(FRAME_CONTEXT *fc, TX_MODE tx_mode, aom_reader *r) {
|
||||
const TX_SIZE max_tx_size = tx_mode_to_biggest_tx_size[tx_mode];
|
||||
TX_SIZE tx_size;
|
||||
int ctx, plane;
|
||||
for (plane = 0; plane < PLANE_TYPES; ++plane)
|
||||
for (ctx = 0; ctx < DC_SIGN_CONTEXTS; ++ctx)
|
||||
av1_diff_update_prob(r, &fc->dc_sign[plane][ctx], ACCT_STR);
|
||||
|
||||
for (tx_size = TX_4X4; tx_size <= max_tx_size; ++tx_size)
|
||||
read_txb_probs(fc, tx_size, r);
|
||||
}
|
||||
31
third_party/aom/av1/decoder/decodetxb.h
vendored
Normal file
31
third_party/aom/av1/decoder/decodetxb.h
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef DECODETXB_H_
|
||||
#define DECODETXB_H_
|
||||
|
||||
#include "./aom_config.h"
|
||||
#include "av1/common/blockd.h"
|
||||
#include "av1/common/onyxc_int.h"
|
||||
#include "av1/common/txb_common.h"
|
||||
#include "aom_dsp/bitreader.h"
|
||||
|
||||
uint8_t av1_read_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCKD *xd,
|
||||
aom_reader *r, int block, int plane,
|
||||
tran_low_t *tcoeffs, TXB_CTX *txb_ctx,
|
||||
int16_t *max_scan_line, int *eob);
|
||||
|
||||
uint8_t av1_read_coeffs_txb_facade(AV1_COMMON *cm, MACROBLOCKD *xd,
|
||||
aom_reader *r, int row, int col, int block,
|
||||
int plane, tran_low_t *tcoeffs,
|
||||
int16_t *max_scan_line, int *eob);
|
||||
void av1_read_txb_probs(FRAME_CONTEXT *fc, TX_MODE tx_mode, aom_reader *r);
|
||||
#endif // DECODETXB_H_
|
||||
467
third_party/aom/av1/decoder/detokenize.c
vendored
Normal file
467
third_party/aom/av1/decoder/detokenize.c
vendored
Normal file
|
|
@ -0,0 +1,467 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include "./aom_config.h"
|
||||
#if !CONFIG_PVQ
|
||||
#include "aom_mem/aom_mem.h"
|
||||
#include "aom_ports/mem.h"
|
||||
#endif // !CONFIG_PVQ
|
||||
|
||||
#include "av1/common/blockd.h"
|
||||
|
||||
#define ACCT_STR __func__
|
||||
|
||||
#if !CONFIG_PVQ || CONFIG_VAR_TX
|
||||
#include "av1/common/common.h"
|
||||
#include "av1/common/entropy.h"
|
||||
#include "av1/common/idct.h"
|
||||
#include "av1/decoder/detokenize.h"
|
||||
|
||||
#define EOB_CONTEXT_NODE 0
|
||||
#define ZERO_CONTEXT_NODE 1
|
||||
#define ONE_CONTEXT_NODE 2
|
||||
#define LOW_VAL_CONTEXT_NODE 0
|
||||
#define TWO_CONTEXT_NODE 1
|
||||
#define THREE_CONTEXT_NODE 2
|
||||
#define HIGH_LOW_CONTEXT_NODE 3
|
||||
#define CAT_ONE_CONTEXT_NODE 4
|
||||
#define CAT_THREEFOUR_CONTEXT_NODE 5
|
||||
#define CAT_THREE_CONTEXT_NODE 6
|
||||
#define CAT_FIVE_CONTEXT_NODE 7
|
||||
|
||||
#define INCREMENT_COUNT(token) \
|
||||
do { \
|
||||
if (counts) ++coef_counts[band][ctx][token]; \
|
||||
} while (0)
|
||||
|
||||
#if CONFIG_NEW_MULTISYMBOL
|
||||
#define READ_COEFF(prob_name, cdf_name, num, r) read_coeff(cdf_name, num, r);
|
||||
static INLINE int read_coeff(const aom_cdf_prob *const *cdf, int n,
|
||||
aom_reader *r) {
|
||||
int val = 0;
|
||||
int i = 0;
|
||||
int count = 0;
|
||||
while (count < n) {
|
||||
const int size = AOMMIN(n - count, 4);
|
||||
val |= aom_read_cdf(r, cdf[i++], 1 << size, ACCT_STR) << count;
|
||||
count += size;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
#else
|
||||
#define READ_COEFF(prob_name, cdf_name, num, r) read_coeff(prob_name, num, r);
|
||||
static INLINE int read_coeff(const aom_prob *probs, int n, aom_reader *r) {
|
||||
int i, val = 0;
|
||||
for (i = 0; i < n; ++i) val = (val << 1) | aom_read(r, probs[i], ACCT_STR);
|
||||
return val;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int token_to_value(aom_reader *const r, int token, TX_SIZE tx_size,
|
||||
int bit_depth) {
|
||||
#if !CONFIG_HIGHBITDEPTH
|
||||
assert(bit_depth == 8);
|
||||
#endif // !CONFIG_HIGHBITDEPTH
|
||||
|
||||
switch (token) {
|
||||
case ZERO_TOKEN:
|
||||
case ONE_TOKEN:
|
||||
case TWO_TOKEN:
|
||||
case THREE_TOKEN:
|
||||
case FOUR_TOKEN: return token;
|
||||
case CATEGORY1_TOKEN:
|
||||
return CAT1_MIN_VAL + READ_COEFF(av1_cat1_prob, av1_cat1_cdf, 1, r);
|
||||
case CATEGORY2_TOKEN:
|
||||
return CAT2_MIN_VAL + READ_COEFF(av1_cat2_prob, av1_cat2_cdf, 2, r);
|
||||
case CATEGORY3_TOKEN:
|
||||
return CAT3_MIN_VAL + READ_COEFF(av1_cat3_prob, av1_cat3_cdf, 3, r);
|
||||
case CATEGORY4_TOKEN:
|
||||
return CAT4_MIN_VAL + READ_COEFF(av1_cat4_prob, av1_cat4_cdf, 4, r);
|
||||
case CATEGORY5_TOKEN:
|
||||
return CAT5_MIN_VAL + READ_COEFF(av1_cat5_prob, av1_cat5_cdf, 5, r);
|
||||
case CATEGORY6_TOKEN: {
|
||||
const int skip_bits = (int)sizeof(av1_cat6_prob) -
|
||||
av1_get_cat6_extrabits_size(tx_size, bit_depth);
|
||||
return CAT6_MIN_VAL + READ_COEFF(av1_cat6_prob + skip_bits, av1_cat6_cdf,
|
||||
18 - skip_bits, r);
|
||||
}
|
||||
default:
|
||||
assert(0); // Invalid token.
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int decode_coefs(MACROBLOCKD *xd, PLANE_TYPE type, tran_low_t *dqcoeff,
|
||||
TX_SIZE tx_size, TX_TYPE tx_type, const int16_t *dq,
|
||||
#if CONFIG_NEW_QUANT
|
||||
dequant_val_type_nuq *dq_val,
|
||||
#endif // CONFIG_NEW_QUANT
|
||||
#if CONFIG_AOM_QM
|
||||
const qm_val_t *iqm[2][TX_SIZES],
|
||||
#endif // CONFIG_AOM_QM
|
||||
int ctx, const int16_t *scan, const int16_t *nb,
|
||||
int16_t *max_scan_line, aom_reader *r) {
|
||||
FRAME_COUNTS *counts = xd->counts;
|
||||
#if CONFIG_EC_ADAPT
|
||||
FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
|
||||
#else
|
||||
FRAME_CONTEXT *const ec_ctx = xd->fc;
|
||||
#endif
|
||||
const int max_eob = tx_size_2d[tx_size];
|
||||
const int ref = is_inter_block(&xd->mi[0]->mbmi);
|
||||
#if CONFIG_AOM_QM
|
||||
const qm_val_t *iqmatrix = iqm[!ref][tx_size];
|
||||
#endif // CONFIG_AOM_QM
|
||||
int band, c = 0;
|
||||
const int tx_size_ctx = txsize_sqr_map[tx_size];
|
||||
#if CONFIG_NEW_TOKENSET
|
||||
aom_cdf_prob(*coef_head_cdfs)[COEFF_CONTEXTS][CDF_SIZE(ENTROPY_TOKENS)] =
|
||||
ec_ctx->coef_head_cdfs[tx_size_ctx][type][ref];
|
||||
aom_cdf_prob(*coef_tail_cdfs)[COEFF_CONTEXTS][CDF_SIZE(ENTROPY_TOKENS)] =
|
||||
ec_ctx->coef_tail_cdfs[tx_size_ctx][type][ref];
|
||||
int val = 0;
|
||||
|
||||
#if !CONFIG_EC_ADAPT
|
||||
unsigned int *blockz_count;
|
||||
unsigned int(*coef_counts)[COEFF_CONTEXTS][UNCONSTRAINED_NODES + 1] = NULL;
|
||||
unsigned int(*eob_branch_count)[COEFF_CONTEXTS] = NULL;
|
||||
#endif
|
||||
#else
|
||||
aom_prob(*coef_probs)[COEFF_CONTEXTS][UNCONSTRAINED_NODES] =
|
||||
ec_ctx->coef_probs[tx_size_ctx][type][ref];
|
||||
const aom_prob *prob;
|
||||
#if CONFIG_EC_MULTISYMBOL
|
||||
aom_cdf_prob(*coef_cdfs)[COEFF_CONTEXTS][CDF_SIZE(ENTROPY_TOKENS)] =
|
||||
ec_ctx->coef_cdfs[tx_size_ctx][type][ref];
|
||||
aom_cdf_prob(*cdf)[CDF_SIZE(ENTROPY_TOKENS)];
|
||||
#endif // CONFIG_EC_MULTISYMBOL
|
||||
unsigned int(*coef_counts)[COEFF_CONTEXTS][UNCONSTRAINED_NODES + 1] = NULL;
|
||||
unsigned int(*eob_branch_count)[COEFF_CONTEXTS] = NULL;
|
||||
#endif // CONFIG_NEW_TOKENSET
|
||||
uint8_t token_cache[MAX_TX_SQUARE];
|
||||
const uint8_t *band_translate = get_band_translate(tx_size);
|
||||
int dq_shift;
|
||||
int v, token;
|
||||
int16_t dqv = dq[0];
|
||||
#if CONFIG_NEW_QUANT
|
||||
const tran_low_t *dqv_val = &dq_val[0][0];
|
||||
#endif // CONFIG_NEW_QUANT
|
||||
(void)tx_type;
|
||||
#if CONFIG_AOM_QM
|
||||
(void)iqmatrix;
|
||||
#endif // CONFIG_AOM_QM
|
||||
|
||||
if (counts) {
|
||||
#if !CONFIG_NEW_TOKENSET || !CONFIG_EC_ADAPT
|
||||
coef_counts = counts->coef[tx_size_ctx][type][ref];
|
||||
eob_branch_count = counts->eob_branch[tx_size_ctx][type][ref];
|
||||
#endif
|
||||
#if CONFIG_NEW_TOKENSET && !CONFIG_EC_ADAPT
|
||||
blockz_count = counts->blockz_count[tx_size_ctx][type][ref][ctx];
|
||||
#endif
|
||||
}
|
||||
|
||||
dq_shift = av1_get_tx_scale(tx_size);
|
||||
|
||||
#if CONFIG_NEW_TOKENSET
|
||||
band = *band_translate++;
|
||||
|
||||
int more_data = 1;
|
||||
while (more_data) {
|
||||
int comb_token;
|
||||
int last_pos = (c + 1 == max_eob);
|
||||
int first_pos = (c == 0);
|
||||
|
||||
#if CONFIG_NEW_QUANT
|
||||
dqv_val = &dq_val[band][0];
|
||||
#endif // CONFIG_NEW_QUANT
|
||||
|
||||
comb_token = last_pos ? 2 * aom_read_bit(r, ACCT_STR) + 2
|
||||
: aom_read_symbol(r, coef_head_cdfs[band][ctx],
|
||||
HEAD_TOKENS + first_pos, ACCT_STR) +
|
||||
!first_pos;
|
||||
if (first_pos) {
|
||||
#if !CONFIG_EC_ADAPT
|
||||
if (counts) ++blockz_count[comb_token != 0];
|
||||
#endif
|
||||
if (comb_token == 0) return 0;
|
||||
}
|
||||
token = comb_token >> 1;
|
||||
|
||||
while (!token) {
|
||||
*max_scan_line = AOMMAX(*max_scan_line, scan[c]);
|
||||
token_cache[scan[c]] = 0;
|
||||
#if !CONFIG_EC_ADAPT
|
||||
if (counts && !last_pos) {
|
||||
++coef_counts[band][ctx][ZERO_TOKEN];
|
||||
}
|
||||
#endif
|
||||
++c;
|
||||
dqv = dq[1];
|
||||
ctx = get_coef_context(nb, token_cache, c);
|
||||
band = *band_translate++;
|
||||
|
||||
last_pos = (c + 1 == max_eob);
|
||||
|
||||
comb_token = last_pos ? 2 * aom_read_bit(r, ACCT_STR) + 2
|
||||
: aom_read_symbol(r, coef_head_cdfs[band][ctx],
|
||||
HEAD_TOKENS, ACCT_STR) +
|
||||
1;
|
||||
token = comb_token >> 1;
|
||||
}
|
||||
|
||||
more_data = comb_token & 1;
|
||||
#if !CONFIG_EC_ADAPT
|
||||
if (counts && !last_pos) {
|
||||
++coef_counts[band][ctx][token];
|
||||
++eob_branch_count[band][ctx];
|
||||
if (!more_data) ++coef_counts[band][ctx][EOB_MODEL_TOKEN];
|
||||
}
|
||||
#endif
|
||||
|
||||
if (token > ONE_TOKEN)
|
||||
token +=
|
||||
aom_read_symbol(r, coef_tail_cdfs[band][ctx], TAIL_TOKENS, ACCT_STR);
|
||||
#if CONFIG_NEW_QUANT
|
||||
dqv_val = &dq_val[band][0];
|
||||
#endif // CONFIG_NEW_QUANT
|
||||
|
||||
*max_scan_line = AOMMAX(*max_scan_line, scan[c]);
|
||||
token_cache[scan[c]] = av1_pt_energy_class[token];
|
||||
|
||||
val = token_to_value(r, token, tx_size,
|
||||
#if CONFIG_HIGHBITDEPTH
|
||||
xd->bd);
|
||||
#else
|
||||
8);
|
||||
#endif // CONFIG_HIGHBITDEPTH
|
||||
|
||||
#if CONFIG_NEW_QUANT
|
||||
v = av1_dequant_abscoeff_nuq(val, dqv, dqv_val);
|
||||
v = dq_shift ? ROUND_POWER_OF_TWO(v, dq_shift) : v;
|
||||
#else
|
||||
#if CONFIG_AOM_QM
|
||||
dqv = ((iqmatrix[scan[c]] * (int)dqv) + (1 << (AOM_QM_BITS - 1))) >>
|
||||
AOM_QM_BITS;
|
||||
#endif
|
||||
v = (val * dqv) >> dq_shift;
|
||||
#endif
|
||||
|
||||
v = aom_read_bit(r, ACCT_STR) ? -v : v;
|
||||
#if CONFIG_COEFFICIENT_RANGE_CHECKING
|
||||
#if CONFIG_HIGHBITDEPTH
|
||||
check_range(v, xd->bd);
|
||||
#else
|
||||
check_range(v, 8);
|
||||
#endif // CONFIG_HIGHBITDEPTH
|
||||
#endif // CONFIG_COEFFICIENT_RANGE_CHECKING
|
||||
|
||||
dqcoeff[scan[c]] = v;
|
||||
|
||||
++c;
|
||||
more_data &= (c < max_eob);
|
||||
if (!more_data) break;
|
||||
dqv = dq[1];
|
||||
ctx = get_coef_context(nb, token_cache, c);
|
||||
band = *band_translate++;
|
||||
|
||||
#else // CONFIG_NEW_TOKENSET
|
||||
while (c < max_eob) {
|
||||
int val = -1;
|
||||
band = *band_translate++;
|
||||
prob = coef_probs[band][ctx];
|
||||
if (counts) ++eob_branch_count[band][ctx];
|
||||
if (!aom_read(r, prob[EOB_CONTEXT_NODE], ACCT_STR)) {
|
||||
INCREMENT_COUNT(EOB_MODEL_TOKEN);
|
||||
break;
|
||||
}
|
||||
|
||||
#if CONFIG_NEW_QUANT
|
||||
dqv_val = &dq_val[band][0];
|
||||
#endif // CONFIG_NEW_QUANT
|
||||
|
||||
while (!aom_read(r, prob[ZERO_CONTEXT_NODE], ACCT_STR)) {
|
||||
INCREMENT_COUNT(ZERO_TOKEN);
|
||||
dqv = dq[1];
|
||||
token_cache[scan[c]] = 0;
|
||||
++c;
|
||||
if (c >= max_eob) return c; // zero tokens at the end (no eob token)
|
||||
ctx = get_coef_context(nb, token_cache, c);
|
||||
band = *band_translate++;
|
||||
prob = coef_probs[band][ctx];
|
||||
#if CONFIG_NEW_QUANT
|
||||
dqv_val = &dq_val[band][0];
|
||||
#endif // CONFIG_NEW_QUANT
|
||||
}
|
||||
|
||||
*max_scan_line = AOMMAX(*max_scan_line, scan[c]);
|
||||
|
||||
#if CONFIG_EC_MULTISYMBOL
|
||||
cdf = &coef_cdfs[band][ctx];
|
||||
token = ONE_TOKEN +
|
||||
aom_read_symbol(r, *cdf, CATEGORY6_TOKEN - ONE_TOKEN + 1, ACCT_STR);
|
||||
INCREMENT_COUNT(ONE_TOKEN + (token > ONE_TOKEN));
|
||||
assert(token != ZERO_TOKEN);
|
||||
val = token_to_value(r, token, tx_size,
|
||||
#if CONFIG_HIGHBITDEPTH
|
||||
xd->bd);
|
||||
#else
|
||||
8);
|
||||
#endif // CONFIG_HIGHBITDEPTH
|
||||
#else // CONFIG_EC_MULTISYMBOL
|
||||
if (!aom_read(r, prob[ONE_CONTEXT_NODE], ACCT_STR)) {
|
||||
INCREMENT_COUNT(ONE_TOKEN);
|
||||
token = ONE_TOKEN;
|
||||
val = 1;
|
||||
} else {
|
||||
INCREMENT_COUNT(TWO_TOKEN);
|
||||
token = aom_read_tree(r, av1_coef_con_tree,
|
||||
av1_pareto8_full[prob[PIVOT_NODE] - 1], ACCT_STR);
|
||||
assert(token != ZERO_TOKEN && token != ONE_TOKEN);
|
||||
val = token_to_value(r, token, tx_size,
|
||||
#if CONFIG_HIGHBITDEPTH
|
||||
xd->bd);
|
||||
#else
|
||||
8);
|
||||
#endif // CONFIG_HIGHBITDEPTH
|
||||
}
|
||||
#endif // CONFIG_EC_MULTISYMBOL
|
||||
#if CONFIG_NEW_QUANT
|
||||
v = av1_dequant_abscoeff_nuq(val, dqv, dqv_val);
|
||||
v = dq_shift ? ROUND_POWER_OF_TWO(v, dq_shift) : v;
|
||||
#else
|
||||
#if CONFIG_AOM_QM
|
||||
dqv = ((iqmatrix[scan[c]] * (int)dqv) + (1 << (AOM_QM_BITS - 1))) >>
|
||||
AOM_QM_BITS;
|
||||
#endif
|
||||
v = (val * dqv) >> dq_shift;
|
||||
#endif // CONFIG_NEW_QUANT
|
||||
|
||||
#if CONFIG_COEFFICIENT_RANGE_CHECKING
|
||||
#if CONFIG_HIGHBITDEPTH
|
||||
dqcoeff[scan[c]] =
|
||||
highbd_check_range((aom_read_bit(r, ACCT_STR) ? -v : v), xd->bd);
|
||||
#else
|
||||
dqcoeff[scan[c]] = check_range(aom_read_bit(r, ACCT_STR) ? -v : v, 8);
|
||||
#endif // CONFIG_HIGHBITDEPTH
|
||||
#else
|
||||
dqcoeff[scan[c]] = aom_read_bit(r, ACCT_STR) ? -v : v;
|
||||
#endif // CONFIG_COEFFICIENT_RANGE_CHECKING
|
||||
token_cache[scan[c]] = av1_pt_energy_class[token];
|
||||
++c;
|
||||
ctx = get_coef_context(nb, token_cache, c);
|
||||
dqv = dq[1];
|
||||
#endif // CONFIG_NEW_TOKENSET
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
#endif // !CONFIG_PVQ
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
void av1_decode_palette_tokens(MACROBLOCKD *const xd, int plane,
|
||||
aom_reader *r) {
|
||||
const MODE_INFO *const mi = xd->mi[0];
|
||||
const MB_MODE_INFO *const mbmi = &mi->mbmi;
|
||||
uint8_t color_order[PALETTE_MAX_SIZE];
|
||||
const int n = mbmi->palette_mode_info.palette_size[plane];
|
||||
int i, j;
|
||||
uint8_t *const color_map = xd->plane[plane].color_index_map;
|
||||
const aom_prob(
|
||||
*const prob)[PALETTE_COLOR_INDEX_CONTEXTS][PALETTE_COLORS - 1] =
|
||||
plane ? av1_default_palette_uv_color_index_prob
|
||||
: av1_default_palette_y_color_index_prob;
|
||||
int plane_block_width, plane_block_height, rows, cols;
|
||||
av1_get_block_dimensions(mbmi->sb_type, plane, xd, &plane_block_width,
|
||||
&plane_block_height, &rows, &cols);
|
||||
assert(plane == 0 || plane == 1);
|
||||
|
||||
#if CONFIG_PALETTE_THROUGHPUT
|
||||
// Run wavefront on the palette map index decoding.
|
||||
for (i = 1; i < rows + cols - 1; ++i) {
|
||||
for (j = AOMMIN(i, cols - 1); j >= AOMMAX(0, i - rows + 1); --j) {
|
||||
const int color_ctx = av1_get_palette_color_index_context(
|
||||
color_map, plane_block_width, (i - j), j, n, color_order, NULL);
|
||||
const int color_idx =
|
||||
aom_read_tree(r, av1_palette_color_index_tree[n - 2],
|
||||
prob[n - 2][color_ctx], ACCT_STR);
|
||||
assert(color_idx >= 0 && color_idx < n);
|
||||
color_map[(i - j) * plane_block_width + j] = color_order[color_idx];
|
||||
}
|
||||
}
|
||||
// Copy last column to extra columns.
|
||||
if (cols < plane_block_width) {
|
||||
for (i = 0; i < plane_block_height; ++i) {
|
||||
memset(color_map + i * plane_block_width + cols,
|
||||
color_map[i * plane_block_width + cols - 1],
|
||||
(plane_block_width - cols));
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (i = 0; i < rows; ++i) {
|
||||
for (j = (i == 0 ? 1 : 0); j < cols; ++j) {
|
||||
const int color_ctx = av1_get_palette_color_index_context(
|
||||
color_map, plane_block_width, i, j, n, color_order, NULL);
|
||||
const int color_idx =
|
||||
aom_read_tree(r, av1_palette_color_index_tree[n - PALETTE_MIN_SIZE],
|
||||
prob[n - PALETTE_MIN_SIZE][color_ctx], ACCT_STR);
|
||||
assert(color_idx >= 0 && color_idx < n);
|
||||
color_map[i * plane_block_width + j] = color_order[color_idx];
|
||||
}
|
||||
memset(color_map + i * plane_block_width + cols,
|
||||
color_map[i * plane_block_width + cols - 1],
|
||||
(plane_block_width - cols)); // Copy last column to extra columns.
|
||||
}
|
||||
#endif // CONFIG_PALETTE_THROUGHPUT
|
||||
// Copy last row to extra rows.
|
||||
for (i = rows; i < plane_block_height; ++i) {
|
||||
memcpy(color_map + i * plane_block_width,
|
||||
color_map + (rows - 1) * plane_block_width, plane_block_width);
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_PALETTE
|
||||
|
||||
#if !CONFIG_PVQ || CONFIG_VAR_TX
|
||||
int av1_decode_block_tokens(AV1_COMMON *cm, MACROBLOCKD *const xd, int plane,
|
||||
const SCAN_ORDER *sc, int x, int y, TX_SIZE tx_size,
|
||||
TX_TYPE tx_type, int16_t *max_scan_line,
|
||||
aom_reader *r, int seg_id) {
|
||||
struct macroblockd_plane *const pd = &xd->plane[plane];
|
||||
const int16_t *const dequant = pd->seg_dequant[seg_id];
|
||||
const int ctx =
|
||||
get_entropy_context(tx_size, pd->above_context + x, pd->left_context + y);
|
||||
#if CONFIG_NEW_QUANT
|
||||
const int ref = is_inter_block(&xd->mi[0]->mbmi);
|
||||
int dq =
|
||||
get_dq_profile_from_ctx(xd->qindex[seg_id], ctx, ref, pd->plane_type);
|
||||
#endif // CONFIG_NEW_QUANT
|
||||
|
||||
const int eob =
|
||||
decode_coefs(xd, pd->plane_type, pd->dqcoeff, tx_size, tx_type, dequant,
|
||||
#if CONFIG_NEW_QUANT
|
||||
pd->seg_dequant_nuq[seg_id][dq],
|
||||
#endif // CONFIG_NEW_QUANT
|
||||
#if CONFIG_AOM_QM
|
||||
pd->seg_iqmatrix[seg_id],
|
||||
#endif // CONFIG_AOM_QM
|
||||
ctx, sc->scan, sc->neighbors, max_scan_line, r);
|
||||
av1_set_contexts(xd, pd, plane, tx_size, eob > 0, x, y);
|
||||
#if CONFIG_ADAPT_SCAN
|
||||
if (xd->counts)
|
||||
av1_update_scan_count_facade(cm, xd->counts, tx_size, tx_type, pd->dqcoeff,
|
||||
eob);
|
||||
#else
|
||||
(void)cm;
|
||||
#endif
|
||||
return eob;
|
||||
}
|
||||
#endif // !CONFIG_PVQ
|
||||
38
third_party/aom/av1/decoder/detokenize.h
vendored
Normal file
38
third_party/aom/av1/decoder/detokenize.h
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AV1_DECODER_DETOKENIZE_H_
|
||||
#define AV1_DECODER_DETOKENIZE_H_
|
||||
|
||||
#include "./aom_config.h"
|
||||
#if !CONFIG_PVQ || CONFIG_VAR_TX
|
||||
#include "av1/decoder/decoder.h"
|
||||
#include "av1/common/scan.h"
|
||||
#endif // !CONFIG_PVQ
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_PALETTE
|
||||
void av1_decode_palette_tokens(MACROBLOCKD *const xd, int plane, aom_reader *r);
|
||||
#endif // CONFIG_PALETTE
|
||||
|
||||
#if !CONFIG_PVQ || CONFIG_VAR_TX
|
||||
int av1_decode_block_tokens(AV1_COMMON *cm, MACROBLOCKD *const xd, int plane,
|
||||
const SCAN_ORDER *sc, int x, int y, TX_SIZE tx_size,
|
||||
TX_TYPE tx_type, int16_t *max_scan_line,
|
||||
aom_reader *r, int seg_id);
|
||||
#endif // !CONFIG_PVQ
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
#endif // AV1_DECODER_DETOKENIZE_H_
|
||||
82
third_party/aom/av1/decoder/dsubexp.c
vendored
Normal file
82
third_party/aom/av1/decoder/dsubexp.c
vendored
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "av1/common/entropy.h"
|
||||
|
||||
#include "av1/decoder/dsubexp.h"
|
||||
|
||||
static int inv_recenter_nonneg(int v, int m) {
|
||||
if (v > 2 * m) return v;
|
||||
|
||||
return (v & 1) ? m - ((v + 1) >> 1) : m + (v >> 1);
|
||||
}
|
||||
|
||||
#define decode_uniform(r, ACCT_STR_NAME) \
|
||||
decode_uniform_(r ACCT_STR_ARG(ACCT_STR_NAME))
|
||||
#define decode_term_subexp(r, ACCT_STR_NAME) \
|
||||
decode_term_subexp_(r ACCT_STR_ARG(ACCT_STR_NAME))
|
||||
|
||||
static int decode_uniform_(aom_reader *r ACCT_STR_PARAM) {
|
||||
const int l = 8;
|
||||
const int m = (1 << l) - 190;
|
||||
const int v = aom_read_literal(r, l - 1, ACCT_STR_NAME);
|
||||
return v < m ? v : (v << 1) - m + aom_read_bit(r, ACCT_STR_NAME);
|
||||
}
|
||||
|
||||
static int inv_remap_prob(int v, int m) {
|
||||
/* clang-format off */
|
||||
static uint8_t inv_map_table[MAX_PROB - 1] = {
|
||||
7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 137, 150, 163, 176, 189,
|
||||
202, 215, 228, 241, 254, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11,
|
||||
12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27,
|
||||
28, 29, 30, 31, 32, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
|
||||
44, 45, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60,
|
||||
61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76,
|
||||
77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 90, 91, 92,
|
||||
93, 94, 95, 96, 97, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
|
||||
109, 110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 125,
|
||||
126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 138, 139, 140, 141,
|
||||
142, 143, 144, 145, 146, 147, 148, 149, 151, 152, 153, 154, 155, 156, 157,
|
||||
158, 159, 160, 161, 162, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
|
||||
174, 175, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 190,
|
||||
191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 203, 204, 205, 206,
|
||||
207, 208, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219, 220, 221, 222,
|
||||
223, 224, 225, 226, 227, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
|
||||
239, 240, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253
|
||||
}; /* clang-format on */
|
||||
assert(v < (int)(sizeof(inv_map_table) / sizeof(inv_map_table[0])));
|
||||
v = inv_map_table[v];
|
||||
m--;
|
||||
if ((m << 1) <= MAX_PROB) {
|
||||
return 1 + inv_recenter_nonneg(v, m);
|
||||
} else {
|
||||
return MAX_PROB - inv_recenter_nonneg(v, MAX_PROB - 1 - m);
|
||||
}
|
||||
}
|
||||
|
||||
static int decode_term_subexp_(aom_reader *r ACCT_STR_PARAM) {
|
||||
if (!aom_read_bit(r, ACCT_STR_NAME))
|
||||
return aom_read_literal(r, 4, ACCT_STR_NAME);
|
||||
if (!aom_read_bit(r, ACCT_STR_NAME))
|
||||
return aom_read_literal(r, 4, ACCT_STR_NAME) + 16;
|
||||
if (!aom_read_bit(r, ACCT_STR_NAME))
|
||||
return aom_read_literal(r, 5, ACCT_STR_NAME) + 32;
|
||||
return decode_uniform(r, ACCT_STR_NAME) + 64;
|
||||
}
|
||||
|
||||
void av1_diff_update_prob_(aom_reader *r, aom_prob *p ACCT_STR_PARAM) {
|
||||
if (aom_read(r, DIFF_UPDATE_PROB, ACCT_STR_NAME)) {
|
||||
const int delp = decode_term_subexp(r, ACCT_STR_NAME);
|
||||
*p = (aom_prob)inv_remap_prob(delp, *p);
|
||||
}
|
||||
}
|
||||
32
third_party/aom/av1/decoder/dsubexp.h
vendored
Normal file
32
third_party/aom/av1/decoder/dsubexp.h
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AV1_DECODER_DSUBEXP_H_
|
||||
#define AV1_DECODER_DSUBEXP_H_
|
||||
|
||||
#include "aom_dsp/bitreader.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_ACCOUNTING
|
||||
#define av1_diff_update_prob(r, p, str) av1_diff_update_prob_(r, p, str)
|
||||
#else
|
||||
#define av1_diff_update_prob(r, p, str) av1_diff_update_prob_(r, p)
|
||||
#endif
|
||||
|
||||
void av1_diff_update_prob_(aom_reader *r, aom_prob *p ACCT_STR_PARAM);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
#endif // AV1_DECODER_DSUBEXP_H_
|
||||
194
third_party/aom/av1/decoder/dthread.c
vendored
Normal file
194
third_party/aom/av1/decoder/dthread.c
vendored
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include "./aom_config.h"
|
||||
#include "aom_mem/aom_mem.h"
|
||||
#include "av1/common/reconinter.h"
|
||||
#include "av1/decoder/dthread.h"
|
||||
#include "av1/decoder/decoder.h"
|
||||
|
||||
// #define DEBUG_THREAD
|
||||
|
||||
// TODO(hkuang): Clean up all the #ifdef in this file.
|
||||
void av1_frameworker_lock_stats(AVxWorker *const worker) {
|
||||
#if CONFIG_MULTITHREAD
|
||||
FrameWorkerData *const worker_data = worker->data1;
|
||||
pthread_mutex_lock(&worker_data->stats_mutex);
|
||||
#else
|
||||
(void)worker;
|
||||
#endif
|
||||
}
|
||||
|
||||
void av1_frameworker_unlock_stats(AVxWorker *const worker) {
|
||||
#if CONFIG_MULTITHREAD
|
||||
FrameWorkerData *const worker_data = worker->data1;
|
||||
pthread_mutex_unlock(&worker_data->stats_mutex);
|
||||
#else
|
||||
(void)worker;
|
||||
#endif
|
||||
}
|
||||
|
||||
void av1_frameworker_signal_stats(AVxWorker *const worker) {
|
||||
#if CONFIG_MULTITHREAD
|
||||
FrameWorkerData *const worker_data = worker->data1;
|
||||
|
||||
// TODO(hkuang): Fix the pthread_cond_broadcast in windows wrapper.
|
||||
#if defined(_WIN32) && !HAVE_PTHREAD_H
|
||||
pthread_cond_signal(&worker_data->stats_cond);
|
||||
#else
|
||||
pthread_cond_broadcast(&worker_data->stats_cond);
|
||||
#endif
|
||||
|
||||
#else
|
||||
(void)worker;
|
||||
#endif
|
||||
}
|
||||
|
||||
// This macro prevents thread_sanitizer from reporting known concurrent writes.
|
||||
#if defined(__has_feature)
|
||||
#if __has_feature(thread_sanitizer)
|
||||
#define BUILDING_WITH_TSAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// TODO(hkuang): Remove worker parameter as it is only used in debug code.
|
||||
void av1_frameworker_wait(AVxWorker *const worker, RefCntBuffer *const ref_buf,
|
||||
int row) {
|
||||
#if CONFIG_MULTITHREAD
|
||||
if (!ref_buf) return;
|
||||
|
||||
#ifndef BUILDING_WITH_TSAN
|
||||
// The following line of code will get harmless tsan error but it is the key
|
||||
// to get best performance.
|
||||
if (ref_buf->row >= row && ref_buf->buf.corrupted != 1) return;
|
||||
#endif
|
||||
|
||||
{
|
||||
// Find the worker thread that owns the reference frame. If the reference
|
||||
// frame has been fully decoded, it may not have owner.
|
||||
AVxWorker *const ref_worker = ref_buf->frame_worker_owner;
|
||||
FrameWorkerData *const ref_worker_data =
|
||||
(FrameWorkerData *)ref_worker->data1;
|
||||
const AV1Decoder *const pbi = ref_worker_data->pbi;
|
||||
|
||||
#ifdef DEBUG_THREAD
|
||||
{
|
||||
FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
|
||||
printf("%d %p worker is waiting for %d %p worker (%d) ref %d \r\n",
|
||||
worker_data->worker_id, worker, ref_worker_data->worker_id,
|
||||
ref_buf->frame_worker_owner, row, ref_buf->row);
|
||||
}
|
||||
#endif
|
||||
|
||||
av1_frameworker_lock_stats(ref_worker);
|
||||
while (ref_buf->row < row && pbi->cur_buf == ref_buf &&
|
||||
ref_buf->buf.corrupted != 1) {
|
||||
pthread_cond_wait(&ref_worker_data->stats_cond,
|
||||
&ref_worker_data->stats_mutex);
|
||||
}
|
||||
|
||||
if (ref_buf->buf.corrupted == 1) {
|
||||
FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
|
||||
av1_frameworker_unlock_stats(ref_worker);
|
||||
aom_internal_error(&worker_data->pbi->common.error,
|
||||
AOM_CODEC_CORRUPT_FRAME,
|
||||
"Worker %p failed to decode frame", worker);
|
||||
}
|
||||
av1_frameworker_unlock_stats(ref_worker);
|
||||
}
|
||||
#else
|
||||
(void)worker;
|
||||
(void)ref_buf;
|
||||
(void)row;
|
||||
(void)ref_buf;
|
||||
#endif // CONFIG_MULTITHREAD
|
||||
}
|
||||
|
||||
void av1_frameworker_broadcast(RefCntBuffer *const buf, int row) {
|
||||
#if CONFIG_MULTITHREAD
|
||||
AVxWorker *worker = buf->frame_worker_owner;
|
||||
|
||||
#ifdef DEBUG_THREAD
|
||||
{
|
||||
FrameWorkerData *const worker_data = (FrameWorkerData *)worker->data1;
|
||||
printf("%d %p worker decode to (%d) \r\n", worker_data->worker_id,
|
||||
buf->frame_worker_owner, row);
|
||||
}
|
||||
#endif
|
||||
|
||||
av1_frameworker_lock_stats(worker);
|
||||
buf->row = row;
|
||||
av1_frameworker_signal_stats(worker);
|
||||
av1_frameworker_unlock_stats(worker);
|
||||
#else
|
||||
(void)buf;
|
||||
(void)row;
|
||||
#endif // CONFIG_MULTITHREAD
|
||||
}
|
||||
|
||||
void av1_frameworker_copy_context(AVxWorker *const dst_worker,
|
||||
AVxWorker *const src_worker) {
|
||||
#if CONFIG_MULTITHREAD
|
||||
FrameWorkerData *const src_worker_data = (FrameWorkerData *)src_worker->data1;
|
||||
FrameWorkerData *const dst_worker_data = (FrameWorkerData *)dst_worker->data1;
|
||||
AV1_COMMON *const src_cm = &src_worker_data->pbi->common;
|
||||
AV1_COMMON *const dst_cm = &dst_worker_data->pbi->common;
|
||||
int i;
|
||||
|
||||
// Wait until source frame's context is ready.
|
||||
av1_frameworker_lock_stats(src_worker);
|
||||
while (!src_worker_data->frame_context_ready) {
|
||||
pthread_cond_wait(&src_worker_data->stats_cond,
|
||||
&src_worker_data->stats_mutex);
|
||||
}
|
||||
|
||||
dst_cm->last_frame_seg_map = src_cm->seg.enabled
|
||||
? src_cm->current_frame_seg_map
|
||||
: src_cm->last_frame_seg_map;
|
||||
dst_worker_data->pbi->need_resync = src_worker_data->pbi->need_resync;
|
||||
av1_frameworker_unlock_stats(src_worker);
|
||||
|
||||
dst_cm->bit_depth = src_cm->bit_depth;
|
||||
#if CONFIG_HIGHBITDEPTH
|
||||
dst_cm->use_highbitdepth = src_cm->use_highbitdepth;
|
||||
#endif
|
||||
#if CONFIG_EXT_REFS
|
||||
// TODO(zoeliu): To handle parallel decoding
|
||||
#endif // CONFIG_EXT_REFS
|
||||
dst_cm->prev_frame =
|
||||
src_cm->show_existing_frame ? src_cm->prev_frame : src_cm->cur_frame;
|
||||
dst_cm->last_width =
|
||||
!src_cm->show_existing_frame ? src_cm->width : src_cm->last_width;
|
||||
dst_cm->last_height =
|
||||
!src_cm->show_existing_frame ? src_cm->height : src_cm->last_height;
|
||||
dst_cm->subsampling_x = src_cm->subsampling_x;
|
||||
dst_cm->subsampling_y = src_cm->subsampling_y;
|
||||
dst_cm->frame_type = src_cm->frame_type;
|
||||
dst_cm->last_show_frame = !src_cm->show_existing_frame
|
||||
? src_cm->show_frame
|
||||
: src_cm->last_show_frame;
|
||||
for (i = 0; i < REF_FRAMES; ++i)
|
||||
dst_cm->ref_frame_map[i] = src_cm->next_ref_frame_map[i];
|
||||
|
||||
memcpy(dst_cm->lf_info.lfthr, src_cm->lf_info.lfthr,
|
||||
(MAX_LOOP_FILTER + 1) * sizeof(loop_filter_thresh));
|
||||
dst_cm->lf.last_sharpness_level = src_cm->lf.sharpness_level;
|
||||
dst_cm->lf.filter_level = src_cm->lf.filter_level;
|
||||
memcpy(dst_cm->lf.ref_deltas, src_cm->lf.ref_deltas, TOTAL_REFS_PER_FRAME);
|
||||
memcpy(dst_cm->lf.mode_deltas, src_cm->lf.mode_deltas, MAX_MODE_LF_DELTAS);
|
||||
dst_cm->seg = src_cm->seg;
|
||||
memcpy(dst_cm->frame_contexts, src_cm->frame_contexts,
|
||||
FRAME_CONTEXTS * sizeof(dst_cm->frame_contexts[0]));
|
||||
#else
|
||||
(void)dst_worker;
|
||||
(void)src_worker;
|
||||
#endif // CONFIG_MULTITHREAD
|
||||
}
|
||||
75
third_party/aom/av1/decoder/dthread.h
vendored
Normal file
75
third_party/aom/av1/decoder/dthread.h
vendored
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AV1_DECODER_DTHREAD_H_
|
||||
#define AV1_DECODER_DTHREAD_H_
|
||||
|
||||
#include "./aom_config.h"
|
||||
#include "aom_util/aom_thread.h"
|
||||
#include "aom/internal/aom_codec_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct AV1Common;
|
||||
struct AV1Decoder;
|
||||
|
||||
// WorkerData for the FrameWorker thread. It contains all the information of
|
||||
// the worker and decode structures for decoding a frame.
|
||||
typedef struct FrameWorkerData {
|
||||
struct AV1Decoder *pbi;
|
||||
const uint8_t *data;
|
||||
const uint8_t *data_end;
|
||||
size_t data_size;
|
||||
void *user_priv;
|
||||
int result;
|
||||
int worker_id;
|
||||
int received_frame;
|
||||
|
||||
// scratch_buffer is used in frame parallel mode only.
|
||||
// It is used to make a copy of the compressed data.
|
||||
uint8_t *scratch_buffer;
|
||||
size_t scratch_buffer_size;
|
||||
|
||||
#if CONFIG_MULTITHREAD
|
||||
pthread_mutex_t stats_mutex;
|
||||
pthread_cond_t stats_cond;
|
||||
#endif
|
||||
|
||||
int frame_context_ready; // Current frame's context is ready to read.
|
||||
int frame_decoded; // Finished decoding current frame.
|
||||
} FrameWorkerData;
|
||||
|
||||
void av1_frameworker_lock_stats(AVxWorker *const worker);
|
||||
void av1_frameworker_unlock_stats(AVxWorker *const worker);
|
||||
void av1_frameworker_signal_stats(AVxWorker *const worker);
|
||||
|
||||
// Wait until ref_buf has been decoded to row in real pixel unit.
|
||||
// Note: worker may already finish decoding ref_buf and release it in order to
|
||||
// start decoding next frame. So need to check whether worker is still decoding
|
||||
// ref_buf.
|
||||
void av1_frameworker_wait(AVxWorker *const worker, RefCntBuffer *const ref_buf,
|
||||
int row);
|
||||
|
||||
// FrameWorker broadcasts its decoding progress so other workers that are
|
||||
// waiting on it can resume decoding.
|
||||
void av1_frameworker_broadcast(RefCntBuffer *const buf, int row);
|
||||
|
||||
// Copy necessary decoding context from src worker to dst worker.
|
||||
void av1_frameworker_copy_context(AVxWorker *const dst_worker,
|
||||
AVxWorker *const src_worker);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // AV1_DECODER_DTHREAD_H_
|
||||
110
third_party/aom/av1/decoder/generic_decoder.c
vendored
Normal file
110
third_party/aom/av1/decoder/generic_decoder.c
vendored
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "aom_dsp/bitreader.h"
|
||||
#include "av1/common/generic_code.h"
|
||||
#include "av1/common/odintrin.h"
|
||||
#include "pvq_decoder.h"
|
||||
|
||||
/** Decodes a value from 0 to N-1 (with N up to 16) based on a cdf and adapts
|
||||
* the cdf accordingly.
|
||||
*
|
||||
* @param [in,out] r multi-symbol entropy decoder
|
||||
* @param [in,out] cdf CDF of the variable (Q15)
|
||||
* @param [in] n number of values possible
|
||||
* @param [in,out] count number of symbols encoded with that cdf so far
|
||||
* @param [in] rate adaptation rate shift (smaller is faster)
|
||||
* @return decoded variable
|
||||
*/
|
||||
int aom_decode_cdf_adapt_q15_(aom_reader *r, uint16_t *cdf, int n,
|
||||
int *count, int rate ACCT_STR_PARAM) {
|
||||
int val;
|
||||
int i;
|
||||
if (*count == 0) {
|
||||
int ft;
|
||||
ft = cdf[n - 1];
|
||||
for (i = 0; i < n; i++) {
|
||||
cdf[i] = AOM_ICDF(cdf[i]*32768/ft);
|
||||
}
|
||||
}
|
||||
val = aom_read_cdf(r, cdf, n, ACCT_STR_NAME);
|
||||
aom_cdf_adapt_q15(val, cdf, n, count, rate);
|
||||
return val;
|
||||
}
|
||||
|
||||
/** Encodes a random variable using a "generic" model, assuming that the
|
||||
* distribution is one-sided (zero and up), has a single mode, and decays
|
||||
* exponentially past the model.
|
||||
*
|
||||
* @param [in,out] r multi-symbol entropy decoder
|
||||
* @param [in,out] model generic probability model
|
||||
* @param [in] x variable being encoded
|
||||
* @param [in,out] ExQ16 expectation of x (adapted)
|
||||
* @param [in] integration integration period of ExQ16 (leaky average over
|
||||
* 1<<integration samples)
|
||||
*
|
||||
* @retval decoded variable x
|
||||
*/
|
||||
int generic_decode_(aom_reader *r, generic_encoder *model,
|
||||
int *ex_q16, int integration ACCT_STR_PARAM) {
|
||||
int lg_q1;
|
||||
int shift;
|
||||
int id;
|
||||
uint16_t *cdf;
|
||||
int xs;
|
||||
int lsb;
|
||||
int x;
|
||||
lsb = 0;
|
||||
lg_q1 = log_ex(*ex_q16);
|
||||
/* If expectation is too large, shift x to ensure that
|
||||
all we have past xs=15 is the exponentially decaying tail
|
||||
of the distribution. */
|
||||
shift = OD_MAXI(0, (lg_q1 - 5) >> 1);
|
||||
/* Choose the cdf to use: we have two per "octave" of ExQ16. */
|
||||
id = OD_MINI(GENERIC_TABLES - 1, lg_q1);
|
||||
cdf = model->cdf[id];
|
||||
xs = aom_read_symbol_pvq(r, cdf, 16, ACCT_STR_NAME);
|
||||
if (xs == 15) {
|
||||
int e;
|
||||
unsigned decay;
|
||||
/* Estimate decay based on the assumption that the distribution is close
|
||||
to Laplacian for large values. We should probably have an adaptive
|
||||
estimate instead. Note: The 2* is a kludge that's not fully understood
|
||||
yet. */
|
||||
OD_ASSERT(*ex_q16 < INT_MAX >> 1);
|
||||
e = ((2**ex_q16 >> 8) + (1 << shift >> 1)) >> shift;
|
||||
decay = OD_MAXI(2, OD_MINI(254, 256*e/(e + 256)));
|
||||
xs += aom_laplace_decode_special(r, decay, ACCT_STR_NAME);
|
||||
}
|
||||
if (shift != 0) {
|
||||
int special;
|
||||
/* Because of the rounding, there's only half the number of possibilities
|
||||
for xs=0 */
|
||||
special = xs == 0;
|
||||
if (shift - special > 0) {
|
||||
lsb = aom_read_literal(r, shift - special, ACCT_STR_NAME);
|
||||
}
|
||||
lsb -= !special << (shift - 1);
|
||||
}
|
||||
x = (xs << shift) + lsb;
|
||||
generic_model_update(ex_q16, x, integration);
|
||||
OD_LOG((OD_LOG_ENTROPY_CODER, OD_LOG_DEBUG,
|
||||
"dec: %d %d %d %d %d %x", *ex_q16, x, shift, id, xs, dec->rng));
|
||||
return x;
|
||||
}
|
||||
103
third_party/aom/av1/decoder/inspection.c
vendored
Normal file
103
third_party/aom/av1/decoder/inspection.c
vendored
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
#include "av1/decoder/decoder.h"
|
||||
#include "av1/decoder/inspection.h"
|
||||
#include "av1/common/enums.h"
|
||||
#if CONFIG_CDEF
|
||||
#include "av1/common/cdef.h"
|
||||
#endif
|
||||
|
||||
void ifd_init(insp_frame_data *fd, int frame_width, int frame_height) {
|
||||
fd->mi_cols = ALIGN_POWER_OF_TWO(frame_width, 3) >> MI_SIZE_LOG2;
|
||||
fd->mi_rows = ALIGN_POWER_OF_TWO(frame_height, 3) >> MI_SIZE_LOG2;
|
||||
fd->mi_grid = (insp_mi_data *)aom_malloc(sizeof(insp_mi_data) * fd->mi_rows *
|
||||
fd->mi_cols);
|
||||
}
|
||||
|
||||
void ifd_clear(insp_frame_data *fd) {
|
||||
aom_free(fd->mi_grid);
|
||||
fd->mi_grid = NULL;
|
||||
}
|
||||
|
||||
/* TODO(negge) This function may be called by more than one thread when using
|
||||
a multi-threaded decoder and this may cause a data race. */
|
||||
int ifd_inspect(insp_frame_data *fd, void *decoder) {
|
||||
struct AV1Decoder *pbi = (struct AV1Decoder *)decoder;
|
||||
AV1_COMMON *const cm = &pbi->common;
|
||||
// TODO(negge): Should this function just call ifd_clear() and ifd_init()?
|
||||
if (fd->mi_rows != cm->mi_rows || fd->mi_cols != cm->mi_cols) {
|
||||
return 0;
|
||||
}
|
||||
fd->show_frame = cm->show_frame;
|
||||
fd->frame_type = cm->frame_type;
|
||||
fd->base_qindex = cm->base_qindex;
|
||||
fd->tile_mi_cols = cm->tile_width;
|
||||
fd->tile_mi_rows = cm->tile_height;
|
||||
#if CONFIG_ACCOUNTING
|
||||
fd->accounting = &pbi->accounting;
|
||||
#endif
|
||||
#if CONFIG_CDEF
|
||||
// TODO(negge): copy per frame CDEF data
|
||||
#endif
|
||||
int i, j;
|
||||
for (i = 0; i < MAX_SEGMENTS; i++) {
|
||||
for (j = 0; j < 2; j++) {
|
||||
fd->y_dequant[i][j] = cm->y_dequant[i][j];
|
||||
fd->uv_dequant[i][j] = cm->uv_dequant[i][j];
|
||||
}
|
||||
}
|
||||
for (j = 0; j < cm->mi_rows; j++) {
|
||||
for (i = 0; i < cm->mi_cols; i++) {
|
||||
const MB_MODE_INFO *mbmi =
|
||||
&cm->mi_grid_visible[j * cm->mi_stride + i]->mbmi;
|
||||
insp_mi_data *mi = &fd->mi_grid[j * cm->mi_cols + i];
|
||||
// Segment
|
||||
mi->segment_id = mbmi->segment_id;
|
||||
// Motion Vectors
|
||||
mi->mv[0].row = mbmi->mv[0].as_mv.row;
|
||||
mi->mv[0].col = mbmi->mv[0].as_mv.col;
|
||||
mi->mv[1].row = mbmi->mv[1].as_mv.row;
|
||||
mi->mv[1].col = mbmi->mv[1].as_mv.col;
|
||||
// Reference Frames
|
||||
mi->ref_frame[0] = mbmi->ref_frame[0];
|
||||
mi->ref_frame[1] = mbmi->ref_frame[1];
|
||||
// Prediction Mode
|
||||
mi->mode = mbmi->mode;
|
||||
// Prediction Mode for Chromatic planes
|
||||
if (mi->mode < INTRA_MODES) {
|
||||
mi->uv_mode = mbmi->uv_mode;
|
||||
} else {
|
||||
mi->uv_mode = INTRA_INVALID;
|
||||
}
|
||||
// Block Size
|
||||
mi->sb_type = mbmi->sb_type;
|
||||
// Skip Flag
|
||||
mi->skip = mbmi->skip;
|
||||
#if CONFIG_DUAL_FILTER
|
||||
mi->filter[0] = mbmi->interp_filter[0];
|
||||
mi->filter[1] = mbmi->interp_filter[1];
|
||||
#else
|
||||
mi->filter = mbmi->interp_filter;
|
||||
#endif
|
||||
// Transform
|
||||
mi->tx_type = mbmi->tx_type;
|
||||
mi->tx_size = mbmi->tx_size;
|
||||
|
||||
#if CONFIG_CDEF
|
||||
mi->cdef_level = cm->cdef_strengths[mbmi->cdef_strength] / CLPF_STRENGTHS;
|
||||
mi->cdef_strength =
|
||||
cm->cdef_strengths[mbmi->cdef_strength] % CLPF_STRENGTHS;
|
||||
mi->cdef_strength += mi->cdef_strength == 3;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
82
third_party/aom/av1/decoder/inspection.h
vendored
Normal file
82
third_party/aom/av1/decoder/inspection.h
vendored
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
#ifndef AOM_INSPECTION_H_
|
||||
#define AOM_INSPECTION_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#if CONFIG_ACCOUNTING
|
||||
#include "av1/decoder/accounting.h"
|
||||
#endif
|
||||
|
||||
typedef void (*aom_inspect_cb)(void *decoder, void *data);
|
||||
|
||||
typedef struct insp_mv insp_mv;
|
||||
|
||||
struct insp_mv {
|
||||
int16_t row;
|
||||
int16_t col;
|
||||
};
|
||||
|
||||
typedef struct insp_mi_data insp_mi_data;
|
||||
|
||||
struct insp_mi_data {
|
||||
insp_mv mv[2];
|
||||
int8_t ref_frame[2];
|
||||
int8_t mode;
|
||||
int8_t uv_mode;
|
||||
int8_t sb_type;
|
||||
int8_t skip;
|
||||
int8_t segment_id;
|
||||
#if CONFIG_DUAL_FILTER
|
||||
int8_t filter[2];
|
||||
#else
|
||||
int8_t filter;
|
||||
#endif
|
||||
int8_t tx_type;
|
||||
int8_t tx_size;
|
||||
#if CONFIG_CDEF
|
||||
int8_t cdef_level;
|
||||
int8_t cdef_strength;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct insp_frame_data insp_frame_data;
|
||||
|
||||
struct insp_frame_data {
|
||||
#if CONFIG_ACCOUNTING
|
||||
Accounting *accounting;
|
||||
#endif
|
||||
insp_mi_data *mi_grid;
|
||||
int show_frame;
|
||||
int frame_type;
|
||||
int base_qindex;
|
||||
int mi_rows;
|
||||
int mi_cols;
|
||||
int tile_mi_rows;
|
||||
int tile_mi_cols;
|
||||
int16_t y_dequant[MAX_SEGMENTS][2];
|
||||
int16_t uv_dequant[MAX_SEGMENTS][2];
|
||||
#if CONFIG_CDEF
|
||||
// TODO(negge): add per frame CDEF data
|
||||
#endif
|
||||
};
|
||||
|
||||
void ifd_init(insp_frame_data *fd, int frame_width, int frame_height);
|
||||
void ifd_clear(insp_frame_data *fd);
|
||||
int ifd_inspect(insp_frame_data *fd, void *decoder);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
#endif // AOM_INSPECTION_H_
|
||||
121
third_party/aom/av1/decoder/laplace_decoder.c
vendored
Normal file
121
third_party/aom/av1/decoder/laplace_decoder.c
vendored
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
/* clang-format off */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "aom_dsp/bitreader.h"
|
||||
#include "av1/common/pvq.h"
|
||||
#include "pvq_decoder.h"
|
||||
|
||||
#define aom_decode_pvq_split(r, adapt, sum, ctx, ACCT_STR_NAME) \
|
||||
aom_decode_pvq_split_(r, adapt, sum, ctx ACCT_STR_ARG(ACCT_STR_NAME))
|
||||
|
||||
static int aom_decode_pvq_split_(aom_reader *r, od_pvq_codeword_ctx *adapt,
|
||||
int sum, int ctx ACCT_STR_PARAM) {
|
||||
int shift;
|
||||
int count;
|
||||
int msbs;
|
||||
int fctx;
|
||||
count = 0;
|
||||
if (sum == 0) return 0;
|
||||
shift = OD_MAXI(0, OD_ILOG(sum) - 3);
|
||||
fctx = 7*ctx + (sum >> shift) - 1;
|
||||
msbs = aom_read_symbol_pvq(r, adapt->pvq_split_cdf[fctx], (sum >> shift) + 1,
|
||||
ACCT_STR_NAME);
|
||||
if (shift) count = aom_read_literal(r, shift, ACCT_STR_NAME);
|
||||
count += msbs << shift;
|
||||
if (count > sum) {
|
||||
count = sum;
|
||||
#if CONFIG_DAALA_EC
|
||||
r->ec.error = 1;
|
||||
#else
|
||||
# error "CONFIG_PVQ currently requires CONFIG_DAALA_EC."
|
||||
#endif
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void aom_decode_band_pvq_splits(aom_reader *r, od_pvq_codeword_ctx *adapt,
|
||||
od_coeff *y, int n, int k, int level) {
|
||||
int mid;
|
||||
int count_right;
|
||||
if (n == 1) {
|
||||
y[0] = k;
|
||||
}
|
||||
else if (k == 0) {
|
||||
OD_CLEAR(y, n);
|
||||
}
|
||||
else if (k == 1 && n <= 16) {
|
||||
int cdf_id;
|
||||
int pos;
|
||||
cdf_id = od_pvq_k1_ctx(n, level == 0);
|
||||
OD_CLEAR(y, n);
|
||||
pos = aom_read_symbol_pvq(r, adapt->pvq_k1_cdf[cdf_id], n, "pvq:k1");
|
||||
y[pos] = 1;
|
||||
}
|
||||
else {
|
||||
mid = n >> 1;
|
||||
count_right = aom_decode_pvq_split(r, adapt, k, od_pvq_size_ctx(n),
|
||||
"pvq:split");
|
||||
aom_decode_band_pvq_splits(r, adapt, y, mid, k - count_right, level + 1);
|
||||
aom_decode_band_pvq_splits(r, adapt, y + mid, n - mid, count_right,
|
||||
level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/** Decodes the tail of a Laplace-distributed variable, i.e. it doesn't
|
||||
* do anything special for the zero case.
|
||||
*
|
||||
* @param [dec] range decoder
|
||||
* @param [decay] decay factor of the distribution, i.e. pdf ~= decay^x
|
||||
*
|
||||
* @retval decoded variable x
|
||||
*/
|
||||
int aom_laplace_decode_special_(aom_reader *r, unsigned decay ACCT_STR_PARAM) {
|
||||
int pos;
|
||||
int shift;
|
||||
int xs;
|
||||
int sym;
|
||||
const uint16_t *cdf;
|
||||
shift = 0;
|
||||
/* We don't want a large decay value because that would require too many
|
||||
symbols. */
|
||||
while (decay > 235) {
|
||||
decay = (decay*decay + 128) >> 8;
|
||||
shift++;
|
||||
}
|
||||
decay = OD_MINI(decay, 254);
|
||||
decay = OD_MAXI(decay, 2);
|
||||
cdf = EXP_CDF_TABLE[(decay + 1) >> 1];
|
||||
OD_LOG((OD_LOG_PVQ, OD_LOG_DEBUG, "decay = %d\n", decay));
|
||||
xs = 0;
|
||||
do {
|
||||
sym = OD_MINI(xs, 15);
|
||||
{
|
||||
int i;
|
||||
OD_LOG((OD_LOG_PVQ, OD_LOG_DEBUG, "%d %d %d", xs, shift, sym));
|
||||
for (i = 0; i < 16; i++) {
|
||||
OD_LOG_PARTIAL((OD_LOG_PVQ, OD_LOG_DEBUG, "%d ", cdf[i]));
|
||||
}
|
||||
OD_LOG_PARTIAL((OD_LOG_PVQ, OD_LOG_DEBUG, "\n"));
|
||||
}
|
||||
sym = aom_read_cdf(r, cdf, 16, ACCT_STR_NAME);
|
||||
xs += sym;
|
||||
} while (sym >= 15);
|
||||
if (shift) pos = (xs << shift) + aom_read_literal(r, shift, ACCT_STR_NAME);
|
||||
else pos = xs;
|
||||
return pos;
|
||||
}
|
||||
378
third_party/aom/av1/decoder/pvq_decoder.c
vendored
Normal file
378
third_party/aom/av1/decoder/pvq_decoder.c
vendored
Normal file
|
|
@ -0,0 +1,378 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "./aom_config.h"
|
||||
#include "aom_dsp/bitreader.h"
|
||||
#include "aom_dsp/entcode.h"
|
||||
#include "aom_dsp/entdec.h"
|
||||
#include "av1/common/odintrin.h"
|
||||
#include "av1/common/partition.h"
|
||||
#include "av1/common/pvq_state.h"
|
||||
#include "av1/decoder/decint.h"
|
||||
#include "av1/decoder/pvq_decoder.h"
|
||||
#include "aom_ports/system_state.h"
|
||||
|
||||
int aom_read_symbol_pvq_(aom_reader *r, aom_cdf_prob *cdf, int nsymbs
|
||||
ACCT_STR_PARAM) {
|
||||
if (cdf[0] == 0)
|
||||
aom_cdf_init_q15_1D(cdf, nsymbs, CDF_SIZE(nsymbs));
|
||||
return aom_read_symbol(r, cdf, nsymbs, ACCT_STR_NAME);
|
||||
}
|
||||
|
||||
static void aom_decode_pvq_codeword(aom_reader *r, od_pvq_codeword_ctx *ctx,
|
||||
od_coeff *y, int n, int k) {
|
||||
int i;
|
||||
aom_decode_band_pvq_splits(r, ctx, y, n, k, 0);
|
||||
for (i = 0; i < n; i++) {
|
||||
if (y[i] && aom_read_bit(r, "pvq:sign")) y[i] = -y[i];
|
||||
}
|
||||
}
|
||||
|
||||
/** Inverse of neg_interleave; decodes the interleaved gain.
|
||||
*
|
||||
* @param [in] x quantized/interleaved gain to decode
|
||||
* @param [in] ref quantized gain of the reference
|
||||
* @return original quantized gain value
|
||||
*/
|
||||
static int neg_deinterleave(int x, int ref) {
|
||||
if (x < 2*ref-1) {
|
||||
if (x & 1) return ref - 1 - (x >> 1);
|
||||
else return ref + (x >> 1);
|
||||
}
|
||||
else return x+1;
|
||||
}
|
||||
|
||||
/** Synthesizes one parition of coefficient values from a PVQ-encoded
|
||||
* vector.
|
||||
*
|
||||
* @param [out] xcoeff output coefficient partition (x in math doc)
|
||||
* @param [in] ypulse PVQ-encoded values (y in math doc); in the noref
|
||||
* case, this vector has n entries, in the
|
||||
* reference case it contains n-1 entries
|
||||
* (the m-th entry is not included)
|
||||
* @param [in] ref reference vector (prediction)
|
||||
* @param [in] n number of elements in this partition
|
||||
* @param [in] gr gain of the reference vector (prediction)
|
||||
* @param [in] noref indicates presence or lack of prediction
|
||||
* @param [in] g decoded quantized vector gain
|
||||
* @param [in] theta decoded theta (prediction error)
|
||||
* @param [in] qm QM with magnitude compensation
|
||||
* @param [in] qm_inv Inverse of QM with magnitude compensation
|
||||
*/
|
||||
static void pvq_synthesis(od_coeff *xcoeff, od_coeff *ypulse, od_val16 *r16,
|
||||
int n, od_val32 gr, int noref, od_val32 g, od_val32 theta, const int16_t *qm_inv,
|
||||
int shift) {
|
||||
int s;
|
||||
int m;
|
||||
/* Sign of the Householder reflection vector */
|
||||
s = 0;
|
||||
/* Direction of the Householder reflection vector */
|
||||
m = noref ? 0 : od_compute_householder(r16, n, gr, &s, shift);
|
||||
od_pvq_synthesis_partial(xcoeff, ypulse, r16, n, noref, g, theta, m, s,
|
||||
qm_inv);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
od_coeff *ref;
|
||||
int nb_coeffs;
|
||||
int allow_flip;
|
||||
} cfl_ctx;
|
||||
|
||||
/** Decodes a single vector of integers (eg, a partition within a
|
||||
* coefficient block) encoded using PVQ
|
||||
*
|
||||
* @param [in,out] ec range encoder
|
||||
* @param [in] q0 scale/quantizer
|
||||
* @param [in] n number of coefficients in partition
|
||||
* @param [in,out] model entropy decoder state
|
||||
* @param [in,out] adapt adaptation context
|
||||
* @param [in,out] exg ExQ16 expectation of decoded gain value
|
||||
* @param [in,out] ext ExQ16 expectation of decoded theta value
|
||||
* @param [in] ref 'reference' (prediction) vector
|
||||
* @param [out] out decoded partition
|
||||
* @param [out] noref boolean indicating absence of reference
|
||||
* @param [in] beta per-band activity masking beta param
|
||||
* @param [in] is_keyframe whether we're encoding a keyframe
|
||||
* @param [in] pli plane index
|
||||
* @param [in] cdf_ctx selects which cdf context to use
|
||||
* @param [in,out] skip_rest whether to skip further bands in each direction
|
||||
* @param [in] band index of the band being decoded
|
||||
* @param [in] band index of the band being decoded
|
||||
* @param [out] skip skip flag with range [0,1]
|
||||
* @param [in] qm QM with magnitude compensation
|
||||
* @param [in] qm_inv Inverse of QM with magnitude compensation
|
||||
*/
|
||||
static void pvq_decode_partition(aom_reader *r,
|
||||
int q0,
|
||||
int n,
|
||||
generic_encoder model[3],
|
||||
od_adapt_ctx *adapt,
|
||||
int *exg,
|
||||
int *ext,
|
||||
od_coeff *ref,
|
||||
od_coeff *out,
|
||||
int *noref,
|
||||
od_val16 beta,
|
||||
int is_keyframe,
|
||||
int pli,
|
||||
int cdf_ctx,
|
||||
cfl_ctx *cfl,
|
||||
int has_skip,
|
||||
int *skip_rest,
|
||||
int band,
|
||||
int *skip,
|
||||
const int16_t *qm,
|
||||
const int16_t *qm_inv) {
|
||||
int k;
|
||||
od_val32 qcg;
|
||||
int itheta;
|
||||
od_val32 theta;
|
||||
od_val32 gr;
|
||||
od_val32 gain_offset;
|
||||
od_coeff y[MAXN];
|
||||
int qg;
|
||||
int id;
|
||||
int i;
|
||||
od_val16 ref16[MAXN];
|
||||
int rshift;
|
||||
theta = 0;
|
||||
gr = 0;
|
||||
gain_offset = 0;
|
||||
/* Skip is per-direction. For band=0, we can use any of the flags. */
|
||||
if (skip_rest[(band + 2) % 3]) {
|
||||
qg = 0;
|
||||
if (is_keyframe) {
|
||||
itheta = -1;
|
||||
*noref = 1;
|
||||
}
|
||||
else {
|
||||
itheta = 0;
|
||||
*noref = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Jointly decode gain, itheta and noref for small values. Then we handle
|
||||
larger gain. */
|
||||
id = aom_read_symbol_pvq(r, &adapt->pvq.pvq_gaintheta_cdf[cdf_ctx][0],
|
||||
8 + 7*has_skip, "pvq:gaintheta");
|
||||
if (!is_keyframe && id >= 10) id++;
|
||||
if (is_keyframe && id >= 8) id++;
|
||||
if (id >= 8) {
|
||||
id -= 8;
|
||||
skip_rest[0] = skip_rest[1] = skip_rest[2] = 1;
|
||||
}
|
||||
qg = id & 1;
|
||||
itheta = (id >> 1) - 1;
|
||||
*noref = (itheta == -1);
|
||||
}
|
||||
/* The CfL flip bit is only decoded on the first band that has noref=0. */
|
||||
if (cfl->allow_flip && !*noref) {
|
||||
int flip;
|
||||
flip = aom_read_bit(r, "cfl:flip");
|
||||
if (flip) {
|
||||
for (i = 0; i < cfl->nb_coeffs; i++) cfl->ref[i] = -cfl->ref[i];
|
||||
}
|
||||
cfl->allow_flip = 0;
|
||||
}
|
||||
if (qg > 0) {
|
||||
int tmp;
|
||||
tmp = *exg;
|
||||
qg = 1 + generic_decode(r, &model[!*noref], &tmp, 2, "pvq:gain");
|
||||
OD_IIR_DIADIC(*exg, qg << 16, 2);
|
||||
}
|
||||
*skip = 0;
|
||||
#if defined(OD_FLOAT_PVQ)
|
||||
rshift = 0;
|
||||
#else
|
||||
/* Shift needed to make the reference fit in 15 bits, so that the Householder
|
||||
vector can fit in 16 bits. */
|
||||
rshift = OD_MAXI(0, od_vector_log_mag(ref, n) - 14);
|
||||
#endif
|
||||
for (i = 0; i < n; i++) {
|
||||
#if defined(OD_FLOAT_PVQ)
|
||||
ref16[i] = ref[i]*(double)qm[i]*OD_QM_SCALE_1;
|
||||
#else
|
||||
ref16[i] = OD_SHR_ROUND(ref[i]*qm[i], OD_QM_SHIFT + rshift);
|
||||
#endif
|
||||
}
|
||||
if(!*noref){
|
||||
/* we have a reference; compute its gain */
|
||||
od_val32 cgr;
|
||||
int icgr;
|
||||
int cfl_enabled;
|
||||
cfl_enabled = pli != 0 && is_keyframe && !OD_DISABLE_CFL;
|
||||
cgr = od_pvq_compute_gain(ref16, n, q0, &gr, beta, rshift);
|
||||
if (cfl_enabled) cgr = OD_CGAIN_SCALE;
|
||||
#if defined(OD_FLOAT_PVQ)
|
||||
icgr = (int)floor(.5 + cgr);
|
||||
#else
|
||||
icgr = OD_SHR_ROUND(cgr, OD_CGAIN_SHIFT);
|
||||
#endif
|
||||
/* quantized gain is interleave encoded when there's a reference;
|
||||
deinterleave it now */
|
||||
if (is_keyframe) qg = neg_deinterleave(qg, icgr);
|
||||
else {
|
||||
qg = neg_deinterleave(qg, icgr + 1) - 1;
|
||||
if (qg == 0) *skip = (icgr ? OD_PVQ_SKIP_ZERO : OD_PVQ_SKIP_COPY);
|
||||
}
|
||||
if (qg == icgr && itheta == 0 && !cfl_enabled) *skip = OD_PVQ_SKIP_COPY;
|
||||
gain_offset = cgr - OD_SHL(icgr, OD_CGAIN_SHIFT);
|
||||
qcg = OD_SHL(qg, OD_CGAIN_SHIFT) + gain_offset;
|
||||
/* read and decode first-stage PVQ error theta */
|
||||
if (itheta > 1) {
|
||||
int tmp;
|
||||
tmp = *ext;
|
||||
itheta = 2 + generic_decode(r, &model[2], &tmp, 2, "pvq:theta");
|
||||
OD_IIR_DIADIC(*ext, itheta << 16, 2);
|
||||
}
|
||||
theta = od_pvq_compute_theta(itheta, od_pvq_compute_max_theta(qcg, beta));
|
||||
}
|
||||
else{
|
||||
itheta = 0;
|
||||
if (!is_keyframe) qg++;
|
||||
qcg = OD_SHL(qg, OD_CGAIN_SHIFT);
|
||||
if (qg == 0) *skip = OD_PVQ_SKIP_ZERO;
|
||||
}
|
||||
|
||||
k = od_pvq_compute_k(qcg, itheta, *noref, n, beta);
|
||||
if (k != 0) {
|
||||
/* when noref==0, y is actually size n-1 */
|
||||
aom_decode_pvq_codeword(r, &adapt->pvq.pvq_codeword_ctx, y,
|
||||
n - !*noref, k);
|
||||
}
|
||||
else {
|
||||
OD_CLEAR(y, n);
|
||||
}
|
||||
if (*skip) {
|
||||
if (*skip == OD_PVQ_SKIP_COPY) OD_COPY(out, ref, n);
|
||||
else OD_CLEAR(out, n);
|
||||
}
|
||||
else {
|
||||
od_val32 g;
|
||||
g = od_gain_expand(qcg, q0, beta);
|
||||
pvq_synthesis(out, y, ref16, n, gr, *noref, g, theta, qm_inv, rshift);
|
||||
}
|
||||
/* If OD_PVQ_SKIP_ZERO or OD_PVQ_SKIP_COPY, set skip to 1 for visualization */
|
||||
if (*skip) *skip = 1;
|
||||
}
|
||||
|
||||
/** Decodes a coefficient block (except for DC) encoded using PVQ
|
||||
*
|
||||
* @param [in,out] dec daala decoder context
|
||||
* @param [in] ref 'reference' (prediction) vector
|
||||
* @param [out] out decoded partition
|
||||
* @param [in] q0 quantizer
|
||||
* @param [in] pli plane index
|
||||
* @param [in] bs log of the block size minus two
|
||||
* @param [in] beta per-band activity masking beta param
|
||||
* @param [in] is_keyframe whether we're encoding a keyframe
|
||||
* @param [out] flags bitmask of the per band skip and noref flags
|
||||
* @param [in] ac_dc_coded skip flag for the block (range 0-3)
|
||||
* @param [in] qm QM with magnitude compensation
|
||||
* @param [in] qm_inv Inverse of QM with magnitude compensation
|
||||
*/
|
||||
void od_pvq_decode(daala_dec_ctx *dec,
|
||||
od_coeff *ref,
|
||||
od_coeff *out,
|
||||
int q0,
|
||||
int pli,
|
||||
int bs,
|
||||
const od_val16 *beta,
|
||||
int is_keyframe,
|
||||
unsigned int *flags,
|
||||
PVQ_SKIP_TYPE ac_dc_coded,
|
||||
const int16_t *qm,
|
||||
const int16_t *qm_inv){
|
||||
|
||||
int noref[PVQ_MAX_PARTITIONS];
|
||||
int skip[PVQ_MAX_PARTITIONS];
|
||||
int *exg;
|
||||
int *ext;
|
||||
int nb_bands;
|
||||
int i;
|
||||
const int *off;
|
||||
int size[PVQ_MAX_PARTITIONS];
|
||||
generic_encoder *model;
|
||||
int skip_rest[3] = {0};
|
||||
cfl_ctx cfl;
|
||||
const unsigned char *pvq_qm;
|
||||
int use_masking;
|
||||
|
||||
aom_clear_system_state();
|
||||
|
||||
/*Default to skip=1 and noref=0 for all bands.*/
|
||||
for (i = 0; i < PVQ_MAX_PARTITIONS; i++) {
|
||||
noref[i] = 0;
|
||||
skip[i] = 1;
|
||||
}
|
||||
|
||||
use_masking = dec->use_activity_masking;
|
||||
|
||||
if (use_masking)
|
||||
pvq_qm = &dec->state.pvq_qm_q4[pli][0];
|
||||
else
|
||||
pvq_qm = 0;
|
||||
|
||||
exg = &dec->state.adapt->pvq.pvq_exg[pli][bs][0];
|
||||
ext = dec->state.adapt->pvq.pvq_ext + bs*PVQ_MAX_PARTITIONS;
|
||||
model = dec->state.adapt->pvq.pvq_param_model;
|
||||
nb_bands = OD_BAND_OFFSETS[bs][0];
|
||||
off = &OD_BAND_OFFSETS[bs][1];
|
||||
out[0] = ac_dc_coded & DC_CODED;
|
||||
if (ac_dc_coded < AC_CODED) {
|
||||
if (is_keyframe) for (i = 1; i < 1 << (2*bs + 4); i++) out[i] = 0;
|
||||
else for (i = 1; i < 1 << (2*bs + 4); i++) out[i] = ref[i];
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < nb_bands; i++) size[i] = off[i+1] - off[i];
|
||||
cfl.ref = ref;
|
||||
cfl.nb_coeffs = off[nb_bands];
|
||||
cfl.allow_flip = pli != 0 && is_keyframe;
|
||||
for (i = 0; i < nb_bands; i++) {
|
||||
int q;
|
||||
|
||||
if (use_masking)
|
||||
q = OD_MAXI(1, q0 * pvq_qm[od_qm_get_index(bs, i + 1)] >> 4);
|
||||
else
|
||||
q = OD_MAXI(1, q0);
|
||||
|
||||
pvq_decode_partition(dec->r, q, size[i],
|
||||
model, dec->state.adapt, exg + i, ext + i, ref + off[i], out + off[i],
|
||||
&noref[i], beta[i], is_keyframe, pli,
|
||||
(pli != 0)*OD_TXSIZES*PVQ_MAX_PARTITIONS + bs*PVQ_MAX_PARTITIONS + i,
|
||||
&cfl, i == 0 && (i < nb_bands - 1), skip_rest, i, &skip[i],
|
||||
qm + off[i], qm_inv + off[i]);
|
||||
if (i == 0 && !skip_rest[0] && bs > 0) {
|
||||
int skip_dir;
|
||||
int j;
|
||||
skip_dir = aom_read_symbol(dec->r,
|
||||
&dec->state.adapt->pvq.pvq_skip_dir_cdf[(pli != 0) + 2*(bs - 1)][0], 7,
|
||||
"pvq:skiprest");
|
||||
for (j = 0; j < 3; j++) skip_rest[j] = !!(skip_dir & (1 << j));
|
||||
}
|
||||
}
|
||||
}
|
||||
*flags = 0;
|
||||
for (i = nb_bands - 1; i >= 0; i--) {
|
||||
*flags <<= 1;
|
||||
*flags |= noref[i]&1;
|
||||
*flags <<= 1;
|
||||
*flags |= skip[i]&1;
|
||||
}
|
||||
}
|
||||
40
third_party/aom/av1/decoder/pvq_decoder.h
vendored
Normal file
40
third_party/aom/av1/decoder/pvq_decoder.h
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#if !defined(_pvq_decoder_H)
|
||||
# define _pvq_decoder_H (1)
|
||||
# include "aom_dsp/bitreader.h"
|
||||
# include "aom_dsp/entdec.h"
|
||||
# include "av1/common/pvq.h"
|
||||
# include "av1/decoder/decint.h"
|
||||
|
||||
#define aom_read_symbol_pvq(r, cdf, nsymbs, ACCT_STR_NAME) \
|
||||
aom_read_symbol_pvq_(r, cdf, nsymbs ACCT_STR_ARG(ACCT_STR_NAME))
|
||||
|
||||
int aom_read_symbol_pvq_(aom_reader *r, aom_cdf_prob *cdf, int nsymbs
|
||||
ACCT_STR_PARAM);
|
||||
|
||||
void aom_decode_band_pvq_splits(aom_reader *r, od_pvq_codeword_ctx *adapt,
|
||||
od_coeff *y, int n, int k, int level);
|
||||
|
||||
#define aom_laplace_decode_special(r, decay, ACCT_STR_NAME) \
|
||||
aom_laplace_decode_special_(r, decay ACCT_STR_ARG(ACCT_STR_NAME))
|
||||
|
||||
int aom_laplace_decode_special_(aom_reader *r, unsigned decay ACCT_STR_PARAM);
|
||||
|
||||
void od_pvq_decode(daala_dec_ctx *dec, od_coeff *ref, od_coeff *out, int q0,
|
||||
int pli, int bs, const od_val16 *beta, int is_keyframe,
|
||||
unsigned int *flags, PVQ_SKIP_TYPE ac_dc_coded, const int16_t *qm,
|
||||
const int16_t *qm_inv);
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue