Index: content/renderer/media/rtc_encoding_video_capturer.cc |
diff --git a/content/renderer/media/rtc_encoding_video_capturer.cc b/content/renderer/media/rtc_encoding_video_capturer.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6fe22d29272be4acc11550f968db14431fed1670 |
--- /dev/null |
+++ b/content/renderer/media/rtc_encoding_video_capturer.cc |
@@ -0,0 +1,228 @@ |
+// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/renderer/media/rtc_encoding_video_capturer.h" |
+ |
+#include "base/logging.h" |
+#include "media/base/encoded_bitstream_buffer.h" |
+ |
+namespace content { |
+ |
+// Client of EncodedVideoSource. This object is created and owned by the |
+// RtcEncodingVideoCapturer. |
+class RtcEncodingVideoCapturer::EncodedVideoSourceClient : |
+ public media::EncodedVideoSource::Client { |
+ public: |
+ EncodedVideoSourceClient( |
+ media::EncodedVideoSource* encoded_video_source, |
+ media::VideoEncodingParameters params, |
+ webrtc::VideoCodecType rtc_codec_type); |
+ virtual ~EncodedVideoSourceClient(); |
+ |
+ // media::EncodedVideoSource::Client implementation. |
+ virtual void OnOpened( |
+ const media::VideoEncodingParameters& params) OVERRIDE; |
+ virtual void OnClosed() OVERRIDE; |
+ virtual void OnBufferReady( |
+ scoped_refptr<const media::EncodedBitstreamBuffer> buffer) OVERRIDE; |
+ virtual void OnConfigChanged( |
+ const media::RuntimeVideoEncodingParameters& params) OVERRIDE; |
+ |
+ // Getters and setters for bitstream properties. |
+ media::RuntimeVideoEncodingParameters runtime_params() const; |
+ void set_round_trip_time(base::TimeDelta round_trip_time); |
+ void set_callback(webrtc::EncodedImageCallback* callback); |
+ |
+ private: |
+ // Convert buffer to webrtc types and invoke encode complete callback. |
+ void ReportEncodedFrame( |
+ scoped_refptr<const media::EncodedBitstreamBuffer> buffer); |
+ |
+ media::VideoEncodingParameters params_; |
+ webrtc::VideoCodecType rtc_codec_type_; |
+ bool finished_; |
+ |
+ base::Time time_base_; |
+ base::TimeDelta round_trip_time_; |
+ media::EncodedVideoSource* encoded_video_source_; |
+ webrtc::EncodedImageCallback* callback_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(EncodedVideoSourceClient); |
+}; |
+ |
+RtcEncodingVideoCapturer::EncodedVideoSourceClient::EncodedVideoSourceClient( |
+ media::EncodedVideoSource* encoded_video_source, |
+ media::VideoEncodingParameters params, |
+ webrtc::VideoCodecType rtc_codec_type) |
+ : params_(params), |
+ rtc_codec_type_(rtc_codec_type), |
+ finished_(false), |
+ encoded_video_source_(encoded_video_source), |
+ callback_(NULL) { |
+ DCHECK(encoded_video_source_); |
+ encoded_video_source_->OpenBitstream(this, params); |
+} |
+ |
+RtcEncodingVideoCapturer::EncodedVideoSourceClient:: |
+ ~EncodedVideoSourceClient() { |
+ if (!finished_) |
+ encoded_video_source_->CloseBitstream(); |
+} |
+ |
+media::RuntimeVideoEncodingParameters |
+ RtcEncodingVideoCapturer::EncodedVideoSourceClient::runtime_params() const { |
+ return params_.runtime_params; |
+} |
+ |
+void RtcEncodingVideoCapturer::EncodedVideoSourceClient::set_round_trip_time( |
+ base::TimeDelta round_trip_time) { |
+ round_trip_time_ = round_trip_time; |
+} |
+ |
+void RtcEncodingVideoCapturer::EncodedVideoSourceClient::set_callback( |
+ webrtc::EncodedImageCallback* callback) { |
+ DCHECK(!callback_); |
+ callback_ = callback; |
+} |
+ |
+void RtcEncodingVideoCapturer::EncodedVideoSourceClient::OnOpened( |
+ const media::VideoEncodingParameters& params) { |
+ params_ = params; |
+} |
+ |
+void RtcEncodingVideoCapturer::EncodedVideoSourceClient::OnClosed() { |
+ finished_ = true; |
+} |
+ |
+void RtcEncodingVideoCapturer::EncodedVideoSourceClient::OnBufferReady( |
+ scoped_refptr<const media::EncodedBitstreamBuffer> buffer) { |
+ DCHECK(!finished_ && buffer); |
+ |
+ // First buffer constitutes the origin of the time for this bitstream context. |
+ if (time_base_.is_null()) |
+ time_base_ = buffer->metadata().timestamp; |
+ |
+ ReportEncodedFrame(buffer); |
+ encoded_video_source_->ReturnBitstreamBuffer(buffer); |
+} |
+ |
+void RtcEncodingVideoCapturer::EncodedVideoSourceClient::OnConfigChanged( |
+ const media::RuntimeVideoEncodingParameters& params) { |
+ params_.runtime_params = params; |
+} |
+ |
+void RtcEncodingVideoCapturer::EncodedVideoSourceClient::ReportEncodedFrame( |
+ scoped_refptr<const media::EncodedBitstreamBuffer> buffer) { |
+ if (!callback_) |
+ return; |
+ |
+ webrtc::EncodedImage image; |
+ webrtc::CodecSpecificInfo codecInfo; |
+ webrtc::RTPFragmentationHeader fragHeader; |
+ |
+ // TODO(hshi): remove this const_cast. Unfortunately webrtc::EncodedImage |
+ // defines member |_buffer| of type uint8_t* even though webrtc never modifies |
+ // the buffer contents. |
+ image._buffer = const_cast<uint8_t*>(buffer->buffer()); |
+ image._length = buffer->size(); |
+ image._size = image._length; |
+ |
+ const media::BufferEncodingMetadata& metadata = buffer->metadata(); |
+ base::TimeDelta capture_time = metadata.timestamp - time_base_; |
+ image.capture_time_ms_ = capture_time.InMilliseconds(); |
+ // Convert capture time to 90 kHz RTP timestamp. |
+ image._timeStamp = (capture_time * 90000).InSeconds(); |
+ if (metadata.key_frame) { |
+ image._frameType = webrtc::kKeyFrame; |
+ } else { |
+ image._frameType = webrtc::kDeltaFrame; |
+ } |
+ image._completeFrame = true; |
+ image._encodedWidth = params_.resolution.width(); |
+ image._encodedHeight = params_.resolution.height(); |
+ |
+ // TODO(hshi): generate codec specific info for VP8. |
+ codecInfo.codecType = rtc_codec_type_; |
+ |
+ // Generate header containing a single fragmentation. |
+ fragHeader.VerifyAndAllocateFragmentationHeader(1); |
+ fragHeader.fragmentationOffset[0] = 0; |
+ fragHeader.fragmentationLength[0] = buffer->size(); |
+ fragHeader.fragmentationPlType[0] = 0; |
+ fragHeader.fragmentationTimeDiff[0] = 0; |
+ |
+ callback_->Encoded(image, &codecInfo, &fragHeader); |
+} |
+ |
+// RtcEncodingVideoCapturer |
+RtcEncodingVideoCapturer::RtcEncodingVideoCapturer( |
+ media::EncodedVideoSource* encoded_video_source, |
+ webrtc::VideoCodecType codec_type) |
+ : encoded_video_source_(encoded_video_source), |
+ rtc_codec_type_(codec_type) { |
+} |
+ |
+RtcEncodingVideoCapturer::~RtcEncodingVideoCapturer() { |
+} |
+ |
+int32_t RtcEncodingVideoCapturer::InitEncode( |
+ const webrtc::VideoCodec* codecSettings, |
+ int32_t numberOfCores, |
+ uint32_t maxPayloadSize) { |
+ DCHECK(!encoded_video_source_client_); |
+ if (codecSettings->codecType != rtc_codec_type_) |
+ return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
+ |
+ // Convert |codecSettings| to |params|. |
+ media::VideoEncodingParameters params; |
+ params.codec_name = codecSettings->plName; |
+ params.resolution = gfx::Size(codecSettings->width, codecSettings->height); |
+ params.runtime_params.target_bitrate = codecSettings->startBitrate; |
+ params.runtime_params.max_bitrate = codecSettings->maxBitrate; |
+ params.runtime_params.frames_per_second = codecSettings->maxFramerate; |
+ encoded_video_source_client_.reset(new EncodedVideoSourceClient( |
+ encoded_video_source_, params, rtc_codec_type_)); |
+ return WEBRTC_VIDEO_CODEC_OK; |
+} |
+ |
+int32_t RtcEncodingVideoCapturer::Encode( |
+ const webrtc::I420VideoFrame& /* inputImage */, |
+ const webrtc::CodecSpecificInfo* codecSpecificInfo, |
+ const std::vector<webrtc::VideoFrameType>* frame_types) { |
+ // TODO(hshi): request specific frame type. |
+ return WEBRTC_VIDEO_CODEC_OK; |
+} |
+ |
+int32_t RtcEncodingVideoCapturer::RegisterEncodeCompleteCallback( |
+ webrtc::EncodedImageCallback* callback) { |
+ DCHECK(encoded_video_source_client_); |
+ encoded_video_source_client_->set_callback(callback); |
+ return WEBRTC_VIDEO_CODEC_OK; |
+} |
+ |
+int32_t RtcEncodingVideoCapturer::Release() { |
+ DCHECK(encoded_video_source_client_); |
+ encoded_video_source_client_.reset(NULL); |
+ return WEBRTC_VIDEO_CODEC_OK; |
+} |
+ |
+int32_t RtcEncodingVideoCapturer::SetChannelParameters( |
+ uint32_t /* packetLoss */, |
+ int rtt_in_ms) { |
+ if (!encoded_video_source_client_) |
+ return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
+ encoded_video_source_client_->set_round_trip_time( |
+ base::TimeDelta::FromMilliseconds(rtt_in_ms)); |
+ return WEBRTC_VIDEO_CODEC_OK; |
+} |
+ |
+int32_t RtcEncodingVideoCapturer::SetRates(uint32_t newBitRate, |
+ uint32_t frameRate) { |
+ if (!encoded_video_source_client_) |
+ return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
+ // TODO(hshi): wire up runtime rate control. |
+ return WEBRTC_VIDEO_CODEC_OK; |
+} |
+ |
+} // namespace content |