summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Userland/Libraries/LibVideo/VP9/Enums.h10
-rw-r--r--Userland/Libraries/LibVideo/VP9/Parser.cpp107
-rw-r--r--Userland/Libraries/LibVideo/VP9/Parser.h22
-rw-r--r--Userland/Libraries/LibVideo/VP9/TreeParser.cpp50
4 files changed, 143 insertions, 46 deletions
diff --git a/Userland/Libraries/LibVideo/VP9/Enums.h b/Userland/Libraries/LibVideo/VP9/Enums.h
index 94e6ca9579..a478e7beb1 100644
--- a/Userland/Libraries/LibVideo/VP9/Enums.h
+++ b/Userland/Libraries/LibVideo/VP9/Enums.h
@@ -32,7 +32,7 @@ enum ColorRange {
FullSwing
};
-enum InterpolationFilter {
+enum InterpolationFilter : u8 {
EightTap = 0,
EightTapSmooth = 1,
EightTapSharp = 2,
@@ -40,7 +40,7 @@ enum InterpolationFilter {
Switchable = 4
};
-enum ReferenceFrame {
+enum ReferenceFrame : u8 {
// 0 is both INTRA_FRAME and NONE because the value's meaning changes depending on which index they're in on the ref_frame array
None = 0,
IntraFrame = 0,
@@ -49,7 +49,7 @@ enum ReferenceFrame {
AltRefFrame = 3,
};
-enum TXMode {
+enum TXMode : u8 {
Only_4x4 = 0,
Allow_8x8 = 1,
Allow_16x16 = 2,
@@ -57,14 +57,14 @@ enum TXMode {
TXModeSelect = 4,
};
-enum TXSize {
+enum TXSize : u8 {
TX_4x4 = 0,
TX_8x8 = 1,
TX_16x16 = 2,
TX_32x32 = 3,
};
-enum ReferenceMode {
+enum ReferenceMode : u8 {
SingleReference = 0,
CompoundReference = 1,
ReferenceModeSelect = 2,
diff --git a/Userland/Libraries/LibVideo/VP9/Parser.cpp b/Userland/Libraries/LibVideo/VP9/Parser.cpp
index 2dd82741b3..edae871a7c 100644
--- a/Userland/Libraries/LibVideo/VP9/Parser.cpp
+++ b/Userland/Libraries/LibVideo/VP9/Parser.cpp
@@ -21,6 +21,37 @@ Parser::Parser(Decoder& decoder)
{
}
+Parser::~Parser()
+{
+ cleanup_tile_allocations();
+ if (m_prev_segment_ids)
+ free(m_prev_segment_ids);
+}
+
+void Parser::cleanup_tile_allocations()
+{
+ if (m_skips)
+ free(m_skips);
+ if (m_tx_sizes)
+ free(m_tx_sizes);
+ if (m_mi_sizes)
+ free(m_mi_sizes);
+ if (m_y_modes)
+ free(m_y_modes);
+ if (m_segment_ids)
+ free(m_segment_ids);
+ if (m_ref_frames)
+ free(m_ref_frames);
+ if (m_interp_filters)
+ free(m_interp_filters);
+ if (m_mvs)
+ free(m_mvs);
+ if (m_sub_mvs)
+ free(m_sub_mvs);
+ if (m_sub_modes)
+ free(m_sub_modes);
+}
+
/* (6.1) */
bool Parser::parse_frame(ByteBuffer const& frame_data)
{
@@ -400,15 +431,9 @@ bool Parser::setup_past_independence()
}
}
m_segmentation_abs_or_delta_update = false;
- m_prev_segment_ids.clear();
- m_prev_segment_ids.ensure_capacity(m_mi_rows);
- for (auto row = 0u; row < m_mi_rows; row++) {
- Vector<u8> sub_vector = {};
- sub_vector.ensure_capacity(m_mi_cols);
- for (auto col = 0u; col < m_mi_cols; col++)
- sub_vector.append(0);
- m_prev_segment_ids.append(sub_vector);
- }
+ if (m_prev_segment_ids)
+ free(m_prev_segment_ids);
+ m_prev_segment_ids = static_cast<u8*>(malloc(m_mi_rows * m_mi_cols));
m_loop_filter_delta_enabled = true;
m_loop_filter_ref_deltas[IntraFrame] = 1;
m_loop_filter_ref_deltas[LastFrame] = 0;
@@ -714,10 +739,30 @@ bool Parser::setup_compound_reference_mode()
return true;
}
+void Parser::allocate_tile_data()
+{
+ auto dimensions = m_mi_rows * m_mi_cols;
+ if (dimensions == m_allocated_dimensions)
+ return;
+ cleanup_tile_allocations();
+ m_skips = static_cast<bool*>(malloc(sizeof(bool) * dimensions));
+ m_tx_sizes = static_cast<TXSize*>(malloc(sizeof(TXSize) * dimensions));
+ m_mi_sizes = static_cast<u32*>(malloc(sizeof(u32) * dimensions));
+ m_y_modes = static_cast<u8*>(malloc(sizeof(u8) * dimensions));
+ m_segment_ids = static_cast<u8*>(malloc(sizeof(u8) * dimensions));
+ m_ref_frames = static_cast<ReferenceFrame*>(malloc(sizeof(ReferenceFrame) * dimensions * 2));
+ m_interp_filters = static_cast<InterpolationFilter*>(malloc(sizeof(InterpolationFilter) * dimensions));
+ m_mvs = static_cast<InterMode*>(malloc(sizeof(InterMode) * dimensions * 2));
+ m_sub_mvs = static_cast<InterMode*>(malloc(sizeof(InterMode) * dimensions * 2 * 4));
+ m_sub_modes = static_cast<IntraMode*>(malloc(sizeof(IntraMode) * dimensions * 4));
+ m_allocated_dimensions = dimensions;
+}
+
bool Parser::decode_tiles()
{
auto tile_cols = 1 << m_tile_cols_log2;
auto tile_rows = 1 << m_tile_rows_log2;
+ allocate_tile_data();
SAFE_CALL(clear_above_context());
for (auto tile_row = 0; tile_row < tile_rows; tile_row++) {
for (auto tile_col = 0; tile_col < tile_cols; tile_col++) {
@@ -732,7 +777,6 @@ bool Parser::decode_tiles()
SAFE_CALL(m_bit_stream->exit_bool());
}
}
-
return true;
}
@@ -833,8 +877,32 @@ bool Parser::decode_block(u32 row, u32 col, u8 subsize)
SAFE_CALL(mode_info());
m_eob_total = 0;
SAFE_CALL(residual());
- // FIXME: Finish implementing
- // note: when finished, re-enable calculate_default_intra_mode_probability's usage of m_sub_modes
+ if (m_is_inter && subsize >= Block_8x8 && m_eob_total == 0)
+ m_skip = true;
+ for (size_t y = 0; y < num_8x8_blocks_high_lookup[subsize]; y++) {
+ for (size_t x = 0; x < num_8x8_blocks_wide_lookup[subsize]; x++) {
+ auto pos = (row + y) * m_mi_cols + (col + x);
+ m_skips[pos] = m_skip;
+ m_tx_sizes[pos] = m_tx_size;
+ m_mi_sizes[pos] = m_mi_size;
+ m_y_modes[pos] = m_y_mode;
+ m_segment_ids[pos] = m_segment_id;
+ for (size_t ref_list = 0; ref_list < 2; ref_list++)
+ m_ref_frames[(pos * 2) + ref_list] = m_ref_frame[ref_list];
+ if (m_is_inter) {
+ m_interp_filters[pos] = m_interp_filter;
+ for (size_t ref_list = 0; ref_list < 2; ref_list++) {
+ auto pos_with_ref_list = pos * 2 + ref_list;
+ m_mvs[pos_with_ref_list] = m_block_mvs[ref_list][3];
+ for (size_t b = 0; b < 4; b++)
+ m_sub_mvs[pos_with_ref_list * 4 + b] = m_block_mvs[ref_list][b];
+ }
+ } else {
+ for (size_t b = 0; b < 4; b++)
+ m_sub_modes[pos * 4 + b] = static_cast<IntraMode>(m_block_sub_modes[b]);
+ }
+ }
+ }
return true;
}
@@ -916,10 +984,10 @@ bool Parser::read_tx_size(bool allow_select)
bool Parser::inter_frame_mode_info()
{
- m_left_ref_frame[0] = m_available_l ? m_ref_frames[m_mi_row][m_mi_col - 1][0] : IntraFrame;
- m_above_ref_frame[0] = m_available_u ? m_ref_frames[m_mi_row - 1][m_mi_col][0] : IntraFrame;
- m_left_ref_frame[1] = m_available_l ? m_ref_frames[m_mi_row][m_mi_col - 1][1] : None;
- m_above_ref_frame[1] = m_available_u ? m_ref_frames[m_mi_row - 1][m_mi_col][1] : None;
+ m_left_ref_frame[0] = m_available_l ? m_ref_frames[m_mi_row * m_mi_cols + (m_mi_col - 1)] : IntraFrame;
+ m_above_ref_frame[0] = m_available_u ? m_ref_frames[(m_mi_row - 1) * m_mi_cols + m_mi_col] : IntraFrame;
+ m_left_ref_frame[1] = m_available_l ? m_ref_frames[m_mi_row * m_mi_cols + (m_mi_col - 1) + 1] : None;
+ m_above_ref_frame[1] = m_available_u ? m_ref_frames[(m_mi_row - 1) * m_mi_cols + m_mi_col + 1] : None;
m_left_intra = m_left_ref_frame[0] <= IntraFrame;
m_above_intra = m_above_ref_frame[0] <= IntraFrame;
m_left_single = m_left_ref_frame[1] <= None;
@@ -973,7 +1041,7 @@ u8 Parser::get_segment_id()
u8 segment = 7;
for (size_t y = 0; y < ymis; y++) {
for (size_t x = 0; x < xmis; x++) {
- segment = min(segment, m_prev_segment_ids[m_mi_row + y][m_mi_col + x]);
+ segment = min(segment, m_prev_segment_ids[(m_mi_row + y) + (m_mi_col + x)]);
}
}
return segment;
@@ -1051,8 +1119,7 @@ bool Parser::inter_block_mode_info()
for (auto x = 0; x < m_num_4x4_w; x++) {
auto block = (idy + y) * 2 + idx + x;
for (auto ref_list = 0; ref_list < 1 + is_compound; ref_list++) {
- (void)block;
- // TODO: m_block_mvs[ref_list][block] = m_mv[ref_list];
+ m_block_mvs[ref_list][block] = m_mv[ref_list];
}
}
}
@@ -1063,7 +1130,7 @@ bool Parser::inter_block_mode_info()
SAFE_CALL(assign_mv(is_compound));
for (auto ref_list = 0; ref_list < 1 + is_compound; ref_list++) {
for (auto block = 0; block < 4; block++) {
- // TODO: m_block_mvs[ref_list][block] = m_mv[ref_list];
+ m_block_mvs[ref_list][block] = m_mv[ref_list];
}
}
return true;
diff --git a/Userland/Libraries/LibVideo/VP9/Parser.h b/Userland/Libraries/LibVideo/VP9/Parser.h
index 0382be9fdb..8b1061652e 100644
--- a/Userland/Libraries/LibVideo/VP9/Parser.h
+++ b/Userland/Libraries/LibVideo/VP9/Parser.h
@@ -24,6 +24,7 @@ class Parser {
public:
explicit Parser(Decoder&);
+ ~Parser();
bool parse_frame(ByteBuffer const&);
void dump_info();
@@ -45,6 +46,8 @@ private:
/* Utilities */
void clear_context(Vector<u8>& context, size_t size);
void clear_context(Vector<Vector<u8>>& context, size_t outer_size, size_t inner_size);
+ void allocate_tile_data();
+ void cleanup_tile_allocations();
/* (6.1) Frame Syntax */
bool trailing_bits();
@@ -208,30 +211,39 @@ private:
u8 m_uv_mode { 0 }; // FIXME: Is u8 the right size?
ReferenceFrame m_left_ref_frame[2];
ReferenceFrame m_above_ref_frame[2];
- Vector<Vector<Vector<ReferenceFrame>>> m_ref_frames; // TODO: Can we make these fixed sized allocations?
bool m_left_intra { false };
bool m_above_intra { false };
bool m_left_single { false };
bool m_above_single { false };
- Vector<Vector<u8>> m_prev_segment_ids;
InterpolationFilter m_interp_filter { EightTap };
InterMode m_mv[2];
InterMode m_near_mv[2];
InterMode m_nearest_mv[2];
- Vector<Vector<Vector<IntraMode>>> m_sub_modes; // FIXME: Can we make these fixed sized allocations?
u32 m_ref_frame_width[NUM_REF_FRAMES];
u32 m_ref_frame_height[NUM_REF_FRAMES];
u32 m_eob_total { 0 };
u8 m_tx_type { 0 };
u8 m_token_cache[1024];
i32 m_tokens[1024];
-
bool m_use_hp { false };
-
TXMode m_tx_mode;
ReferenceMode m_reference_mode;
ReferenceFrame m_comp_fixed_ref;
ReferenceFrame m_comp_var_ref[2];
+ InterMode m_block_mvs[2][4];
+ u8* m_prev_segment_ids { nullptr };
+
+ u32 m_allocated_dimensions { 0 };
+ bool* m_skips { nullptr };
+ TXSize* m_tx_sizes { nullptr };
+ u32* m_mi_sizes { nullptr };
+ u8* m_y_modes { nullptr };
+ u8* m_segment_ids { nullptr };
+ ReferenceFrame* m_ref_frames { nullptr };
+ InterpolationFilter* m_interp_filters { nullptr };
+ InterMode* m_mvs { nullptr };
+ InterMode* m_sub_mvs { nullptr };
+ IntraMode* m_sub_modes { nullptr };
OwnPtr<BitStream> m_bit_stream;
OwnPtr<ProbabilityTables> m_probability_tables;
diff --git a/Userland/Libraries/LibVideo/VP9/TreeParser.cpp b/Userland/Libraries/LibVideo/VP9/TreeParser.cpp
index 47b7a14e19..aeb71a7930 100644
--- a/Userland/Libraries/LibVideo/VP9/TreeParser.cpp
+++ b/Userland/Libraries/LibVideo/VP9/TreeParser.cpp
@@ -208,26 +208,26 @@ u8 TreeParser::calculate_default_intra_mode_probability(u8 node)
{
u32 above_mode, left_mode;
if (m_decoder.m_mi_size >= Block_8x8) {
- above_mode = false // FIXME: AVAIL_U
- ? m_decoder.m_sub_modes[m_decoder.m_mi_row - 1][m_decoder.m_mi_col][2]
+ above_mode = AVAIL_U
+ ? m_decoder.m_sub_modes[(m_decoder.m_mi_row - 1) * m_decoder.m_mi_cols * 4 + m_decoder.m_mi_col * 4 + 2]
: DcPred;
- left_mode = false // FIXME: AVAIL_L
- ? m_decoder.m_sub_modes[m_decoder.m_mi_row][m_decoder.m_mi_col - 1][1]
+ left_mode = AVAIL_L
+ ? m_decoder.m_sub_modes[m_decoder.m_mi_row * m_decoder.m_mi_cols * 4 + (m_decoder.m_mi_col - 1) * 4 + 1]
: DcPred;
} else {
if (m_idy) {
above_mode = m_decoder.m_block_sub_modes[m_idx];
} else {
- above_mode = false // FIXME: AVAIL_U
- ? m_decoder.m_sub_modes[m_decoder.m_mi_row - 1][m_decoder.m_mi_col][2 + m_idx]
+ above_mode = AVAIL_U
+ ? m_decoder.m_sub_modes[(m_decoder.m_mi_row - 1) * m_decoder.m_mi_cols * 4 + m_decoder.m_mi_col * 4 + 2 + m_idx]
: DcPred;
}
if (m_idx) {
left_mode = m_decoder.m_block_sub_modes[m_idy * 2];
} else {
- left_mode = false // FIXME: AVAIL_L
- ? m_decoder.m_sub_modes[m_decoder.m_mi_row][m_decoder.m_mi_col - 1][1 + m_idy * 2]
+ left_mode = AVAIL_L
+ ? m_decoder.m_sub_modes[m_decoder.m_mi_row * m_decoder.m_mi_cols * 4 + (m_decoder.m_mi_col - 1) * 4 + 1 + m_idy * 2]
: DcPred;
}
}
@@ -265,12 +265,10 @@ u8 TreeParser::calculate_segment_id_probability(u8 node)
u8 TreeParser::calculate_skip_probability()
{
m_ctx = 0;
- if (AVAIL_U) {
- // FIXME: m_ctx += m_skips[m_mi_row - 1][m_mi_col];
- }
- if (AVAIL_L) {
- // FIXME: m_ctx += m_skips[m_mi_row][m_mi_col - 1];
- }
+ if (AVAIL_U)
+ m_ctx += m_decoder.m_skips[(m_decoder.m_mi_row - 1) * m_decoder.m_mi_cols + m_decoder.m_mi_col];
+ if (AVAIL_L)
+ m_ctx += m_decoder.m_skips[m_decoder.m_mi_row * m_decoder.m_mi_cols + m_decoder.m_mi_col - 1];
return m_decoder.m_probability_tables->skip_prob()[m_ctx];
}
@@ -543,7 +541,16 @@ u8 TreeParser::calculate_tx_size_probability(u8 node)
{
auto above = m_decoder.m_max_tx_size;
auto left = m_decoder.m_max_tx_size;
- // FIXME: Fix varying above/left when Skips is implemented
+ auto u_pos = (m_decoder.m_mi_row - 1) * m_decoder.m_mi_cols + m_decoder.m_mi_col;
+ if (AVAIL_U && !m_decoder.m_skips[u_pos])
+ above = m_decoder.m_tx_sizes[u_pos];
+ auto l_pos = m_decoder.m_mi_row * m_decoder.m_mi_cols + m_decoder.m_mi_col - 1;
+ if (AVAIL_L && !m_decoder.m_skips[l_pos])
+ left = m_decoder.m_tx_sizes[l_pos];
+ if (!AVAIL_L)
+ left = above;
+ if (!AVAIL_U)
+ above = left;
m_ctx = (above + left) > m_decoder.m_max_tx_size;
return m_decoder.m_probability_tables->tx_probs()[m_decoder.m_max_tx_size][m_ctx][node];
}
@@ -557,7 +564,18 @@ u8 TreeParser::calculate_inter_mode_probability(u8 node)
u8 TreeParser::calculate_interp_filter_probability(u8 node)
{
- // FIXME: Implement ctx calculation when InterpFilters is implemented
+ auto left_interp = (AVAIL_L && m_decoder.m_left_ref_frame[0] > IntraFrame)
+ ? m_decoder.m_interp_filters[m_decoder.m_mi_row * m_decoder.m_mi_cols + m_decoder.m_mi_col - 1]
+ : 3;
+ auto above_interp = (AVAIL_U && m_decoder.m_above_ref_frame[0] > IntraFrame)
+ ? m_decoder.m_interp_filters[m_decoder.m_mi_row * m_decoder.m_mi_cols + m_decoder.m_mi_col - 1]
+ : 3;
+ if (left_interp == above_interp || (left_interp != 3 && above_interp == 3))
+ m_ctx = left_interp;
+ else if (left_interp == 3 && above_interp != 3)
+ m_ctx = above_interp;
+ else
+ m_ctx = 3;
return m_decoder.m_probability_tables->interp_filter_probs()[m_ctx][node];
}