| OLD | NEW | 
|    1 /* |    1 /* | 
|    2  *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. |    2  *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 
|    3  * |    3  * | 
|    4  *  Use of this source code is governed by a BSD-style license |    4  *  Use of this source code is governed by a BSD-style license | 
|    5  *  that can be found in the LICENSE file in the root of the source |    5  *  that can be found in the LICENSE file in the root of the source | 
|    6  *  tree. An additional intellectual property rights grant can be found |    6  *  tree. An additional intellectual property rights grant can be found | 
|    7  *  in the file PATENTS.  All contributing project authors may |    7  *  in the file PATENTS.  All contributing project authors may | 
|    8  *  be found in the AUTHORS file in the root of the source tree. |    8  *  be found in the AUTHORS file in the root of the source tree. | 
|    9  * |    9  * | 
|   10  */ |   10  */ | 
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   50   if (width * height <= 352 * 288) |   50   if (width * height <= 352 * 288) | 
|   51     return 5; |   51     return 5; | 
|   52   else |   52   else | 
|   53     return 7; |   53     return 7; | 
|   54 } |   54 } | 
|   55  |   55  | 
|   56 VP9Encoder* VP9Encoder::Create() { |   56 VP9Encoder* VP9Encoder::Create() { | 
|   57   return new VP9EncoderImpl(); |   57   return new VP9EncoderImpl(); | 
|   58 } |   58 } | 
|   59  |   59  | 
 |   60 void VP9EncoderImpl::EncoderOutputCodedPacketCallback(vpx_codec_cx_pkt* pkt, | 
 |   61                                                       void* user_data) { | 
 |   62   VP9EncoderImpl* enc = (VP9EncoderImpl*)(user_data); | 
 |   63   enc->GetEncodedLayerFrame(pkt); | 
 |   64 } | 
 |   65  | 
|   60 VP9EncoderImpl::VP9EncoderImpl() |   66 VP9EncoderImpl::VP9EncoderImpl() | 
|   61     : encoded_image_(), |   67     : encoded_image_(), | 
|   62       encoded_complete_callback_(NULL), |   68       encoded_complete_callback_(NULL), | 
|   63       inited_(false), |   69       inited_(false), | 
|   64       timestamp_(0), |   70       timestamp_(0), | 
|   65       picture_id_(0), |   71       picture_id_(0), | 
|   66       cpu_speed_(3), |   72       cpu_speed_(3), | 
|   67       rc_max_intra_target_(0), |   73       rc_max_intra_target_(0), | 
|   68       encoder_(NULL), |   74       encoder_(NULL), | 
|   69       config_(NULL), |   75       config_(NULL), | 
|   70       raw_(NULL) { |   76       raw_(NULL), | 
 |   77       input_image_(NULL), | 
 |   78       tl0_pic_idx_(0), | 
 |   79       gof_idx_(0), | 
 |   80       num_temporal_layers_(0), | 
 |   81       num_spatial_layers_(0) { | 
|   71   memset(&codec_, 0, sizeof(codec_)); |   82   memset(&codec_, 0, sizeof(codec_)); | 
|   72   uint32_t seed = static_cast<uint32_t>(TickTime::MillisecondTimestamp()); |   83   uint32_t seed = static_cast<uint32_t>(TickTime::MillisecondTimestamp()); | 
|   73   srand(seed); |   84   srand(seed); | 
|   74 } |   85 } | 
|   75  |   86  | 
|   76 VP9EncoderImpl::~VP9EncoderImpl() { |   87 VP9EncoderImpl::~VP9EncoderImpl() { | 
|   77   Release(); |   88   Release(); | 
|   78 } |   89 } | 
|   79  |   90  | 
|   80 int VP9EncoderImpl::Release() { |   91 int VP9EncoderImpl::Release() { | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
|   94     config_ = NULL; |  105     config_ = NULL; | 
|   95   } |  106   } | 
|   96   if (raw_ != NULL) { |  107   if (raw_ != NULL) { | 
|   97     vpx_img_free(raw_); |  108     vpx_img_free(raw_); | 
|   98     raw_ = NULL; |  109     raw_ = NULL; | 
|   99   } |  110   } | 
|  100   inited_ = false; |  111   inited_ = false; | 
|  101   return WEBRTC_VIDEO_CODEC_OK; |  112   return WEBRTC_VIDEO_CODEC_OK; | 
|  102 } |  113 } | 
|  103  |  114  | 
 |  115 bool VP9EncoderImpl::SetSvcRates() { | 
 |  116   float rate_ratio[VPX_MAX_LAYERS] = {0}; | 
 |  117   float total = 0; | 
 |  118   uint8_t i = 0; | 
 |  119  | 
 |  120   for (i = 0; i < num_spatial_layers_; ++i) { | 
 |  121     if (svc_internal_.svc_params.scaling_factor_num[i] <= 0 || | 
 |  122         svc_internal_.svc_params.scaling_factor_den[i] <= 0) { | 
 |  123       return false; | 
 |  124     } | 
 |  125     rate_ratio[i] = static_cast<float>( | 
 |  126         svc_internal_.svc_params.scaling_factor_num[i]) / | 
 |  127         svc_internal_.svc_params.scaling_factor_den[i]; | 
 |  128     total += rate_ratio[i]; | 
 |  129   } | 
 |  130  | 
 |  131   for (i = 0; i < num_spatial_layers_; ++i) { | 
 |  132     config_->ss_target_bitrate[i] = static_cast<unsigned int>( | 
 |  133         config_->rc_target_bitrate * rate_ratio[i] / total); | 
 |  134     if (num_temporal_layers_ == 1) { | 
 |  135       config_->layer_target_bitrate[i] = config_->ss_target_bitrate[i]; | 
 |  136     } else if (num_temporal_layers_ == 2) { | 
 |  137       config_->layer_target_bitrate[i * num_temporal_layers_] = | 
 |  138           config_->ss_target_bitrate[i] * 2 / 3; | 
 |  139       config_->layer_target_bitrate[i * num_temporal_layers_ + 1] = | 
 |  140           config_->ss_target_bitrate[i]; | 
 |  141     } else if (num_temporal_layers_ == 3) { | 
 |  142       config_->layer_target_bitrate[i * num_temporal_layers_] = | 
 |  143           config_->ss_target_bitrate[i] / 2; | 
 |  144       config_->layer_target_bitrate[i * num_temporal_layers_ + 1] = | 
 |  145           config_->layer_target_bitrate[i * num_temporal_layers_] + | 
 |  146           (config_->ss_target_bitrate[i] / 4); | 
 |  147       config_->layer_target_bitrate[i * num_temporal_layers_ + 2] = | 
 |  148           config_->ss_target_bitrate[i]; | 
 |  149     } else { | 
 |  150       return false; | 
 |  151     } | 
 |  152   } | 
 |  153  | 
 |  154   // For now, temporal layers only supported when having one spatial layer. | 
 |  155   if (num_spatial_layers_ == 1) { | 
 |  156     for (i = 0; i < num_temporal_layers_; ++i) { | 
 |  157       config_->ts_target_bitrate[i] = config_->layer_target_bitrate[i]; | 
 |  158     } | 
 |  159   } | 
 |  160  | 
 |  161   return true; | 
 |  162 } | 
 |  163  | 
