/* * Copyright (c) 2019 The WebM project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include <memory>#include <vector>#include "./ivfenc.h"#include "vp9/common/vp9_entropymode.h"#include "vp9/common/vp9_enums.h"#include "vp9/common/vp9_onyxc_int.h"#include "vp9/vp9_iface_common.h"#include "vp9/encoder/vp9_encoder.h"#include "vp9/encoder/vp9_firstpass.h"#include "vp9/simple_encode.h"#include "vp9/vp9_cx_iface.h" namespace vp9 { static int get_plane_height(vpx_img_fmt_t img_fmt, int frame_height, int plane) { assert(plane < 3); if (plane == 0) { return frame_height; } switch (img_fmt) { case VPX_IMG_FMT_I420: case VPX_IMG_FMT_I440: case VPX_IMG_FMT_YV12: case VPX_IMG_FMT_I42016: case VPX_IMG_FMT_I44016: return (frame_height + 1) >> 1; default: return frame_height; }} static int get_plane_width(vpx_img_fmt_t img_fmt, int frame_width, int plane) { assert(plane < 3); if (plane == 0) { return frame_width; } switch (img_fmt) { case VPX_IMG_FMT_I420: case VPX_IMG_FMT_YV12: case VPX_IMG_FMT_I422: case VPX_IMG_FMT_I42016: case VPX_IMG_FMT_I42216: return (frame_width + 1) >> 1; default: return frame_width; }} // TODO(angiebird): Merge this function with vpx_img_plane_width()static int img_plane_width(const vpx_image_t *img, int plane) { if (plane > 0 && img->x_chroma_shift > 0) return (img->d_w + 1) >> img->x_chroma_shift; else return img->d_w;} // TODO(angiebird): Merge this function with vpx_img_plane_height()static int img_plane_height(const vpx_image_t *img, int plane) { if (plane > 0 && img->y_chroma_shift > 0) return (img->d_h + 1) >> img->y_chroma_shift; else return img->d_h;} // TODO(angiebird): Merge this function with vpx_img_read()static int img_read(vpx_image_t *img, FILE *file) { int plane; for (plane = 0; plane < 3; ++plane) { unsigned char *buf = img->planes[plane]; const int stride = img->stride[plane]; const int w = img_plane_width(img, plane) * ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1); const int h = img_plane_height(img, plane); int y; for (y = 0; y < h; ++y) { if (fread(buf, 1, w, file) != (size_t)w) return 0; buf += stride; } } return 1;} class SimpleEncode::EncodeImpl { public: VP9_COMP *cpi; vpx_img_fmt_t img_fmt; vpx_image_t tmp_img; std::vector<FIRSTPASS_STATS> first_pass_stats;}; static VP9_COMP *init_encoder(const VP9EncoderConfig *oxcf, vpx_img_fmt_t img_fmt) { VP9_COMP *cpi; BufferPool *buffer_pool = (BufferPool *)vpx_calloc(1, sizeof(*buffer_pool)); vp9_initialize_enc(); cpi = vp9_create_compressor(oxcf, buffer_pool); vp9_update_compressor_with_img_fmt(cpi, img_fmt); return cpi;} static void free_encoder(VP9_COMP *cpi) { BufferPool *buffer_pool = cpi->common.buffer_pool; vp9_remove_compressor(cpi); // buffer_pool needs to be free after cpi because buffer_pool contains // allocated buffers that will be free in vp9_remove_compressor() vpx_free(buffer_pool);} static INLINE vpx_rational_t make_vpx_rational(int num, int den) { vpx_rational_t v; v.num = num; v.den = den; return v;} static INLINE FrameTypeget_frame_type_from_update_type(FRAME_UPDATE_TYPE update_type) { switch (update_type) { case KF_UPDATE: return kFrameTypeKey; case ARF_UPDATE: return kFrameTypeAltRef; case GF_UPDATE: return kFrameTypeGolden; case OVERLAY_UPDATE: return kFrameTypeOverlay; case LF_UPDATE: return kFrameTypeInter; default: fprintf(stderr, "Unsupported update_type %d\n", update_type); abort(); return kFrameTypeInter; }} static void update_partition_info(const PARTITION_INFO *input_partition_info, const int num_rows_4x4, const int num_cols_4x4, PartitionInfo *output_partition_info) { const int num_units_4x4 = num_rows_4x4 * num_cols_4x4; for (int i = 0; i < num_units_4x4; ++i) { output_partition_info[i].row = input_partition_info[i].row; output_partition_info[i].column = input_partition_info[i].column; output_partition_info[i].row_start = input_partition_info[i].row_start; output_partition_info[i].column_start = input_partition_info[i].column_start; output_partition_info[i].width = input_partition_info[i].width; output_partition_info[i].height = input_partition_info[i].height; }} // translate MV_REFERENCE_FRAME to RefFrameTypestatic RefFrameType mv_ref_frame_to_ref_frame_type( MV_REFERENCE_FRAME mv_ref_frame) { switch (mv_ref_frame) { case LAST_FRAME: return kRefFrameTypeLast; case GOLDEN_FRAME: return kRefFrameTypePast; case ALTREF_FRAME: return kRefFrameTypeFuture; default: return kRefFrameTypeNone; }} static void update_motion_vector_info( const MOTION_VECTOR_INFO *input_motion_vector_info, const int num_rows_4x4, const int num_cols_4x4, MotionVectorInfo *output_motion_vector_info) { const int num_units_4x4 = num_rows_4x4 * num_cols_4x4; for (int i = 0; i < num_units_4x4; ++i) { const MV_REFERENCE_FRAME *in_ref_frame = input_motion_vector_info[i].ref_frame; output_motion_vector_info[i].mv_count = (in_ref_frame[0] == INTRA_FRAME) ? 0 : ((in_ref_frame[1] == NONE) ? 1 : 2); if (in_ref_frame[0] == NONE) { fprintf(stderr, "in_ref_frame[0] shouldn't be NONE\n"); abort(); } output_motion_vector_info[i].ref_frame[0] = mv_ref_frame_to_ref_frame_type(in_ref_frame[0]); output_motion_vector_info[i].ref_frame[1] = mv_ref_frame_to_ref_frame_type(in_ref_frame[1]); output_motion_vector_info[i].mv_row[0] = (double)input_motion_vector_info[i].mv[0].as_mv.row / kMotionVectorPrecision; output_motion_vector_info[i].mv_column[0] = (double)input_motion_vector_info[i].mv[0].as_mv.col / kMotionVectorPrecision; output_motion_vector_info[i].mv_row[1] = (double)input_motion_vector_info[i].mv[1].as_mv.row / kMotionVectorPrecision; output_motion_vector_info[i].mv_column[1] = (double)input_motion_vector_info[i].mv[1].as_mv.col / kMotionVectorPrecision; }} static void update_frame_counts(const FRAME_COUNTS *input_counts, FrameCounts *output_counts) { // Init array sizes. output_counts->y_mode.resize(BLOCK_SIZE_GROUPS); for (int i = 0; i < BLOCK_SIZE_GROUPS; ++i) { output_counts->y_mode[i].resize(INTRA_MODES); } output_counts->uv_mode.resize(INTRA_MODES); for (int i = 0; i < INTRA_MODES; ++i) { output_counts->uv_mode[i].resize(INTRA_MODES); } output_counts->partition.resize(PARTITION_CONTEXTS); for (int i = 0; i < PARTITION_CONTEXTS; ++i) { output_counts->partition[i].resize(PARTITION_TYPES); } output_counts->coef.resize(TX_SIZES); output_counts->eob_branch.resize(TX_SIZES); for (int i = 0; i < TX_SIZES; ++i) { output_counts->coef[i].resize(PLANE_TYPES); output_counts->eob_branch[i].resize(PLANE_TYPES); for (int j = 0; j < PLANE_TYPES; ++j) { output_counts->coef[i][j].resize(REF_TYPES); output_counts->eob_branch[i][j].resize(REF_TYPES); for (int k = 0; k < REF_TYPES; ++k) { output_counts->coef[i][j][k].resize(COEF_BANDS); output_counts->eob_branch[i][j][k].resize(COEF_BANDS); for (int l = 0; l < COEF_BANDS; ++l) { output_counts->coef[i][j][k][l].resize(COEFF_CONTEXTS); output_counts->eob_branch[i][j][k][l].resize(COEFF_CONTEXTS); for (int m = 0; m < COEFF_CONTEXTS; ++m) { output_counts->coef[i][j][k][l][m].resize(UNCONSTRAINED_NODES + 1); } } } } } output_counts->switchable_interp.resize(SWITCHABLE_FILTER_CONTEXTS); for (int i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i) { output_counts->switchable_interp[i].resize(SWITCHABLE_FILTERS); } output_counts->inter_mode.resize(INTER_MODE_CONTEXTS); for (int i = 0; i < INTER_MODE_CONTEXTS; ++i) { output_counts->inter_mode[i].resize(INTER_MODES); } output_counts->intra_inter.resize(INTRA_INTER_CONTEXTS); for (int i = 0; i < INTRA_INTER_CONTEXTS; ++i) { output_counts->intra_inter[i].resize(2); } output_counts->comp_inter.resize(COMP_INTER_CONTEXTS); for (int i = 0; i < COMP_INTER_CONTEXTS; ++i) { output_counts->comp_inter[i].resize(2); } output_counts->single_ref.resize(REF_CONTEXTS); for (int i = 0; i < REF_CONTEXTS; ++i) { output_counts->single_ref[i].resize(2); for (int j = 0; j < 2; ++j) { output_counts->single_ref[i][j].resize(2); } } output_counts->comp_ref.resize(REF_CONTEXTS); for (int i = 0; i < REF_CONTEXTS; ++i) { output_counts->comp_ref[i].resize(2); } output_counts->skip.resize(SKIP_CONTEXTS); for (int i = 0; i < SKIP_CONTEXTS; ++i) { output_counts->skip[i].resize(2); } output_counts->tx.p32x32.resize(TX_SIZE_CONTEXTS); output_counts->tx.p16x16.resize(TX_SIZE_CONTEXTS); output_counts->tx.p8x8.resize(TX_SIZE_CONTEXTS); for (int i = 0; i < TX_SIZE_CONTEXTS; i++) { output_counts->tx.p32x32[i].resize(TX_SIZES); output_counts->tx.p16x16[i].resize(TX_SIZES - 1); output_counts->tx.p8x8[i].resize(TX_SIZES - 2); } output_counts->tx.tx_totals.resize(TX_SIZES); output_counts->mv.joints.resize(MV_JOINTS); output_counts->mv.comps.resize(2); for (int i = 0; i < 2; ++i) { output_counts->mv.comps[i].sign.resize(2); output_counts->mv.comps[i].classes.resize(MV_CLASSES); output_counts->mv.comps[i].class0.resize(CLASS0_SIZE); output_counts->mv.comps[i].bits.resize(MV_OFFSET_BITS); for (int j = 0; j < MV_OFFSET_BITS; ++j) { output_counts->mv.comps[i].bits[j].resize(2); } output_counts->mv.comps[i].class0_fp.resize(CLASS0_SIZE); for (int j = 0; j < CLASS0_SIZE; ++j) { output_counts->mv.comps[i].class0_fp[j].resize(MV_FP_SIZE); } output_counts->mv.comps[i].fp.resize(MV_FP_SIZE); output_counts->mv.comps[i].class0_hp.resize(2); output_counts->mv.comps[i].hp.resize(2); } // Populate counts. for (int i = 0; i < BLOCK_SIZE_GROUPS; ++i) { for (int j = 0; j < INTRA_MODES; ++j) { output_counts->y_mode[i][j] = input_counts->y_mode[i][j]; } } for (int i = 0; i < INTRA_MODES; ++i) { for (int j = 0; j < INTRA_MODES; ++j) { output_counts->uv_mode[i][j] = input_counts->uv_mode[i][j]; } } for (int i = 0; i < PARTITION_CONTEXTS; ++i) { for (int j = 0; j < PARTITION_TYPES; ++j) { output_counts->partition[i][j] = input_counts->partition[i][j]; } } for (int i = 0; i < TX_SIZES; ++i) { for (int j = 0; j < PLANE_TYPES; ++j) { for (int k = 0; k < REF_TYPES; ++k) { for (int l = 0; l < COEF_BANDS; ++l) { for (int m = 0; m < COEFF_CONTEXTS; ++m) { output_counts->eob_branch[i][j][k][l][m] = input_counts->eob_branch[i][j][k][l][m]; for (int n = 0; n < UNCONSTRAINED_NODES + 1; n++) { output_counts->coef[i][j][k][l][m][n] = input_counts->coef[i][j][k][l][m][n]; } } } } } } for (int i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i) { for (int j = 0; j < SWITCHABLE_FILTERS; ++j) { output_counts->switchable_interp[i][j] = input_counts->switchable_interp[i][j]; } } for (int i = 0; i < INTER_MODE_CONTEXTS; ++i) { for (int j = 0; j < INTER_MODES; ++j) { output_counts->inter_mode[i][j] = input_counts->inter_mode[i][j]; } } for (int i = 0; i < INTRA_INTER_CONTEXTS; ++i) { for (int j = 0; j < 2; ++j) { output_counts->intra_inter[i][j] = input_counts->intra_inter[i][j]; } } for (int i = 0; i < COMP_INTER_CONTEXTS; ++i) { for (int j = 0; j < 2; ++j) { output_counts->comp_inter[i][j] = input_counts->comp_inter[i][j]; } } for (int i = 0; i < REF_CONTEXTS; ++i) { for (int j = 0; j < 2; ++j) { for (int k = 0; k < 2; ++k) { output_counts->single_ref[i][j][k] = input_counts->single_ref[i][j][k]; } } } for (int i = 0; i < REF_CONTEXTS; ++i) { for (int j = 0; j < 2; ++j) { output_counts->comp_ref[i][j] = input_counts->comp_ref[i][j]; } } for (int i = 0; i < SKIP_CONTEXTS; ++i) { for (int j = 0; j < 2; ++j) { output_counts->skip[i][j] = input_counts->skip[i][j]; } } for (int i = 0; i < TX_SIZE_CONTEXTS; i++) { for (int j = 0; j < TX_SIZES; j++) { output_counts->tx.p32x32[i][j] = input_counts->tx.p32x32[i][j]; } for (int j = 0; j < TX_SIZES - 1; j++) { output_counts->tx.p16x16[i][j] = input_counts->tx.p16x16[i][j]; } for (int j = 0; j < TX_SIZES - 2; j++) { output_counts->tx.p8x8[i][j] = input_counts->tx.p8x8[i][j]; } } for (int i = 0; i < TX_SIZES; i++) { output_counts->tx.tx_totals[i] = input_counts->tx.tx_totals[i]; } for (int i = 0; i < MV_JOINTS; i++) { output_counts->mv.joints[i] = input_counts->mv.joints[i]; } for (int k = 0; k < 2; k++) { const nmv_component_counts *const comps_t = &input_counts->mv.comps[k]; for (int i = 0; i < 2; i++) { output_counts->mv.comps[k].sign[i] = comps_t->sign[i]; output_counts->mv.comps[k].class0_hp[i] = comps_t->class0_hp[i]; output_counts->mv.comps[k].hp[i] = comps_t->hp[i]; } for (int i = 0; i < MV_CLASSES; i++) { output_counts->mv.comps[k].classes[i] = comps_t->classes[i]; } for (int i = 0; i < CLASS0_SIZE; i++) { output_counts->mv.comps[k].class0[i] = comps_t->class0[i]; for (int j = 0; j < MV_FP_SIZE; j++) { output_counts->mv.comps[k].class0_fp[i][j] = comps_t->class0_fp[i][j]; } } for (int i = 0; i < MV_OFFSET_BITS; i++) { for (int j = 0; j < 2; j++) { output_counts->mv.comps[k].bits[i][j] = comps_t->bits[i][j]; } } for (int i = 0; i < MV_FP_SIZE; i++) { output_counts->mv.comps[k].fp[i] = comps_t->fp[i]; } }} void output_image_buffer(const ImageBuffer &image_buffer, std::FILE *out_file) { for (int plane = 0; plane < 3; ++plane) { const int w = image_buffer.plane_width[plane]; const int h = image_buffer.plane_height[plane]; const uint8_t *buf = image_buffer.plane_buffer[plane].get(); fprintf(out_file, "%d %d\n", h, w); for (int i = 0; i < w * h; ++i) { fprintf(out_file, "%d ", (int)buf[i]); } fprintf(out_file, "\n"); }} static bool init_image_buffer(ImageBuffer *image_buffer, int frame_width, int frame_height, vpx_img_fmt_t img_fmt) { for (int plane = 0; plane < 3; ++plane) { const int w = get_plane_width(img_fmt, frame_width, plane); const int h = get_plane_height(img_fmt, frame_height, plane); image_buffer->plane_width[plane] = w; image_buffer->plane_height[plane] = h; image_buffer->plane_buffer[plane].reset(new (std::nothrow) uint8_t[w * h]); if (image_buffer->plane_buffer[plane].get() == nullptr) { return false; } } return true;} static void ImageBuffer_to_IMAGE_BUFFER(const ImageBuffer &image_buffer, IMAGE_BUFFER *image_buffer_c) { image_buffer_c->allocated = 1; for (int plane = 0; plane < 3; ++plane) { image_buffer_c->plane_width[plane] = image_buffer.plane_width[plane]; image_buffer_c->plane_height[plane] = image_buffer.plane_height[plane]; image_buffer_c->plane_buffer[plane] = image_buffer.plane_buffer[plane].get(); }} static size_t get_max_coding_data_byte_size(int frame_width, int frame_height) { return frame_width * frame_height * 3;} static bool init_encode_frame_result(EncodeFrameResult *encode_frame_result, int frame_width, int frame_height, vpx_img_fmt_t img_fmt) { const size_t max_coding_data_byte_size = get_max_coding_data_byte_size(frame_width, frame_height); encode_frame_result->coding_data.reset( new (std::nothrow) uint8_t[max_coding_data_byte_size]); encode_frame_result->num_rows_4x4 = get_num_unit_4x4(frame_width); encode_frame_result->num_cols_4x4 = get_num_unit_4x4(frame_height); encode_frame_result->partition_info.resize(encode_frame_result->num_rows_4x4 * encode_frame_result->num_cols_4x4); encode_frame_result->motion_vector_info.resize( encode_frame_result->num_rows_4x4 * encode_frame_result->num_cols_4x4); if (encode_frame_result->coding_data.get() == nullptr) { return false; } return init_image_buffer(&encode_frame_result->coded_frame, frame_width, frame_height, img_fmt);} static void update_encode_frame_result( EncodeFrameResult *encode_frame_result, const ENCODE_FRAME_RESULT *encode_frame_info) { encode_frame_result->coding_data_bit_size = encode_frame_result->coding_data_byte_size * 8; encode_frame_result->show_idx = encode_frame_info->show_idx; encode_frame_result->coding_idx = encode_frame_info->frame_coding_index; assert(kRefFrameTypeMax == MAX_INTER_REF_FRAMES); for (int i = 0; i < kRefFrameTypeMax; ++i) { encode_frame_result->ref_frame_info.coding_indexes[i] = encode_frame_info->ref_frame_coding_indexes[i]; encode_frame_result->ref_frame_info.valid_list[i] = encode_frame_info->ref_frame_valid_list[i];Lines 1–500 of 1148. Load more
/* * Copyright (c) 2019 The WebM project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include <memory> #include <vector> #include "./ivfenc.h" #include "vp9/common/vp9_entropymode.h" #include "vp9/common/vp9_enums.h" #include "vp9/common/vp9_onyxc_int.h" #include "vp9/vp9_iface_common.h" #include "vp9/encoder/vp9_encoder.h" #include "vp9/encoder/vp9_firstpass.h" #include "vp9/simple_encode.h" #include "vp9/vp9_cx_iface.h" namespace vp9 { static int get_plane_height(vpx_img_fmt_t img_fmt, int frame_height, int plane) { assert(plane < 3); if (plane == 0) { return frame_height; } switch (img_fmt) { case VPX_IMG_FMT_I420: case VPX_IMG_FMT_I440: case VPX_IMG_FMT_YV12: case VPX_IMG_FMT_I42016: case VPX_IMG_FMT_I44016: return (frame_height + 1) >> 1; default: return frame_height; } } static int get_plane_width(vpx_img_fmt_t img_fmt, int frame_width, int plane) { assert(plane < 3); if (plane == 0) { return frame_width; } switch (img_fmt) { case VPX_IMG_FMT_I420: case VPX_IMG_FMT_YV12: case VPX_IMG_FMT_I422: case VPX_IMG_FMT_I42016: case VPX_IMG_FMT_I42216: return (frame_width + 1) >> 1; default: return frame_width; } } // TODO(angiebird): Merge this function with vpx_img_plane_width() static int img_plane_width(const vpx_image_t *img, int plane) { if (plane > 0 && img->x_chroma_shift > 0) return (img->d_w + 1) >> img->x_chroma_shift; else return img->d_w; } // TODO(angiebird): Merge this function with vpx_img_plane_height() static int img_plane_height(const vpx_image_t *img, int plane) { if (plane > 0 && img->y_chroma_shift > 0) return (img->d_h + 1) >> img->y_chroma_shift; else return img->d_h; } // TODO(angiebird): Merge this function with vpx_img_read() static int img_read(vpx_image_t *img, FILE *file) { int plane; for (plane = 0; plane < 3; ++plane) { unsigned char *buf = img->planes[plane]; const int stride = img->stride[plane]; const int w = img_plane_width(img, plane) * ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1); const int h = img_plane_height(img, plane); int y; for (y = 0; y < h; ++y) { if (fread(buf, 1, w, file) != (size_t)w) return 0; buf += stride; } } return 1; } class SimpleEncode::EncodeImpl { public: VP9_COMP *cpi; vpx_img_fmt_t img_fmt; vpx_image_t tmp_img; std::vector<FIRSTPASS_STATS> first_pass_stats; }; static VP9_COMP *init_encoder(const VP9EncoderConfig *oxcf, vpx_img_fmt_t img_fmt) { VP9_COMP *cpi; BufferPool *buffer_pool = (BufferPool *)vpx_calloc(1, sizeof(*buffer_pool)); vp9_initialize_enc(); cpi = vp9_create_compressor(oxcf, buffer_pool); vp9_update_compressor_with_img_fmt(cpi, img_fmt); return cpi; } static void free_encoder(VP9_COMP *cpi) { BufferPool *buffer_pool = cpi->common.buffer_pool; vp9_remove_compressor(cpi); // buffer_pool needs to be free after cpi because buffer_pool contains // allocated buffers that will be free in vp9_remove_compressor() vpx_free(buffer_pool); } static INLINE vpx_rational_t make_vpx_rational(int num, int den) { vpx_rational_t v; v.num = num; v.den = den; return v; } static INLINE FrameType get_frame_type_from_update_type(FRAME_UPDATE_TYPE update_type) { switch (update_type) { case KF_UPDATE: return kFrameTypeKey; case ARF_UPDATE: return kFrameTypeAltRef; case GF_UPDATE: return kFrameTypeGolden; case OVERLAY_UPDATE: return kFrameTypeOverlay; case LF_UPDATE: return kFrameTypeInter; default: fprintf(stderr, "Unsupported update_type %d\n", update_type); abort(); return kFrameTypeInter; } } static void update_partition_info(const PARTITION_INFO *input_partition_info, const int num_rows_4x4, const int num_cols_4x4, PartitionInfo *output_partition_info) { const int num_units_4x4 = num_rows_4x4 * num_cols_4x4; for (int i = 0; i < num_units_4x4; ++i) { output_partition_info[i].row = input_partition_info[i].row; output_partition_info[i].column = input_partition_info[i].column; output_partition_info[i].row_start = input_partition_info[i].row_start; output_partition_info[i].column_start = input_partition_info[i].column_start; output_partition_info[i].width = input_partition_info[i].width; output_partition_info[i].height = input_partition_info[i].height; } } // translate MV_REFERENCE_FRAME to RefFrameType static RefFrameType mv_ref_frame_to_ref_frame_type( MV_REFERENCE_FRAME mv_ref_frame) { switch (mv_ref_frame) { case LAST_FRAME: return kRefFrameTypeLast; case GOLDEN_FRAME: return kRefFrameTypePast; case ALTREF_FRAME: return kRefFrameTypeFuture; default: return kRefFrameTypeNone; } } static void update_motion_vector_info( const MOTION_VECTOR_INFO *input_motion_vector_info, const int num_rows_4x4, const int num_cols_4x4, MotionVectorInfo *output_motion_vector_info) { const int num_units_4x4 = num_rows_4x4 * num_cols_4x4; for (int i = 0; i < num_units_4x4; ++i) { const MV_REFERENCE_FRAME *in_ref_frame = input_motion_vector_info[i].ref_frame; output_motion_vector_info[i].mv_count = (in_ref_frame[0] == INTRA_FRAME) ? 0 : ((in_ref_frame[1] == NONE) ? 1 : 2); if (in_ref_frame[0] == NONE) { fprintf(stderr, "in_ref_frame[0] shouldn't be NONE\n"); abort(); } output_motion_vector_info[i].ref_frame[0] = mv_ref_frame_to_ref_frame_type(in_ref_frame[0]); output_motion_vector_info[i].ref_frame[1] = mv_ref_frame_to_ref_frame_type(in_ref_frame[1]); output_motion_vector_info[i].mv_row[0] = (double)input_motion_vector_info[i].mv[0].as_mv.row / kMotionVectorPrecision; output_motion_vector_info[i].mv_column[0] = (double)input_motion_vector_info[i].mv[0].as_mv.col / kMotionVectorPrecision; output_motion_vector_info[i].mv_row[1] = (double)input_motion_vector_info[i].mv[1].as_mv.row / kMotionVectorPrecision; output_motion_vector_info[i].mv_column[1] = (double)input_motion_vector_info[i].mv[1].as_mv.col / kMotionVectorPrecision; } } static void update_frame_counts(const FRAME_COUNTS *input_counts, FrameCounts *output_counts) { // Init array sizes. output_counts->y_mode.resize(BLOCK_SIZE_GROUPS); for (int i = 0; i < BLOCK_SIZE_GROUPS; ++i) { output_counts->y_mode[i].resize(INTRA_MODES); } output_counts->uv_mode.resize(INTRA_MODES); for (int i = 0; i < INTRA_MODES; ++i) { output_counts->uv_mode[i].resize(INTRA_MODES); } output_counts->partition.resize(PARTITION_CONTEXTS); for (int i = 0; i < PARTITION_CONTEXTS; ++i) { output_counts->partition[i].resize(PARTITION_TYPES); } output_counts->coef.resize(TX_SIZES); output_counts->eob_branch.resize(TX_SIZES); for (int i = 0; i < TX_SIZES; ++i) { output_counts->coef[i].resize(PLANE_TYPES); output_counts->eob_branch[i].resize(PLANE_TYPES); for (int j = 0; j < PLANE_TYPES; ++j) { output_counts->coef[i][j].resize(REF_TYPES); output_counts->eob_branch[i][j].resize(REF_TYPES); for (int k = 0; k < REF_TYPES; ++k) { output_counts->coef[i][j][k].resize(COEF_BANDS); output_counts->eob_branch[i][j][k].resize(COEF_BANDS); for (int l = 0; l < COEF_BANDS; ++l) { output_counts->coef[i][j][k][l].resize(COEFF_CONTEXTS); output_counts->eob_branch[i][j][k][l].resize(COEFF_CONTEXTS); for (int m = 0; m < COEFF_CONTEXTS; ++m) { output_counts->coef[i][j][k][l][m].resize(UNCONSTRAINED_NODES + 1); } } } } } output_counts->switchable_interp.resize(SWITCHABLE_FILTER_CONTEXTS); for (int i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i) { output_counts->switchable_interp[i].resize(SWITCHABLE_FILTERS); } output_counts->inter_mode.resize(INTER_MODE_CONTEXTS); for (int i = 0; i < INTER_MODE_CONTEXTS; ++i) { output_counts->inter_mode[i].resize(INTER_MODES); } output_counts->intra_inter.resize(INTRA_INTER_CONTEXTS); for (int i = 0; i < INTRA_INTER_CONTEXTS; ++i) { output_counts->intra_inter[i].resize(2); } output_counts->comp_inter.resize(COMP_INTER_CONTEXTS); for (int i = 0; i < COMP_INTER_CONTEXTS; ++i) { output_counts->comp_inter[i].resize(2); } output_counts->single_ref.resize(REF_CONTEXTS); for (int i = 0; i < REF_CONTEXTS; ++i) { output_counts->single_ref[i].resize(2); for (int j = 0; j < 2; ++j) { output_counts->single_ref[i][j].resize(2); } } output_counts->comp_ref.resize(REF_CONTEXTS); for (int i = 0; i < REF_CONTEXTS; ++i) { output_counts->comp_ref[i].resize(2); } output_counts->skip.resize(SKIP_CONTEXTS); for (int i = 0; i < SKIP_CONTEXTS; ++i) { output_counts->skip[i].resize(2); } output_counts->tx.p32x32.resize(TX_SIZE_CONTEXTS); output_counts->tx.p16x16.resize(TX_SIZE_CONTEXTS); output_counts->tx.p8x8.resize(TX_SIZE_CONTEXTS); for (int i = 0; i < TX_SIZE_CONTEXTS; i++) { output_counts->tx.p32x32[i].resize(TX_SIZES); output_counts->tx.p16x16[i].resize(TX_SIZES - 1); output_counts->tx.p8x8[i].resize(TX_SIZES - 2); } output_counts->tx.tx_totals.resize(TX_SIZES); output_counts->mv.joints.resize(MV_JOINTS); output_counts->mv.comps.resize(2); for (int i = 0; i < 2; ++i) { output_counts->mv.comps[i].sign.resize(2); output_counts->mv.comps[i].classes.resize(MV_CLASSES); output_counts->mv.comps[i].class0.resize(CLASS0_SIZE); output_counts->mv.comps[i].bits.resize(MV_OFFSET_BITS); for (int j = 0; j < MV_OFFSET_BITS; ++j) { output_counts->mv.comps[i].bits[j].resize(2); } output_counts->mv.comps[i].class0_fp.resize(CLASS0_SIZE); for (int j = 0; j < CLASS0_SIZE; ++j) { output_counts->mv.comps[i].class0_fp[j].resize(MV_FP_SIZE); } output_counts->mv.comps[i].fp.resize(MV_FP_SIZE); output_counts->mv.comps[i].class0_hp.resize(2); output_counts->mv.comps[i].hp.resize(2); } // Populate counts. for (int i = 0; i < BLOCK_SIZE_GROUPS; ++i) { for (int j = 0; j < INTRA_MODES; ++j) { output_counts->y_mode[i][j] = input_counts->y_mode[i][j]; } } for (int i = 0; i < INTRA_MODES; ++i) { for (int j = 0; j < INTRA_MODES; ++j) { output_counts->uv_mode[i][j] = input_counts->uv_mode[i][j]; } } for (int i = 0; i < PARTITION_CONTEXTS; ++i) { for (int j = 0; j < PARTITION_TYPES; ++j) { output_counts->partition[i][j] = input_counts->partition[i][j]; } } for (int i = 0; i < TX_SIZES; ++i) { for (int j = 0; j < PLANE_TYPES; ++j) { for (int k = 0; k < REF_TYPES; ++k) { for (int l = 0; l < COEF_BANDS; ++l) { for (int m = 0; m < COEFF_CONTEXTS; ++m) { output_counts->eob_branch[i][j][k][l][m] = input_counts->eob_branch[i][j][k][l][m]; for (int n = 0; n < UNCONSTRAINED_NODES + 1; n++) { output_counts->coef[i][j][k][l][m][n] = input_counts->coef[i][j][k][l][m][n]; } } } } } } for (int i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i) { for (int j = 0; j < SWITCHABLE_FILTERS; ++j) { output_counts->switchable_interp[i][j] = input_counts->switchable_interp[i][j]; } } for (int i = 0; i < INTER_MODE_CONTEXTS; ++i) { for (int j = 0; j < INTER_MODES; ++j) { output_counts->inter_mode[i][j] = input_counts->inter_mode[i][j]; } } for (int i = 0; i < INTRA_INTER_CONTEXTS; ++i) { for (int j = 0; j < 2; ++j) { output_counts->intra_inter[i][j] = input_counts->intra_inter[i][j]; } } for (int i = 0; i < COMP_INTER_CONTEXTS; ++i) { for (int j = 0; j < 2; ++j) { output_counts->comp_inter[i][j] = input_counts->comp_inter[i][j]; } } for (int i = 0; i < REF_CONTEXTS; ++i) { for (int j = 0; j < 2; ++j) { for (int k = 0; k < 2; ++k) { output_counts->single_ref[i][j][k] = input_counts->single_ref[i][j][k]; } } } for (int i = 0; i < REF_CONTEXTS; ++i) { for (int j = 0; j < 2; ++j) { output_counts->comp_ref[i][j] = input_counts->comp_ref[i][j]; } } for (int i = 0; i < SKIP_CONTEXTS; ++i) { for (int j = 0; j < 2; ++j) { output_counts->skip[i][j] = input_counts->skip[i][j]; } } for (int i = 0; i < TX_SIZE_CONTEXTS; i++) { for (int j = 0; j < TX_SIZES; j++) { output_counts->tx.p32x32[i][j] = input_counts->tx.p32x32[i][j]; } for (int j = 0; j < TX_SIZES - 1; j++) { output_counts->tx.p16x16[i][j] = input_counts->tx.p16x16[i][j]; } for (int j = 0; j < TX_SIZES - 2; j++) { output_counts->tx.p8x8[i][j] = input_counts->tx.p8x8[i][j]; } } for (int i = 0; i < TX_SIZES; i++) { output_counts->tx.tx_totals[i] = input_counts->tx.tx_totals[i]; } for (int i = 0; i < MV_JOINTS; i++) { output_counts->mv.joints[i] = input_counts->mv.joints[i]; } for (int k = 0; k < 2; k++) { const nmv_component_counts *const comps_t = &input_counts->mv.comps[k]; for (int i = 0; i < 2; i++) { output_counts->mv.comps[k].sign[i] = comps_t->sign[i]; output_counts->mv.comps[k].class0_hp[i] = comps_t->class0_hp[i]; output_counts->mv.comps[k].hp[i] = comps_t->hp[i]; } for (int i = 0; i < MV_CLASSES; i++) { output_counts->mv.comps[k].classes[i] = comps_t->classes[i]; } for (int i = 0; i < CLASS0_SIZE; i++) { output_counts->mv.comps[k].class0[i] = comps_t->class0[i]; for (int j = 0; j < MV_FP_SIZE; j++) { output_counts->mv.comps[k].class0_fp[i][j] = comps_t->class0_fp[i][j]; } } for (int i = 0; i < MV_OFFSET_BITS; i++) { for (int j = 0; j < 2; j++) { output_counts->mv.comps[k].bits[i][j] = comps_t->bits[i][j]; } } for (int i = 0; i < MV_FP_SIZE; i++) { output_counts->mv.comps[k].fp[i] = comps_t->fp[i]; } } } void output_image_buffer(const ImageBuffer &image_buffer, std::FILE *out_file) { for (int plane = 0; plane < 3; ++plane) { const int w = image_buffer.plane_width[plane]; const int h = image_buffer.plane_height[plane]; const uint8_t *buf = image_buffer.plane_buffer[plane].get(); fprintf(out_file, "%d %d\n", h, w); for (int i = 0; i < w * h; ++i) { fprintf(out_file, "%d ", (int)buf[i]); } fprintf(out_file, "\n"); } } static bool init_image_buffer(ImageBuffer *image_buffer, int frame_width, int frame_height, vpx_img_fmt_t img_fmt) { for (int plane = 0; plane < 3; ++plane) { const int w = get_plane_width(img_fmt, frame_width, plane); const int h = get_plane_height(img_fmt, frame_height, plane); image_buffer->plane_width[plane] = w; image_buffer->plane_height[plane] = h; image_buffer->plane_buffer[plane].reset(new (std::nothrow) uint8_t[w * h]); if (image_buffer->plane_buffer[plane].get() == nullptr) { return false; } } return true; } static void ImageBuffer_to_IMAGE_BUFFER(const ImageBuffer &image_buffer, IMAGE_BUFFER *image_buffer_c) { image_buffer_c->allocated = 1; for (int plane = 0; plane < 3; ++plane) { image_buffer_c->plane_width[plane] = image_buffer.plane_width[plane]; image_buffer_c->plane_height[plane] = image_buffer.plane_height[plane]; image_buffer_c->plane_buffer[plane] = image_buffer.plane_buffer[plane].get(); } } static size_t get_max_coding_data_byte_size(int frame_width, int frame_height) { return frame_width * frame_height * 3; } static bool init_encode_frame_result(EncodeFrameResult *encode_frame_result, int frame_width, int frame_height, vpx_img_fmt_t img_fmt) { const size_t max_coding_data_byte_size = get_max_coding_data_byte_size(frame_width, frame_height); encode_frame_result->coding_data.reset( new (std::nothrow) uint8_t[max_coding_data_byte_size]); encode_frame_result->num_rows_4x4 = get_num_unit_4x4(frame_width); encode_frame_result->num_cols_4x4 = get_num_unit_4x4(frame_height); encode_frame_result->partition_info.resize(encode_frame_result->num_rows_4x4 * encode_frame_result->num_cols_4x4); encode_frame_result->motion_vector_info.resize( encode_frame_result->num_rows_4x4 * encode_frame_result->num_cols_4x4); if (encode_frame_result->coding_data.get() == nullptr) { return false; } return init_image_buffer(&encode_frame_result->coded_frame, frame_width, frame_height, img_fmt); } static void update_encode_frame_result( EncodeFrameResult *encode_frame_result, const ENCODE_FRAME_RESULT *encode_frame_info) { encode_frame_result->coding_data_bit_size = encode_frame_result->coding_data_byte_size * 8; encode_frame_result->show_idx = encode_frame_info->show_idx; encode_frame_result->coding_idx = encode_frame_info->frame_coding_index; assert(kRefFrameTypeMax == MAX_INTER_REF_FRAMES); for (int i = 0; i < kRefFrameTypeMax; ++i) { encode_frame_result->ref_frame_info.coding_indexes[i] = encode_frame_info->ref_frame_coding_indexes[i]; encode_frame_result->ref_frame_info.valid_list[i] = encode_frame_info->ref_frame_valid_list[i];