| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 | 126 |
| 127 VP8Encoder* VP8Encoder::Create() { | 127 VP8Encoder* VP8Encoder::Create() { |
| 128 return new VP8EncoderImpl(); | 128 return new VP8EncoderImpl(); |
| 129 } | 129 } |
| 130 | 130 |
| 131 VP8Decoder* VP8Decoder::Create() { | 131 VP8Decoder* VP8Decoder::Create() { |
| 132 return new VP8DecoderImpl(); | 132 return new VP8DecoderImpl(); |
| 133 } | 133 } |
| 134 | 134 |
| 135 vpx_enc_frame_flags_t VP8EncoderImpl::EncodeFlags( | 135 vpx_enc_frame_flags_t VP8EncoderImpl::EncodeFlags( |
| 136 TemporalReferences references) { | 136 const TemporalLayers::FrameConfig& references) { |
| 137 RTC_DCHECK(!references.drop_frame); | 137 RTC_DCHECK(!references.drop_frame); |
| 138 | 138 |
| 139 vpx_enc_frame_flags_t flags = 0; | 139 vpx_enc_frame_flags_t flags = 0; |
| 140 | 140 |
| 141 if ((references.last_buffer_flags & kReference) == 0) | 141 if ((references.last_buffer_flags & TemporalLayers::kReference) == 0) |
| 142 flags |= VP8_EFLAG_NO_REF_LAST; | 142 flags |= VP8_EFLAG_NO_REF_LAST; |
| 143 if ((references.last_buffer_flags & kUpdate) == 0) | 143 if ((references.last_buffer_flags & TemporalLayers::kUpdate) == 0) |
| 144 flags |= VP8_EFLAG_NO_UPD_LAST; | 144 flags |= VP8_EFLAG_NO_UPD_LAST; |
| 145 if ((references.golden_buffer_flags & kReference) == 0) | 145 if ((references.golden_buffer_flags & TemporalLayers::kReference) == 0) |
| 146 flags |= VP8_EFLAG_NO_REF_GF; | 146 flags |= VP8_EFLAG_NO_REF_GF; |
| 147 if ((references.golden_buffer_flags & kUpdate) == 0) | 147 if ((references.golden_buffer_flags & TemporalLayers::kUpdate) == 0) |
| 148 flags |= VP8_EFLAG_NO_UPD_GF; | 148 flags |= VP8_EFLAG_NO_UPD_GF; |
| 149 if ((references.arf_buffer_flags & kReference) == 0) | 149 if ((references.arf_buffer_flags & TemporalLayers::kReference) == 0) |
| 150 flags |= VP8_EFLAG_NO_REF_ARF; | 150 flags |= VP8_EFLAG_NO_REF_ARF; |
| 151 if ((references.arf_buffer_flags & kUpdate) == 0) | 151 if ((references.arf_buffer_flags & TemporalLayers::kUpdate) == 0) |
| 152 flags |= VP8_EFLAG_NO_UPD_ARF; | 152 flags |= VP8_EFLAG_NO_UPD_ARF; |
| 153 if (references.freeze_entropy) | 153 if (references.freeze_entropy) |
| 154 flags |= VP8_EFLAG_NO_UPD_ENTROPY; | 154 flags |= VP8_EFLAG_NO_UPD_ENTROPY; |
| 155 | 155 |
| 156 return flags; | 156 return flags; |
| 157 } | 157 } |
| 158 | 158 |
| 159 VP8EncoderImpl::VP8EncoderImpl() | 159 VP8EncoderImpl::VP8EncoderImpl() |
| 160 : use_gf_boost_(webrtc::field_trial::IsEnabled(kVp8GfBoostFieldTrial)), | 160 : use_gf_boost_(webrtc::field_trial::IsEnabled(kVp8GfBoostFieldTrial)), |
| 161 encoded_complete_callback_(nullptr), | 161 encoded_complete_callback_(nullptr), |
| (...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 696 raw_images_[i - 1].stride[VPX_PLANE_U], | 696 raw_images_[i - 1].stride[VPX_PLANE_U], |
| 697 raw_images_[i - 1].planes[VPX_PLANE_V], | 697 raw_images_[i - 1].planes[VPX_PLANE_V], |
| 698 raw_images_[i - 1].stride[VPX_PLANE_V], raw_images_[i - 1].d_w, | 698 raw_images_[i - 1].stride[VPX_PLANE_V], raw_images_[i - 1].d_w, |
| 699 raw_images_[i - 1].d_h, raw_images_[i].planes[VPX_PLANE_Y], | 699 raw_images_[i - 1].d_h, raw_images_[i].planes[VPX_PLANE_Y], |
| 700 raw_images_[i].stride[VPX_PLANE_Y], raw_images_[i].planes[VPX_PLANE_U], | 700 raw_images_[i].stride[VPX_PLANE_Y], raw_images_[i].planes[VPX_PLANE_U], |
| 701 raw_images_[i].stride[VPX_PLANE_U], raw_images_[i].planes[VPX_PLANE_V], | 701 raw_images_[i].stride[VPX_PLANE_U], raw_images_[i].planes[VPX_PLANE_V], |
| 702 raw_images_[i].stride[VPX_PLANE_V], raw_images_[i].d_w, | 702 raw_images_[i].stride[VPX_PLANE_V], raw_images_[i].d_w, |
| 703 raw_images_[i].d_h, libyuv::kFilterBilinear); | 703 raw_images_[i].d_h, libyuv::kFilterBilinear); |
| 704 } | 704 } |
| 705 vpx_enc_frame_flags_t flags[kMaxSimulcastStreams]; | 705 vpx_enc_frame_flags_t flags[kMaxSimulcastStreams]; |
| 706 TemporalLayers::FrameConfig tl_configs[kMaxSimulcastStreams]; |
| 706 for (size_t i = 0; i < encoders_.size(); ++i) { | 707 for (size_t i = 0; i < encoders_.size(); ++i) { |
| 707 TemporalReferences tl_config = | 708 tl_configs[i] = temporal_layers_[i]->UpdateLayerConfig(frame.timestamp()); |
| 708 temporal_layers_[i]->UpdateLayerConfig(frame.timestamp()); | |
| 709 | 709 |
| 710 if (tl_config.drop_frame) { | 710 if (tl_configs[i].drop_frame) { |
| 711 // Drop this frame. | 711 // Drop this frame. |
| 712 return WEBRTC_VIDEO_CODEC_OK; | 712 return WEBRTC_VIDEO_CODEC_OK; |
| 713 } | 713 } |
| 714 flags[i] = EncodeFlags(tl_config); | 714 flags[i] = EncodeFlags(tl_configs[i]); |
| 715 } | 715 } |
| 716 bool send_key_frame = false; | 716 bool send_key_frame = false; |
| 717 for (size_t i = 0; i < key_frame_request_.size() && i < send_stream_.size(); | 717 for (size_t i = 0; i < key_frame_request_.size() && i < send_stream_.size(); |
| 718 ++i) { | 718 ++i) { |
| 719 if (key_frame_request_[i] && send_stream_[i]) { | 719 if (key_frame_request_[i] && send_stream_[i]) { |
| 720 send_key_frame = true; | 720 send_key_frame = true; |
| 721 break; | 721 break; |
| 722 } | 722 } |
| 723 } | 723 } |
| 724 if (!send_key_frame && frame_types) { | 724 if (!send_key_frame && frame_types) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 757 // change isn't stored in configurations_ so change will be discarded at | 757 // change isn't stored in configurations_ so change will be discarded at |
| 758 // the next update. | 758 // the next update. |
| 759 vpx_codec_enc_cfg_t temp_config; | 759 vpx_codec_enc_cfg_t temp_config; |
| 760 memcpy(&temp_config, &configurations_[i], sizeof(vpx_codec_enc_cfg_t)); | 760 memcpy(&temp_config, &configurations_[i], sizeof(vpx_codec_enc_cfg_t)); |
| 761 if (temporal_layers_[stream_idx]->UpdateConfiguration(&temp_config)) { | 761 if (temporal_layers_[stream_idx]->UpdateConfiguration(&temp_config)) { |
| 762 if (vpx_codec_enc_config_set(&encoders_[i], &temp_config)) | 762 if (vpx_codec_enc_config_set(&encoders_[i], &temp_config)) |
| 763 return WEBRTC_VIDEO_CODEC_ERROR; | 763 return WEBRTC_VIDEO_CODEC_ERROR; |
| 764 } | 764 } |
| 765 | 765 |
| 766 vpx_codec_control(&encoders_[i], VP8E_SET_FRAME_FLAGS, flags[stream_idx]); | 766 vpx_codec_control(&encoders_[i], VP8E_SET_FRAME_FLAGS, flags[stream_idx]); |
| 767 vpx_codec_control(&encoders_[i], VP8E_SET_TEMPORAL_LAYER_ID, | 767 vpx_codec_control( |
| 768 temporal_layers_[stream_idx]->CurrentLayerId()); | 768 &encoders_[i], VP8E_SET_TEMPORAL_LAYER_ID, |
| 769 temporal_layers_[stream_idx]->GetTemporalLayerId(tl_configs[i])); |
| 769 } | 770 } |
| 770 // TODO(holmer): Ideally the duration should be the timestamp diff of this | 771 // TODO(holmer): Ideally the duration should be the timestamp diff of this |
| 771 // frame and the next frame to be encoded, which we don't have. Instead we | 772 // frame and the next frame to be encoded, which we don't have. Instead we |
| 772 // would like to use the duration of the previous frame. Unfortunately the | 773 // would like to use the duration of the previous frame. Unfortunately the |
| 773 // rate control seems to be off with that setup. Using the average input | 774 // rate control seems to be off with that setup. Using the average input |
| 774 // frame rate to calculate an average duration for now. | 775 // frame rate to calculate an average duration for now. |
| 775 assert(codec_.maxFramerate > 0); | 776 assert(codec_.maxFramerate > 0); |
| 776 uint32_t duration = 90000 / codec_.maxFramerate; | 777 uint32_t duration = 90000 / codec_.maxFramerate; |
| 777 | 778 |
| 778 // Note we must pass 0 for |flags| field in encode call below since they are | 779 // Note we must pass 0 for |flags| field in encode call below since they are |
| 779 // set above in |vpx_codec_control| function for each encoder/spatial layer. | 780 // set above in |vpx_codec_control| function for each encoder/spatial layer. |
| 780 int error = vpx_codec_encode(&encoders_[0], &raw_images_[0], timestamp_, | 781 int error = vpx_codec_encode(&encoders_[0], &raw_images_[0], timestamp_, |
| 781 duration, 0, VPX_DL_REALTIME); | 782 duration, 0, VPX_DL_REALTIME); |
| 782 // Reset specific intra frame thresholds, following the key frame. | 783 // Reset specific intra frame thresholds, following the key frame. |
| 783 if (send_key_frame) { | 784 if (send_key_frame) { |
| 784 vpx_codec_control(&(encoders_[0]), VP8E_SET_MAX_INTRA_BITRATE_PCT, | 785 vpx_codec_control(&(encoders_[0]), VP8E_SET_MAX_INTRA_BITRATE_PCT, |
| 785 rc_max_intra_target_); | 786 rc_max_intra_target_); |
| 786 } | 787 } |
| 787 if (error) | 788 if (error) |
| 788 return WEBRTC_VIDEO_CODEC_ERROR; | 789 return WEBRTC_VIDEO_CODEC_ERROR; |
| 789 timestamp_ += duration; | 790 timestamp_ += duration; |
| 790 // Examines frame timestamps only. | 791 // Examines frame timestamps only. |
| 791 return GetEncodedPartitions(frame); | 792 return GetEncodedPartitions(tl_configs, frame); |
| 792 } | 793 } |
| 793 | 794 |
| 794 void VP8EncoderImpl::PopulateCodecSpecific( | 795 void VP8EncoderImpl::PopulateCodecSpecific( |
| 795 CodecSpecificInfo* codec_specific, | 796 CodecSpecificInfo* codec_specific, |
| 797 const TemporalLayers::FrameConfig& tl_config, |
| 796 const vpx_codec_cx_pkt_t& pkt, | 798 const vpx_codec_cx_pkt_t& pkt, |
| 797 int stream_idx, | 799 int stream_idx, |
| 798 uint32_t timestamp) { | 800 uint32_t timestamp) { |
| 799 assert(codec_specific != NULL); | 801 assert(codec_specific != NULL); |
| 800 codec_specific->codecType = kVideoCodecVP8; | 802 codec_specific->codecType = kVideoCodecVP8; |
| 801 codec_specific->codec_name = ImplementationName(); | 803 codec_specific->codec_name = ImplementationName(); |
| 802 CodecSpecificInfoVP8* vp8Info = &(codec_specific->codecSpecific.VP8); | 804 CodecSpecificInfoVP8* vp8Info = &(codec_specific->codecSpecific.VP8); |
| 803 vp8Info->pictureId = picture_id_[stream_idx]; | 805 vp8Info->pictureId = picture_id_[stream_idx]; |
| 804 vp8Info->simulcastIdx = stream_idx; | 806 vp8Info->simulcastIdx = stream_idx; |
| 805 vp8Info->keyIdx = kNoKeyIdx; // TODO(hlundin) populate this | 807 vp8Info->keyIdx = kNoKeyIdx; // TODO(hlundin) populate this |
| 806 vp8Info->nonReference = (pkt.data.frame.flags & VPX_FRAME_IS_DROPPABLE) != 0; | 808 vp8Info->nonReference = (pkt.data.frame.flags & VPX_FRAME_IS_DROPPABLE) != 0; |
| 807 temporal_layers_[stream_idx]->PopulateCodecSpecific( | 809 temporal_layers_[stream_idx]->PopulateCodecSpecific( |
| 808 (pkt.data.frame.flags & VPX_FRAME_IS_KEY) != 0, vp8Info, timestamp); | 810 (pkt.data.frame.flags & VPX_FRAME_IS_KEY) != 0, tl_config, vp8Info, |
| 811 timestamp); |
| 809 // Prepare next. | 812 // Prepare next. |
| 810 picture_id_[stream_idx] = (picture_id_[stream_idx] + 1) & 0x7FFF; | 813 picture_id_[stream_idx] = (picture_id_[stream_idx] + 1) & 0x7FFF; |
| 811 } | 814 } |
| 812 | 815 |
| 813 int VP8EncoderImpl::GetEncodedPartitions(const VideoFrame& input_image) { | 816 int VP8EncoderImpl::GetEncodedPartitions( |
| 817 const TemporalLayers::FrameConfig tl_configs[], |
| 818 const VideoFrame& input_image) { |
| 814 int bw_resolutions_disabled = | 819 int bw_resolutions_disabled = |
| 815 (encoders_.size() > 1) ? NumStreamsDisabled(send_stream_) : -1; | 820 (encoders_.size() > 1) ? NumStreamsDisabled(send_stream_) : -1; |
| 816 | 821 |
| 817 int stream_idx = static_cast<int>(encoders_.size()) - 1; | 822 int stream_idx = static_cast<int>(encoders_.size()) - 1; |
| 818 int result = WEBRTC_VIDEO_CODEC_OK; | 823 int result = WEBRTC_VIDEO_CODEC_OK; |
| 819 for (size_t encoder_idx = 0; encoder_idx < encoders_.size(); | 824 for (size_t encoder_idx = 0; encoder_idx < encoders_.size(); |
| 820 ++encoder_idx, --stream_idx) { | 825 ++encoder_idx, --stream_idx) { |
| 821 vpx_codec_iter_t iter = NULL; | 826 vpx_codec_iter_t iter = NULL; |
| 822 int part_idx = 0; | 827 int part_idx = 0; |
| 823 encoded_images_[encoder_idx]._length = 0; | 828 encoded_images_[encoder_idx]._length = 0; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 853 } | 858 } |
| 854 default: | 859 default: |
| 855 break; | 860 break; |
| 856 } | 861 } |
| 857 // End of frame | 862 // End of frame |
| 858 if ((pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT) == 0) { | 863 if ((pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT) == 0) { |
| 859 // check if encoded frame is a key frame | 864 // check if encoded frame is a key frame |
| 860 if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) { | 865 if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) { |
| 861 encoded_images_[encoder_idx]._frameType = kVideoFrameKey; | 866 encoded_images_[encoder_idx]._frameType = kVideoFrameKey; |
| 862 } | 867 } |
| 863 PopulateCodecSpecific(&codec_specific, *pkt, stream_idx, | 868 PopulateCodecSpecific(&codec_specific, tl_configs[stream_idx], *pkt, |
| 864 input_image.timestamp()); | 869 stream_idx, input_image.timestamp()); |
| 865 break; | 870 break; |
| 866 } | 871 } |
| 867 } | 872 } |
| 868 encoded_images_[encoder_idx]._timeStamp = input_image.timestamp(); | 873 encoded_images_[encoder_idx]._timeStamp = input_image.timestamp(); |
| 869 encoded_images_[encoder_idx].capture_time_ms_ = | 874 encoded_images_[encoder_idx].capture_time_ms_ = |
| 870 input_image.render_time_ms(); | 875 input_image.render_time_ms(); |
| 871 encoded_images_[encoder_idx].rotation_ = input_image.rotation(); | 876 encoded_images_[encoder_idx].rotation_ = input_image.rotation(); |
| 872 encoded_images_[encoder_idx].content_type_ = | 877 encoded_images_[encoder_idx].content_type_ = |
| 873 (codec_.mode == kScreensharing) ? VideoContentType::SCREENSHARE | 878 (codec_.mode == kScreensharing) ? VideoContentType::SCREENSHARE |
| 874 : VideoContentType::UNSPECIFIED; | 879 : VideoContentType::UNSPECIFIED; |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1143 buffer_pool_.Release(); | 1148 buffer_pool_.Release(); |
| 1144 inited_ = false; | 1149 inited_ = false; |
| 1145 return WEBRTC_VIDEO_CODEC_OK; | 1150 return WEBRTC_VIDEO_CODEC_OK; |
| 1146 } | 1151 } |
| 1147 | 1152 |
| 1148 const char* VP8DecoderImpl::ImplementationName() const { | 1153 const char* VP8DecoderImpl::ImplementationName() const { |
| 1149 return "libvpx"; | 1154 return "libvpx"; |
| 1150 } | 1155 } |
| 1151 | 1156 |
| 1152 } // namespace webrtc | 1157 } // namespace webrtc |
| OLD | NEW |