|  104 int VP9EncoderImpl::SetRates(uint32_t new_bitrate_kbit, |  164 int VP9EncoderImpl::SetRates(uint32_t new_bitrate_kbit, | 
|  105                              uint32_t new_framerate) { |  165                              uint32_t new_framerate) { | 
|  106   if (!inited_) { |  166   if (!inited_) { | 
|  107     return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |  167     return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 
|  108   } |  168   } | 
|  109   if (encoder_->err) { |  169   if (encoder_->err) { | 
|  110     return WEBRTC_VIDEO_CODEC_ERROR; |  170     return WEBRTC_VIDEO_CODEC_ERROR; | 
|  111   } |  171   } | 
|  112   if (new_framerate < 1) { |  172   if (new_framerate < 1) { | 
|  113     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |  173     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 
|  114   } |  174   } | 
|  115   // Update bit rate |  175   // Update bit rate | 
|  116   if (codec_.maxBitrate > 0 && new_bitrate_kbit > codec_.maxBitrate) { |  176   if (codec_.maxBitrate > 0 && new_bitrate_kbit > codec_.maxBitrate) { | 
|  117     new_bitrate_kbit = codec_.maxBitrate; |  177     new_bitrate_kbit = codec_.maxBitrate; | 
|  118   } |  178   } | 
|  119   config_->rc_target_bitrate = new_bitrate_kbit; |  179   config_->rc_target_bitrate = new_bitrate_kbit; | 
|  120   codec_.maxFramerate = new_framerate; |  180   codec_.maxFramerate = new_framerate; | 
 |  181  | 
 |  182   if (!SetSvcRates()) { | 
 |  183     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 
 |  184   } | 
 |  185  | 
|  121   // Update encoder context |  186   // Update encoder context | 
|  122   if (vpx_codec_enc_config_set(encoder_, config_)) { |  187   if (vpx_codec_enc_config_set(encoder_, config_)) { | 
|  123     return WEBRTC_VIDEO_CODEC_ERROR; |  188     return WEBRTC_VIDEO_CODEC_ERROR; | 
|  124   } |  189   } | 
|  125   return WEBRTC_VIDEO_CODEC_OK; |  190   return WEBRTC_VIDEO_CODEC_OK; | 
|  126 } |  191 } | 
|  127  |  192  | 
|  128 int VP9EncoderImpl::InitEncode(const VideoCodec* inst, |  193 int VP9EncoderImpl::InitEncode(const VideoCodec* inst, | 
|  129                                int number_of_cores, |  194                                int number_of_cores, | 
|  130                                size_t /*max_payload_size*/) { |  195                                size_t /*max_payload_size*/) { | 
|  131   if (inst == NULL) { |  196   if (inst == NULL) { | 
|  132     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |  197     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 
|  133   } |  198   } | 
|  134   if (inst->maxFramerate < 1) { |  199   if (inst->maxFramerate < 1) { | 
|  135     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |  200     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 
|  136   } |  201   } | 
|  137   // Allow zero to represent an unspecified maxBitRate |  202   // Allow zero to represent an unspecified maxBitRate | 
|  138   if (inst->maxBitrate > 0 && inst->startBitrate > inst->maxBitrate) { |  203   if (inst->maxBitrate > 0 && inst->startBitrate > inst->maxBitrate) { | 
|  139     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |  204     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 
|  140   } |  205   } | 
|  141   if (inst->width < 1 || inst->height < 1) { |  206   if (inst->width < 1 || inst->height < 1) { | 
|  142     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |  207     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 
|  143   } |  208   } | 
|  144   if (number_of_cores < 1) { |  209   if (number_of_cores < 1) { | 
|  145     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |  210     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 
|  146   } |  211   } | 
 |  212   if (inst->codecSpecific.VP9.numberOfTemporalLayers > 3) { | 
 |  213     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 
 |  214   } | 
 |  215   // For now, only support one spatial layer. | 
 |  216   if (inst->codecSpecific.VP9.numberOfSpatialLayers != 1) { | 
 |  217     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 
 |  218   } | 
|  147   int retVal = Release(); |  219   int retVal = Release(); | 
|  148   if (retVal < 0) { |  220   if (retVal < 0) { | 
|  149     return retVal; |  221     return retVal; | 
|  150   } |  222   } | 
|  151   if (encoder_ == NULL) { |  223   if (encoder_ == NULL) { | 
|  152     encoder_ = new vpx_codec_ctx_t; |  224     encoder_ = new vpx_codec_ctx_t; | 
|  153   } |  225   } | 
|  154   if (config_ == NULL) { |  226   if (config_ == NULL) { | 
|  155     config_ = new vpx_codec_enc_cfg_t; |  227     config_ = new vpx_codec_enc_cfg_t; | 
|  156   } |  228   } | 
|  157   timestamp_ = 0; |  229   timestamp_ = 0; | 
|  158   if (&codec_ != inst) { |  230   if (&codec_ != inst) { | 
|  159     codec_ = *inst; |  231     codec_ = *inst; | 
|  160   } |  232   } | 
 |  233  | 
 |  234   num_spatial_layers_ = inst->codecSpecific.VP9.numberOfSpatialLayers; | 
 |  235   num_temporal_layers_ = inst->codecSpecific.VP9.numberOfTemporalLayers; | 
 |  236   if (num_temporal_layers_ == 0) | 
 |  237     num_temporal_layers_ = 1; | 
 |  238  | 
|  161   // Random start 16 bits is enough. |  239   // Random start 16 bits is enough. | 
|  162   picture_id_ = static_cast<uint16_t>(rand()) & 0x7FFF; |  240   picture_id_ = static_cast<uint16_t>(rand()) & 0x7FFF; | 
|  163   // Allocate memory for encoded image |  241   // Allocate memory for encoded image | 
|  164   if (encoded_image_._buffer != NULL) { |  242   if (encoded_image_._buffer != NULL) { | 
|  165     delete [] encoded_image_._buffer; |  243     delete [] encoded_image_._buffer; | 
|  166   } |  244   } | 
|  167   encoded_image_._size = CalcBufferSize(kI420, codec_.width, codec_.height); |  245   encoded_image_._size = CalcBufferSize(kI420, codec_.width, codec_.height); | 
|  168   encoded_image_._buffer = new uint8_t[encoded_image_._size]; |  246   encoded_image_._buffer = new uint8_t[encoded_image_._size]; | 
|  169   encoded_image_._completeFrame = true; |  247   encoded_image_._completeFrame = true; | 
|  170   // Creating a wrapper to the image - setting image data to NULL. Actual |  248   // Creating a wrapper to the image - setting image data to NULL. Actual | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  202   if (inst->codecSpecific.VP9.keyFrameInterval  > 0) { |  280   if (inst->codecSpecific.VP9.keyFrameInterval  > 0) { | 
|  203     config_->kf_mode = VPX_KF_AUTO; |  281     config_->kf_mode = VPX_KF_AUTO; | 
|  204     config_->kf_max_dist = inst->codecSpecific.VP9.keyFrameInterval; |  282     config_->kf_max_dist = inst->codecSpecific.VP9.keyFrameInterval; | 
|  205   } else { |  283   } else { | 
|  206     config_->kf_mode = VPX_KF_DISABLED; |  284     config_->kf_mode = VPX_KF_DISABLED; | 
|  207   } |  285   } | 
|  208   // Determine number of threads based on the image size and #cores. |  286   // Determine number of threads based on the image size and #cores. | 
|  209   config_->g_threads = NumberOfThreads(config_->g_w, |  287   config_->g_threads = NumberOfThreads(config_->g_w, | 
|  210                                        config_->g_h, |  288                                        config_->g_h, | 
|  211                                        number_of_cores); |  289                                        number_of_cores); | 
 |  290  | 
