Index: content/renderer/media/webrtc/video_destination_handler.cc |
diff --git a/content/renderer/media/video_destination_handler.cc b/content/renderer/media/webrtc/video_destination_handler.cc |
similarity index 40% |
rename from content/renderer/media/video_destination_handler.cc |
rename to content/renderer/media/webrtc/video_destination_handler.cc |
index a76ca8974d855aa24476d9354ec7b6766848d951..ca3d4e45ffabc05c62e53bc147a09a0ffb04fd15 100644 |
--- a/content/renderer/media/video_destination_handler.cc |
+++ b/content/renderer/media/webrtc/video_destination_handler.cc |
@@ -2,102 +2,65 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "content/renderer/media/video_destination_handler.h" |
+#include "content/renderer/media/webrtc/video_destination_handler.h" |
#include <string> |
#include "base/base64.h" |
#include "base/logging.h" |
#include "base/rand_util.h" |
+#include "base/strings/utf_string_conversions.h" |
#include "content/renderer/media/media_stream.h" |
#include "content/renderer/media/media_stream_dependency_factory.h" |
#include "content/renderer/media/media_stream_registry_interface.h" |
+#include "content/renderer/media/media_stream_video_track.h" |
#include "content/renderer/pepper/ppb_image_data_impl.h" |
#include "content/renderer/render_thread_impl.h" |
+#include "media/video/capture/video_capture_types.h" |
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" |
#include "third_party/WebKit/public/platform/WebURL.h" |
#include "third_party/WebKit/public/web/WebMediaStreamRegistry.h" |
+#include "third_party/libyuv/include/libyuv/convert.h" |
#include "url/gurl.h" |
-using cricket::CaptureState; |
-using cricket::VideoFormat; |
-using webrtc::VideoTrackInterface; |
-using webrtc::VideoTrackVector; |
- |
-static const cricket::FourCC kEffectColorFormat = cricket::FOURCC_BGRA; |
- |
namespace content { |
-PpFrameWriter::PpFrameWriter() |
- : started_(false) {} |
- |
-PpFrameWriter::~PpFrameWriter() {} |
- |
-CaptureState PpFrameWriter::Start(const VideoFormat& capture_format) { |
- base::AutoLock auto_lock(lock_); |
- if (started_) { |
- LOG(ERROR) << "PpFrameWriter::Start - " |
- << "Got a StartCapture when already started!"; |
- return cricket::CS_FAILED; |
- } |
- started_ = true; |
- return cricket::CS_STARTING; |
-} |
- |
-void PpFrameWriter::Stop() { |
- base::AutoLock auto_lock(lock_); |
- started_ = false; |
- SignalStateChange(this, cricket::CS_STOPPED); |
+PpFrameWriter::PpFrameWriter(MediaStreamDependencyFactory* factory) |
+ : MediaStreamVideoSource(factory), first_frame_received_(false) { |
+ DVLOG(3) << "PpFrameWriter ctor"; |
} |
-bool PpFrameWriter::IsRunning() { |
- return started_; |
+PpFrameWriter::~PpFrameWriter() { |
+ DVLOG(3) << "PpFrameWriter dtor"; |
} |
-bool PpFrameWriter::GetPreferredFourccs(std::vector<uint32>* fourccs) { |
- if (!fourccs) { |
- LOG(ERROR) << "PpFrameWriter::GetPreferredFourccs - " |
- << "fourccs is NULL."; |
- return false; |
+void PpFrameWriter::GetCurrentSupportedFormats(int max_requested_width, |
+ int max_requested_height) { |
+ DCHECK(CalledOnValidThread()); |
+ DVLOG(3) << "PpFrameWriter::GetCurrentSupportedFormats()"; |
+ if (format_.IsValid()) { |
+ media::VideoCaptureFormats formats; |
+ formats.push_back(format_); |
+ OnSupportedFormats(formats); |
} |
- // The effects plugin output BGRA. |
- fourccs->push_back(kEffectColorFormat); |
- return true; |
} |
-bool PpFrameWriter::GetBestCaptureFormat(const VideoFormat& desired, |
- VideoFormat* best_format) { |
- if (!best_format) { |
- LOG(ERROR) << "PpFrameWriter::GetBestCaptureFormat - " |
- << "best_format is NULL."; |
- return false; |
- } |
- |
- // Use the desired format as the best format. |
- best_format->width = desired.width; |
- best_format->height = desired.height; |
- best_format->fourcc = kEffectColorFormat; |
- best_format->interval = desired.interval; |
- return true; |
+void PpFrameWriter::StartSourceImpl( |
+ const media::VideoCaptureParams& params) { |
+ DCHECK(CalledOnValidThread()); |
+ DVLOG(3) << "PpFrameWriter::StartSourceImpl()"; |
+ OnStartDone(true); |
} |
-bool PpFrameWriter::IsScreencast() const { |
- return false; |
+void PpFrameWriter::StopSourceImpl() { |
+ DCHECK(CalledOnValidThread()); |
} |
void PpFrameWriter::PutFrame(PPB_ImageData_Impl* image_data, |
int64 time_stamp_ns) { |
- base::AutoLock auto_lock(lock_); |
- // This assumes the handler of the SignalFrameCaptured won't call Start/Stop. |
- // TODO(ronghuawu): Avoid the using of lock. One way is to post this call to |
- // libjingle worker thread, which will require an extra copy of |image_data|. |
- // However if pepper host can hand over the ownership of |image_data| |
- // then we can avoid this extra copy. |
- if (!started_) { |
- LOG(ERROR) << "PpFrameWriter::PutFrame - " |
- << "Called when capturer is not started."; |
- return; |
- } |
+ DCHECK(CalledOnValidThread()); |
+ DVLOG(3) << "PpFrameWriter::PutFrame()"; |
+ |
if (!image_data) { |
LOG(ERROR) << "PpFrameWriter::PutFrame - Called with NULL image_data."; |
return; |
@@ -115,36 +78,51 @@ void PpFrameWriter::PutFrame(PPB_ImageData_Impl* image_data, |
return; |
} |
- cricket::CapturedFrame frame; |
- frame.elapsed_time = 0; |
- frame.time_stamp = time_stamp_ns; |
- frame.pixel_height = 1; |
- frame.pixel_width = 1; |
- frame.width = bitmap->width(); |
- frame.height = bitmap->height(); |
- if (image_data->format() == PP_IMAGEDATAFORMAT_BGRA_PREMUL) { |
- frame.fourcc = cricket::FOURCC_BGRA; |
- } else { |
- LOG(ERROR) << "PpFrameWriter::PutFrame - Got RGBA which is not supported."; |
- return; |
+ const gfx::Size frame_size(bitmap->width(), bitmap->height()); |
+ |
+ if (!first_frame_received_) { |
+ first_frame_received_ = true; |
+ format_ = media::VideoCaptureFormat( |
+ frame_size, |
+ MediaStreamVideoSource::kDefaultFrameRate, |
+ media::PIXEL_FORMAT_I420); |
+ if (state() == MediaStreamVideoSource::RETRIEVING_CAPABILITIES) { |
+ media::VideoCaptureFormats formats; |
+ formats.push_back(format_); |
+ OnSupportedFormats(formats); |
+ } |
} |
- frame.data_size = bitmap->getSize(); |
- frame.data = bitmap->getPixels(); |
- // This signals to libJingle that a new VideoFrame is available. |
- // libJingle have no assumptions on what thread this signal come from. |
- SignalFrameCaptured(this, &frame); |
+ if (state() != MediaStreamVideoSource::STARTED) |
+ return; |
+ |
+ const base::TimeDelta timestamp = base::TimeDelta::FromMilliseconds( |
+ time_stamp_ns / talk_base::kNumNanosecsPerMillisec); |
+ |
+ scoped_refptr<media::VideoFrame> new_frame = |
+ frame_pool_.CreateFrame(media::VideoFrame::I420, frame_size, |
+ gfx::Rect(frame_size), frame_size, timestamp); |
+ |
+ libyuv::BGRAToI420(reinterpret_cast<uint8*>(bitmap->getPixels()), |
+ bitmap->rowBytes(), |
+ new_frame->data(media::VideoFrame::kYPlane), |
+ new_frame->stride(media::VideoFrame::kYPlane), |
+ new_frame->data(media::VideoFrame::kUPlane), |
+ new_frame->stride(media::VideoFrame::kUPlane), |
+ new_frame->data(media::VideoFrame::kVPlane), |
+ new_frame->stride(media::VideoFrame::kVPlane), |
+ frame_size.width(), frame_size.height()); |
+ |
+ DeliverVideoFrame(new_frame); |
} |
// PpFrameWriterProxy is a helper class to make sure the user won't use |
-// PpFrameWriter after it is released (IOW its owner - WebMediaStreamTrack - |
+// PpFrameWriter after it is released (IOW its owner - WebMediaStreamSource - |
// is released). |
class PpFrameWriterProxy : public FrameWriterInterface { |
public: |
- PpFrameWriterProxy(VideoTrackInterface* track, |
- PpFrameWriter* writer) |
- : track_(track), |
- writer_(writer) { |
+ explicit PpFrameWriterProxy(const base::WeakPtr<PpFrameWriter>& writer) |
+ : writer_(writer) { |
DCHECK(writer_ != NULL); |
} |
@@ -156,8 +134,7 @@ class PpFrameWriterProxy : public FrameWriterInterface { |
} |
private: |
- scoped_refptr<VideoTrackInterface> track_; |
- PpFrameWriter* writer_; |
+ base::WeakPtr<PpFrameWriter> writer_; |
DISALLOW_COPY_AND_ASSIGN(PpFrameWriterProxy); |
}; |
@@ -167,6 +144,7 @@ bool VideoDestinationHandler::Open( |
MediaStreamRegistryInterface* registry, |
const std::string& url, |
FrameWriterInterface** frame_writer) { |
+ DVLOG(3) << "VideoDestinationHandler::Open"; |
if (!factory) { |
factory = RenderThreadImpl::current()->GetMediaStreamDependencyFactory(); |
DCHECK(factory != NULL); |
@@ -178,32 +156,38 @@ bool VideoDestinationHandler::Open( |
stream = |
blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url)); |
} |
- if (stream.isNull() || !stream.extraData()) { |
+ if (stream.isNull()) { |
LOG(ERROR) << "VideoDestinationHandler::Open - invalid url: " << url; |
return false; |
} |
// Create a new native video track and add it to |stream|. |
std::string track_id; |
- // According to spec, a media stream track's id should be globally unique. |
- // There's no easy way to strictly achieve that. The id generated with this |
- // method should be unique for most of the cases but theoretically it's |
- // possible we can get an id that's duplicated with the existing tracks. |
+ // According to spec, a media stream source's id should be unique per |
+ // application. There's no easy way to strictly achieve that. The id |
+ // generated with this method should be unique for most of the cases but |
+ // theoretically it's possible we can get an id that's duplicated with the |
+ // existing sources. |
base::Base64Encode(base::RandBytesAsString(64), &track_id); |
- PpFrameWriter* writer = new PpFrameWriter(); |
- if (!factory->AddNativeVideoMediaTrack(track_id, &stream, writer)) { |
- delete writer; |
- return false; |
- } |
+ PpFrameWriter* writer = new PpFrameWriter(factory); |
+ |
+ // Create a new webkit video track. |
+ blink::WebMediaStreamSource webkit_source; |
+ blink::WebMediaStreamSource::Type type = |
+ blink::WebMediaStreamSource::TypeVideo; |
+ blink::WebString webkit_track_id = base::UTF8ToUTF16(track_id); |
+ webkit_source.initialize(webkit_track_id, type, webkit_track_id); |
+ webkit_source.setExtraData(writer); |
+ |
+ blink::WebMediaConstraints constraints; |
+ constraints.initialize(); |
+ bool track_enabled = true; |
- // Gets a handler to the native video track, which owns the |writer|. |
- webrtc::MediaStreamInterface* native_stream = MediaStream::GetAdapter(stream); |
- DCHECK(native_stream); |
- VideoTrackVector video_tracks = native_stream->GetVideoTracks(); |
- // Currently one supports one video track per media stream. |
- DCHECK(video_tracks.size() == 1); |
+ stream.addTrack(MediaStreamVideoTrack::CreateVideoTrack( |
+ writer, constraints, MediaStreamVideoSource::ConstraintsCallback(), |
+ track_enabled, factory)); |
- *frame_writer = new PpFrameWriterProxy(video_tracks[0].get(), writer); |
+ *frame_writer = new PpFrameWriterProxy(writer->AsWeakPtr()); |
return true; |
} |