1195 lines · 45.0 KB · C++
RawDownload
/* *  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,    int motion_vector_scale) {  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 /        motion_vector_scale;    output_motion_vector_info[i].mv_column[0] =        (double)input_motion_vector_info[i].mv[0].as_mv.col /        motion_vector_scale;    output_motion_vector_info[i].mv_row[1] =        (double)input_motion_vector_info[i].mv[1].as_mv.row /        motion_vector_scale;    output_motion_vector_info[i].mv_column[1] =        (double)input_motion_vector_info[i].mv[1].as_mv.col /        motion_vector_scale;  }} 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_height);  encode_frame_result->num_cols_4x4 = get_num_unit_4x4(frame_width);  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 encode_frame_result_update_rq_history(    const RATE_QINDEX_HISTORY *rq_history,    EncodeFrameResult *encode_frame_result) {  encode_frame_result->recode_count = rq_history->recode_count;  for (int i = 0; i < encode_frame_result->recode_count; ++i) {    const int q_index = rq_history->q_index_history[i];    const int rate = rq_history->rate_history[i];    encode_frame_result->q_index_history.push_back(q_index);    encode_frame_result->rate_history.push_back(rate);  }} 

Lines 1–500 of 1195.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t