|  212   cpu_speed_ = GetCpuSpeed(config_->g_w, config_->g_h); |  291   cpu_speed_ = GetCpuSpeed(config_->g_w, config_->g_h); | 
 |  292  | 
 |  293   // TODO(asapersson): Check configuration of temporal switch up and increase | 
 |  294   // pattern length. | 
 |  295   if (num_temporal_layers_ == 1) { | 
 |  296     gof_.SetGofInfoVP9(kTemporalStructureMode1); | 
 |  297     config_->temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING; | 
 |  298     config_->ts_number_layers = 1; | 
 |  299     config_->ts_rate_decimator[0] = 1; | 
 |  300     config_->ts_periodicity = 1; | 
 |  301     config_->ts_layer_id[0] = 0; | 
 |  302   } else if (num_temporal_layers_ == 2) { | 
 |  303     gof_.SetGofInfoVP9(kTemporalStructureMode2); | 
 |  304     config_->temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_0101; | 
 |  305     config_->ts_number_layers = 2; | 
 |  306     config_->ts_rate_decimator[0] = 2; | 
 |  307     config_->ts_rate_decimator[1] = 1; | 
 |  308     config_->ts_periodicity = 2; | 
 |  309     config_->ts_layer_id[0] = 0; | 
 |  310     config_->ts_layer_id[1] = 1; | 
 |  311   } else if (num_temporal_layers_ == 3) { | 
 |  312     gof_.SetGofInfoVP9(kTemporalStructureMode3); | 
 |  313     config_->temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_0212; | 
 |  314     config_->ts_number_layers = 3; | 
 |  315     config_->ts_rate_decimator[0] = 4; | 
 |  316     config_->ts_rate_decimator[1] = 2; | 
 |  317     config_->ts_rate_decimator[2] = 1; | 
 |  318     config_->ts_periodicity = 4; | 
 |  319     config_->ts_layer_id[0] = 0; | 
 |  320     config_->ts_layer_id[1] = 2; | 
 |  321     config_->ts_layer_id[2] = 1; | 
 |  322     config_->ts_layer_id[3] = 2; | 
 |  323   } else { | 
 |  324     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 
 |  325   } | 
 |  326  | 
 |  327   tl0_pic_idx_ = static_cast<uint8_t>(rand()); | 
 |  328  | 
|  213   return InitAndSetControlSettings(inst); |  329   return InitAndSetControlSettings(inst); | 
|  214 } |  330 } | 
|  215  |  331  | 
|  216 int VP9EncoderImpl::NumberOfThreads(int width, |  332 int VP9EncoderImpl::NumberOfThreads(int width, | 
|  217                                     int height, |  333                                     int height, | 
|  218                                     int number_of_cores) { |  334                                     int number_of_cores) { | 
 |  335   // For the current libvpx library, only 1 thread is supported when SVC is | 
 |  336   // turned on. | 
 |  337   if (num_temporal_layers_ > 1 || num_spatial_layers_ > 1) { | 
 |  338     return 1; | 
 |  339   } | 
 |  340  | 
|  219   // Keep the number of encoder threads equal to the possible number of column |  341   // Keep the number of encoder threads equal to the possible number of column | 
|  220   // tiles, which is (1, 2, 4, 8). See comments below for VP9E_SET_TILE_COLUMNS. |  342   // tiles, which is (1, 2, 4, 8). See comments below for VP9E_SET_TILE_COLUMNS. | 
|  221   if (width * height >= 1280 * 720 && number_of_cores > 4) { |  343   if (width * height >= 1280 * 720 && number_of_cores > 4) { | 
|  222     return 4; |  344     return 4; | 
|  223   } else if (width * height >= 640 * 480 && number_of_cores > 2) { |  345   } else if (width * height >= 640 * 480 && number_of_cores > 2) { | 
|  224     return 2; |  346     return 2; | 
|  225   } else { |  347   } else { | 
|  226     // 1 thread less than VGA. |  348     // 1 thread less than VGA. | 
|  227     return 1; |  349     return 1; | 
|  228   } |  350   } | 
|  229 } |  351 } | 
|  230  |  352  | 
|  231 int VP9EncoderImpl::InitAndSetControlSettings(const VideoCodec* inst) { |  353 int VP9EncoderImpl::InitAndSetControlSettings(const VideoCodec* inst) { | 
 |  354  | 
 |  355   config_->ss_number_layers = num_spatial_layers_; | 
 |  356  | 
 |  357   if (num_spatial_layers_ > 1) { | 
 |  358     config_->rc_min_quantizer = 0; | 
 |  359     config_->rc_max_quantizer = 63; | 
 |  360   } | 
 |  361   int scaling_factor_num = 256; | 
 |  362   for (int i = num_spatial_layers_ - 1; i >= 0; --i) { | 
 |  363     svc_internal_.svc_params.max_quantizers[i] = config_->rc_max_quantizer; | 
 |  364     svc_internal_.svc_params.min_quantizers[i] = config_->rc_min_quantizer; | 
 |  365     // 1:2 scaling in each dimension. | 
 |  366     svc_internal_.svc_params.scaling_factor_num[i] = scaling_factor_num; | 
 |  367     svc_internal_.svc_params.scaling_factor_den[i] = 256; | 
 |  368     scaling_factor_num /= 2; | 
 |  369   } | 
 |  370  | 
 |  371   if (!SetSvcRates()) { | 
 |  372     return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 
 |  373   } | 
 |  374  | 
|  232   if (vpx_codec_enc_init(encoder_, vpx_codec_vp9_cx(), config_, 0)) { |  375   if (vpx_codec_enc_init(encoder_, vpx_codec_vp9_cx(), config_, 0)) { | 
|  233     return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |  376     return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 
|  234   } |  377   } | 
|  235   vpx_codec_control(encoder_, VP8E_SET_CPUUSED, cpu_speed_); |  378   vpx_codec_control(encoder_, VP8E_SET_CPUUSED, cpu_speed_); | 
|  236   vpx_codec_control(encoder_, VP8E_SET_MAX_INTRA_BITRATE_PCT, |  379   vpx_codec_control(encoder_, VP8E_SET_MAX_INTRA_BITRATE_PCT, | 
|  237                     rc_max_intra_target_); |  380                     rc_max_intra_target_); | 
|  238   vpx_codec_control(encoder_, VP9E_SET_AQ_MODE, |  381   vpx_codec_control(encoder_, VP9E_SET_AQ_MODE, | 
|  239                     inst->codecSpecific.VP9.adaptiveQpMode ? 3 : 0); |  382                     inst->codecSpecific.VP9.adaptiveQpMode ? 3 : 0); | 
 |  383  | 
 |  384   vpx_codec_control( | 
 |  385       encoder_, VP9E_SET_SVC, | 
 |  386       (num_temporal_layers_ > 1 || num_spatial_layers_ > 1) ? 1 : 0); | 
 |  387   if (num_temporal_layers_ > 1 || num_spatial_layers_ > 1) { | 
 |  388     vpx_codec_control(encoder_, VP9E_SET_SVC_PARAMETERS, | 
 |  389                       &svc_internal_.svc_params); | 
 |  390   } | 
 |  391   // Register callback for getting each spatial layer. | 
 |  392   vpx_codec_priv_output_cx_pkt_cb_pair_t cbp = { | 
 |  393       VP9EncoderImpl::EncoderOutputCodedPacketCallback, (void*)(this)}; | 
 |  394   vpx_codec_control(encoder_, VP9E_REGISTER_CX_CALLBACK, (void*)(&cbp)); | 
 |  395  | 
|  240   // Control function to set the number of column tiles in encoding a frame, in |  396   // Control function to set the number of column tiles in encoding a frame, in | 
|  241   // log2 unit: e.g., 0 = 1 tile column, 1 = 2 tile columns, 2 = 4 tile columns. |  397   // log2 unit: e.g., 0 = 1 tile column, 1 = 2 tile columns, 2 = 4 tile columns. | 
|  242   // The number tile columns will be capped by the encoder based on image size |  398   // The number tile columns will be capped by the encoder based on image size | 
|  243   // (minimum width of tile column is 256 pixels, maximum is 4096). |  399   // (minimum width of tile column is 256 pixels, maximum is 4096). | 
|  244   vpx_codec_control(encoder_, VP9E_SET_TILE_COLUMNS, (config_->g_threads >> 1)); |  400   vpx_codec_control(encoder_, VP9E_SET_TILE_COLUMNS, (config_->g_threads >> 1)); | 
|  245 #if !defined(WEBRTC_ARCH_ARM) && !defined(WEBRTC_ARCH_ARM64) |  401 #if !defined(WEBRTC_ARCH_ARM) && !defined(WEBRTC_ARCH_ARM64) | 
|  246   // Note denoiser is still off by default until further testing/optimization, |  402   // Note denoiser is still off by default until further testing/optimization, | 
|  247   // i.e., codecSpecific.VP9.denoisingOn == 0. |  403   // i.e., codecSpecific.VP9.denoisingOn == 0. | 
|  248   vpx_codec_control(encoder_, VP9E_SET_NOISE_SENSITIVITY, |  404   vpx_codec_control(encoder_, VP9E_SET_NOISE_SENSITIVITY, | 
|  249                     inst->codecSpecific.VP9.denoisingOn ? 1 : 0); |  405                     inst->codecSpecific.VP9.denoisingOn ? 1 : 0); | 
| (...skipping 29 matching lines...) Expand all  Loading... | 
|  279   if (encoded_complete_callback_ == NULL) { |  435   if (encoded_complete_callback_ == NULL) { | 
|  280     return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |  436     return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 
|  281   } |  437   } | 
|  282   VideoFrameType frame_type = kDeltaFrame; |  438   VideoFrameType frame_type = kDeltaFrame; | 
|  283   // We only support one stream at the moment. |  439   // We only support one stream at the moment. | 
|  284   if (frame_types && frame_types->size() > 0) { |  440   if (frame_types && frame_types->size() > 0) { | 
|  285     frame_type = (*frame_types)[0]; |  441     frame_type = (*frame_types)[0]; | 
|  286   } |  442   } | 
|  287   DCHECK_EQ(input_image.width(), static_cast<int>(raw_->d_w)); |  443   DCHECK_EQ(input_image.width(), static_cast<int>(raw_->d_w)); | 
|  288   DCHECK_EQ(input_image.height(), static_cast<int>(raw_->d_h)); |  444   DCHECK_EQ(input_image.height(), static_cast<int>(raw_->d_h)); | 
 |  445  | 
 |  446   // Set input image for use in the callback. | 
 |  447   // This was necessary since you need some information from input_image. | 
 |  448   // You can save only the necessary information (such as timestamp) instead of | 
 |  449   // doing this. | 
 |  450   input_image_ = &input_image; | 
 |  451  | 
|  289   // Image in vpx_image_t format. |  452   // Image in vpx_image_t format. | 
|  290   // Input image is const. VPX's raw image is not defined as const. |  453   // Input image is const. VPX's raw image is not defined as const. | 
|  291   raw_->planes[VPX_PLANE_Y] = const_cast<uint8_t*>(input_image.buffer(kYPlane)); |  454   raw_->planes[VPX_PLANE_Y] = const_cast<uint8_t*>(input_image.buffer(kYPlane)); | 
|  292   raw_->planes[VPX_PLANE_U] = const_cast<uint8_t*>(input_image.buffer(kUPlane)); |  455   raw_->planes[VPX_PLANE_U] = const_cast<uint8_t*>(input_image.buffer(kUPlane)); | 
|  293   raw_->planes[VPX_PLANE_V] = const_cast<uint8_t*>(input_image.buffer(kVPlane)); |  456   raw_->planes[VPX_PLANE_V] = const_cast<uint8_t*>(input_image.buffer(kVPlane)); | 
|  294   raw_->stride[VPX_PLANE_Y] = input_image.stride(kYPlane); |  457   raw_->stride[VPX_PLANE_Y] = input_image.stride(kYPlane); | 
|  295   raw_->stride[VPX_PLANE_U] = input_image.stride(kUPlane); |  458   raw_->stride[VPX_PLANE_U] = input_image.stride(kUPlane); | 
|  296   raw_->stride[VPX_PLANE_V] = input_image.stride(kVPlane); |  459   raw_->stride[VPX_PLANE_V] = input_image.stride(kVPlane); | 
|  297  |  460  | 
|  298   int flags = 0; |  461   int flags = 0; | 
|  299   bool send_keyframe = (frame_type == kKeyFrame); |  462   bool send_keyframe = (frame_type == kKeyFrame); | 
|  300   if (send_keyframe) { |  463   if (send_keyframe) { | 
|  301     // Key frame request from caller. |  464     // Key frame request from caller. | 
|  302     flags = VPX_EFLAG_FORCE_KF; |  465     flags = VPX_EFLAG_FORCE_KF; | 
|  303   } |  466   } | 
|  304   assert(codec_.maxFramerate > 0); |  467   assert(codec_.maxFramerate > 0); | 
|  305   uint32_t duration = 90000 / codec_.maxFramerate; |  468   uint32_t duration = 90000 / codec_.maxFramerate; | 
|  306   if (vpx_codec_encode(encoder_, raw_, timestamp_, duration, flags, |  469   if (vpx_codec_encode(encoder_, raw_, timestamp_, duration, flags, | 
|  307                        VPX_DL_REALTIME)) { |  470                        VPX_DL_REALTIME)) { | 
|  308     return WEBRTC_VIDEO_CODEC_ERROR; |  471     return WEBRTC_VIDEO_CODEC_ERROR; | 
|  309   } |  472   } | 
|  310   timestamp_ += duration; |  473   timestamp_ += duration; | 
|  311   return GetEncodedPartitions(input_image); |  474  | 
 |  475   return WEBRTC_VIDEO_CODEC_OK; | 
|  312 } |  476 } | 
|  313  |  477  | 
|  314 void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific, |  478 void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific, | 
|  315                                        const vpx_codec_cx_pkt& pkt, |  479                                        const vpx_codec_cx_pkt& pkt, | 
|  316                                        uint32_t timestamp) { |  480                                        uint32_t timestamp) { | 
|  317   assert(codec_specific != NULL); |  481   assert(codec_specific != NULL); | 
|  318   codec_specific->codecType = kVideoCodecVP9; |  482   codec_specific->codecType = kVideoCodecVP9; | 
|  319   CodecSpecificInfoVP9 *vp9_info = &(codec_specific->codecSpecific.VP9); |  483   CodecSpecificInfoVP9 *vp9_info = &(codec_specific->codecSpecific.VP9); | 
|  320   vp9_info->pictureId = picture_id_; |  484   // TODO(asapersson): Set correct values. | 
|  321   vp9_info->keyIdx = kNoKeyIdx; |  485   vp9_info->inter_pic_predicted = | 
|  322   vp9_info->nonReference = (pkt.data.frame.flags & VPX_FRAME_IS_DROPPABLE) != 0; |  486       (pkt.data.frame.flags & VPX_FRAME_IS_KEY) ? false : true; | 
|  323   // TODO(marpan): Temporal layers are supported in the current VP9 version, |  487   vp9_info->flexible_mode = codec_.codecSpecific.VP9.flexibleMode; | 
|  324   // but for now use 1 temporal layer encoding. Will update this when temporal |  488   vp9_info->ss_data_available = | 
|  325   // layer support for VP9 is added in webrtc. |  489       (pkt.data.frame.flags & VPX_FRAME_IS_KEY) ? true : false; | 
|  326   vp9_info->temporalIdx = kNoTemporalIdx; |  490   if (pkt.data.frame.flags & VPX_FRAME_IS_KEY) { | 
|  327   vp9_info->layerSync = false; |  491     gof_idx_ = 0; | 
|  328   vp9_info->tl0PicIdx = kNoTl0PicIdx; |  492   } | 
|  329   picture_id_ = (picture_id_ + 1) & 0x7FFF; |  493  | 
 |  494   vpx_svc_layer_id_t layer_id = {0}; | 
 |  495   vpx_codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id); | 
 |  496  | 
 |  497   assert(num_temporal_layers_ > 0); | 
 |  498   assert(num_spatial_layers_ > 0); | 
 |  499   if (num_temporal_layers_ == 1) { | 
 |  500     assert(layer_id.temporal_layer_id == 0); | 
 |  501     vp9_info->temporal_idx = kNoTemporalIdx; | 
 |  502   } else { | 
 |  503     vp9_info->temporal_idx = layer_id.temporal_layer_id; | 
 |  504   } | 
 |  505   if (num_spatial_layers_ == 1) { | 
 |  506     assert(layer_id.spatial_layer_id == 0); | 
 |  507     vp9_info->spatial_idx = kNoSpatialIdx; | 
 |  508   } else { | 
 |  509     vp9_info->spatial_idx = layer_id.spatial_layer_id; | 
 |  510   } | 
 |  511   if (layer_id.spatial_layer_id != 0) { | 
 |  512     vp9_info->ss_data_available = false; | 
 |  513   } | 
 |  514  | 
 |  515   if (vp9_info->flexible_mode) { | 
 |  516     vp9_info->gof_idx = kNoGofIdx; | 
 |  517   } else { | 
 |  518     vp9_info->gof_idx = | 
 |  519         static_cast<uint8_t>(gof_idx_++ % gof_.num_frames_in_gof); | 
 |  520   } | 
 |  521  | 
 |  522   // TODO(asapersson): this info has to be obtained from the encoder. | 
 |  523   vp9_info->temporal_up_switch = true; | 
 |  524  | 
 |  525   if (layer_id.spatial_layer_id == 0) { | 
 |  526     picture_id_ = (picture_id_ + 1) & 0x7FFF; | 
 |  527     // TODO(asapersson): this info has to be obtained from the encoder. | 
 |  528     vp9_info->inter_layer_predicted = false; | 
 |  529   } else { | 
 |  530     // TODO(asapersson): this info has to be obtained from the encoder. | 
 |  531     vp9_info->inter_layer_predicted = true; | 
 |  532   } | 
 |  533  | 
 |  534   vp9_info->picture_id = picture_id_; | 
 |  535  | 
 |  536   if (!vp9_info->flexible_mode) { | 
 |  537     if (layer_id.temporal_layer_id == 0 && layer_id.spatial_layer_id == 0) { | 
 |  538       tl0_pic_idx_++; | 
 |  539     } | 
 |  540     vp9_info->tl0_pic_idx = tl0_pic_idx_; | 
 |  541   } | 
 |  542  | 
 |  543   if (vp9_info->ss_data_available) { | 
 |  544     vp9_info->num_spatial_layers = num_spatial_layers_; | 
 |  545     vp9_info->spatial_layer_resolution_present = true; | 
 |  546     for (size_t i = 0; i < vp9_info->num_spatial_layers; ++i) { | 
 |  547       vp9_info->width[i] = codec_.width * | 
 |  548                            svc_internal_.svc_params.scaling_factor_num[i] / | 
 |  549                            svc_internal_.svc_params.scaling_factor_den[i]; | 
 |  550       vp9_info->height[i] = codec_.height * | 
 |  551                             svc_internal_.svc_params.scaling_factor_num[i] / | 
 |  552                             svc_internal_.svc_params.scaling_factor_den[i]; | 
 |  553     } | 
 |  554     if (!vp9_info->flexible_mode) { | 
 |  555       vp9_info->gof.CopyGofInfoVP9(gof_); | 
 |  556     } | 
 |  557   } | 
|  330 } |  558 } | 
|  331  |  559  | 
|  332 int VP9EncoderImpl::GetEncodedPartitions(const VideoFrame& input_image) { |  560 int VP9EncoderImpl::GetEncodedLayerFrame(const vpx_codec_cx_pkt* pkt) { | 
|  333   vpx_codec_iter_t iter = NULL; |  | 
|  334   encoded_image_._length = 0; |  561   encoded_image_._length = 0; | 
|  335   encoded_image_._frameType = kDeltaFrame; |  562   encoded_image_._frameType = kDeltaFrame; | 
|  336   RTPFragmentationHeader frag_info; |  563   RTPFragmentationHeader frag_info; | 
|  337   // Note: no data partitioning in VP9, so 1 partition only. We keep this |  564   // Note: no data partitioning in VP9, so 1 partition only. We keep this | 
|  338   // fragmentation data for now, until VP9 packetizer is implemented. |  565   // fragmentation data for now, until VP9 packetizer is implemented. | 
|  339   frag_info.VerifyAndAllocateFragmentationHeader(1); |  566   frag_info.VerifyAndAllocateFragmentationHeader(1); | 
|  340   int part_idx = 0; |  567   int part_idx = 0; | 
|  341   CodecSpecificInfo codec_specific; |  568   CodecSpecificInfo codec_specific; | 
|  342   const vpx_codec_cx_pkt_t *pkt = NULL; |  569  | 
|  343   while ((pkt = vpx_codec_get_cx_data(encoder_, &iter)) != NULL) { |  570   assert(pkt->kind == VPX_CODEC_CX_FRAME_PKT); | 
|  344     switch (pkt->kind) { |  571   memcpy(&encoded_image_._buffer[encoded_image_._length], pkt->data.frame.buf, | 
|  345       case VPX_CODEC_CX_FRAME_PKT: { |  572          pkt->data.frame.sz); | 
|  346         memcpy(&encoded_image_._buffer[encoded_image_._length], |  573   frag_info.fragmentationOffset[part_idx] = encoded_image_._length; | 
|  347                pkt->data.frame.buf, |  574   frag_info.fragmentationLength[part_idx] = | 
|  348                pkt->data.frame.sz); |  575       static_cast<uint32_t>(pkt->data.frame.sz); | 
|  349         frag_info.fragmentationOffset[part_idx] = encoded_image_._length; |  576   frag_info.fragmentationPlType[part_idx] = 0; | 
|  350         frag_info.fragmentationLength[part_idx] = |  577   frag_info.fragmentationTimeDiff[part_idx] = 0; | 
|  351             static_cast<uint32_t>(pkt->data.frame.sz); |  578   encoded_image_._length += static_cast<uint32_t>(pkt->data.frame.sz); | 
|  352         frag_info.fragmentationPlType[part_idx] = 0; |  579   assert(encoded_image_._length <= encoded_image_._size); | 
|  353         frag_info.fragmentationTimeDiff[part_idx] = 0; |  580  | 
|  354         encoded_image_._length += static_cast<uint32_t>(pkt->data.frame.sz); |  581   // End of frame. | 
|  355         assert(encoded_image_._length <= encoded_image_._size); |  582   // Check if encoded frame is a key frame. | 
|  356         break; |  583   if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) { | 
|  357       } |  584     encoded_image_._frameType = kKeyFrame; | 
|  358       default: { |  | 
|  359         break; |  | 
|  360       } |  | 
|  361     } |  | 
|  362     // End of frame. |  | 
|  363     if ((pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT) == 0) { |  | 
|  364       // Check if encoded frame is a key frame. |  | 
|  365       if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) { |  | 
|  366         encoded_image_._frameType = kKeyFrame; |  | 
|  367       } |  | 
|  368       PopulateCodecSpecific(&codec_specific, *pkt, input_image.timestamp()); |  | 
|  369       break; |  | 
|  370     } |  | 
|  371   } |  585   } | 
 |  586   PopulateCodecSpecific(&codec_specific, *pkt, input_image_->timestamp()); | 
 |  587  | 
|  372   if (encoded_image_._length > 0) { |  588   if (encoded_image_._length > 0) { | 
|  373     TRACE_COUNTER1("webrtc", "EncodedFrameSize", encoded_image_._length); |  589     TRACE_COUNTER1("webrtc", "EncodedFrameSize", encoded_image_._length); | 
|  374     encoded_image_._timeStamp = input_image.timestamp(); |  590     encoded_image_._timeStamp = input_image_->timestamp(); | 
|  375     encoded_image_.capture_time_ms_ = input_image.render_time_ms(); |  591     encoded_image_.capture_time_ms_ = input_image_->render_time_ms(); | 
|  376     encoded_image_._encodedHeight = raw_->d_h; |  592     encoded_image_._encodedHeight = raw_->d_h; | 
|  377     encoded_image_._encodedWidth = raw_->d_w; |  593     encoded_image_._encodedWidth = raw_->d_w; | 
|  378     encoded_complete_callback_->Encoded(encoded_image_, &codec_specific, |  594     encoded_complete_callback_->Encoded(encoded_image_, &codec_specific, | 
|  379                                       &frag_info); |  595                                         &frag_info); | 
|  380   } |  596   } | 
|  381   return WEBRTC_VIDEO_CODEC_OK; |  597   return WEBRTC_VIDEO_CODEC_OK; | 
|  382 } |  598 } | 
|  383  |  599  | 
|  384 int VP9EncoderImpl::SetChannelParameters(uint32_t packet_loss, int64_t rtt) { |  600 int VP9EncoderImpl::SetChannelParameters(uint32_t packet_loss, int64_t rtt) { | 
|  385   return WEBRTC_VIDEO_CODEC_OK; |  601   return WEBRTC_VIDEO_CODEC_OK; | 
|  386 } |  602 } | 
|  387  |  603  | 
|  388 int VP9EncoderImpl::RegisterEncodeCompleteCallback( |  604 int VP9EncoderImpl::RegisterEncodeCompleteCallback( | 
|  389     EncodedImageCallback* callback) { |  605     EncodedImageCallback* callback) { | 
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  559     decoder_ = NULL; |  775     decoder_ = NULL; | 
|  560   } |  776   } | 
|  561   // Releases buffers from the pool. Any buffers not in use are deleted. Buffers |  777   // Releases buffers from the pool. Any buffers not in use are deleted. Buffers | 
|  562   // still referenced externally are deleted once fully released, not returning |  778   // still referenced externally are deleted once fully released, not returning | 
|  563   // to the pool. |  779   // to the pool. | 
|  564   frame_buffer_pool_.ClearPool(); |  780   frame_buffer_pool_.ClearPool(); | 
|  565   inited_ = false; |  781   inited_ = false; | 
|  566   return WEBRTC_VIDEO_CODEC_OK; |  782   return WEBRTC_VIDEO_CODEC_OK; | 
|  567 } |  783 } | 
|  568 }  // namespace webrtc |  784 }  // namespace webrtc | 
| OLD | NEW |