| Index: content/renderer/media/webrtc/video_destination_handler.cc
|
| diff --git a/content/renderer/media/webrtc/video_destination_handler.cc b/content/renderer/media/webrtc/video_destination_handler.cc
|
| index 88d0fa3baa36f9f176e014b3f8c3ee50bc8454bf..160537165d7912e4c514f6d49272f9dd60d0adde 100644
|
| --- a/content/renderer/media/webrtc/video_destination_handler.cc
|
| +++ b/content/renderer/media/webrtc/video_destination_handler.cc
|
| @@ -29,113 +29,115 @@ class PpFrameWriter::FrameWriterDelegate
|
| : public base::RefCountedThreadSafe<FrameWriterDelegate> {
|
| public:
|
| FrameWriterDelegate(
|
| - const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy,
|
| - const VideoCaptureDeliverFrameCB& new_frame_callback);
|
| + const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy);
|
| +
|
| + // Starts forwarding frames to |frame_callback| on the IO-thread that are
|
| + // delivered to this class by calling DeliverFrame on the main render thread.
|
| + void StartDeliver(const VideoCaptureDeliverFrameCB& frame_callback);
|
| + void StopDeliver();
|
| +
|
| + void DeliverFrame(const scoped_refptr<PPB_ImageData_Impl>& image_data,
|
| + int64 time_stamp_ns);
|
|
|
| - void DeliverFrame(const scoped_refptr<media::VideoFrame>& frame,
|
| - const media::VideoCaptureFormat& format);
|
| private:
|
| friend class base::RefCountedThreadSafe<FrameWriterDelegate>;
|
| virtual ~FrameWriterDelegate();
|
|
|
| - void DeliverFrameOnIO(const scoped_refptr<media::VideoFrame>& frame,
|
| - const media::VideoCaptureFormat& format);
|
| + void StartDeliverOnIO(const VideoCaptureDeliverFrameCB& frame_callback);
|
| + void StopDeliverOnIO();
|
| +
|
| + void DeliverFrameOnIO(uint8* data, int stride, int width, int height,
|
| + int64 time_stamp_ns);
|
| + void FrameDelivered(const scoped_refptr<PPB_ImageData_Impl>& image_data);
|
|
|
| scoped_refptr<base::MessageLoopProxy> io_message_loop_;
|
| +
|
| + // |frame_pool_| and |new_frame_callback_| are only used on the IO-thread.
|
| + media::VideoFramePool frame_pool_;
|
| VideoCaptureDeliverFrameCB new_frame_callback_;
|
| +
|
| + // Used to DCHECK that we are called on the main render thread.
|
| + base::ThreadChecker thread_checker_;
|
| };
|
|
|
| PpFrameWriter::FrameWriterDelegate::FrameWriterDelegate(
|
| - const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy,
|
| - const VideoCaptureDeliverFrameCB& new_frame_callback)
|
| - : io_message_loop_(io_message_loop_proxy),
|
| - new_frame_callback_(new_frame_callback) {
|
| + const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy)
|
| + : io_message_loop_(io_message_loop_proxy) {
|
| }
|
|
|
| PpFrameWriter::FrameWriterDelegate::~FrameWriterDelegate() {
|
| }
|
|
|
| -void PpFrameWriter::FrameWriterDelegate::DeliverFrame(
|
| - const scoped_refptr<media::VideoFrame>& frame,
|
| - const media::VideoCaptureFormat& format) {
|
| +void PpFrameWriter::FrameWriterDelegate::StartDeliver(
|
| + const VideoCaptureDeliverFrameCB& frame_callback) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| io_message_loop_->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&FrameWriterDelegate::DeliverFrameOnIO,
|
| - this, frame, format));
|
| -}
|
| -
|
| -void PpFrameWriter::FrameWriterDelegate::DeliverFrameOnIO(
|
| - const scoped_refptr<media::VideoFrame>& frame,
|
| - const media::VideoCaptureFormat& format) {
|
| - DCHECK(io_message_loop_->BelongsToCurrentThread());
|
| - // The local time when this frame is generated is unknown so give a null
|
| - // value to |estimated_capture_time|.
|
| - new_frame_callback_.Run(frame, format, base::TimeTicks());
|
| + base::Bind(&FrameWriterDelegate::StartDeliverOnIO, this,
|
| + frame_callback));
|
| }
|
|
|
| -PpFrameWriter::PpFrameWriter() {
|
| - DVLOG(3) << "PpFrameWriter ctor";
|
| -}
|
| -
|
| -PpFrameWriter::~PpFrameWriter() {
|
| - DVLOG(3) << "PpFrameWriter dtor";
|
| -}
|
| -
|
| -void PpFrameWriter::GetCurrentSupportedFormats(
|
| - int max_requested_width,
|
| - int max_requested_height,
|
| - double max_requested_frame_rate,
|
| - const VideoCaptureDeviceFormatsCB& callback) {
|
| - DCHECK(CalledOnValidThread());
|
| - DVLOG(3) << "PpFrameWriter::GetCurrentSupportedFormats()";
|
| - // Since the input is free to change the resolution at any point in time
|
| - // the supported formats are unknown.
|
| - media::VideoCaptureFormats formats;
|
| - callback.Run(formats);
|
| -}
|
| -
|
| -void PpFrameWriter::StartSourceImpl(
|
| - const media::VideoCaptureFormat& format,
|
| - const VideoCaptureDeliverFrameCB& frame_callback) {
|
| - DCHECK(CalledOnValidThread());
|
| - DCHECK(!delegate_.get());
|
| - DVLOG(3) << "PpFrameWriter::StartSourceImpl()";
|
| - delegate_ = new FrameWriterDelegate(io_message_loop(), frame_callback);
|
| - OnStartDone(MEDIA_DEVICE_OK);
|
| -}
|
| -
|
| -void PpFrameWriter::StopSourceImpl() {
|
| - DCHECK(CalledOnValidThread());
|
| +void PpFrameWriter::FrameWriterDelegate::StopDeliver() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + io_message_loop_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&FrameWriterDelegate::StopDeliverOnIO, this));
|
| }
|
|
|
| -void PpFrameWriter::PutFrame(PPB_ImageData_Impl* image_data,
|
| - int64 time_stamp_ns) {
|
| - DCHECK(CalledOnValidThread());
|
| - TRACE_EVENT0("video", "PpFrameWriter::PutFrame");
|
| - DVLOG(3) << "PpFrameWriter::PutFrame()";
|
| -
|
| - if (!image_data) {
|
| - LOG(ERROR) << "PpFrameWriter::PutFrame - Called with NULL image_data.";
|
| - return;
|
| - }
|
| - ImageDataAutoMapper mapper(image_data);
|
| - if (!mapper.is_valid()) {
|
| +void PpFrameWriter::FrameWriterDelegate::DeliverFrame(
|
| + const scoped_refptr<PPB_ImageData_Impl>& image_data,
|
| + int64 time_stamp_ns) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + TRACE_EVENT0("video", "PpFrameWriter::FrameWriterDelegate::DeliverFrame");
|
| + if (!image_data->Map()) {
|
| LOG(ERROR) << "PpFrameWriter::PutFrame - "
|
| << "The image could not be mapped and is unusable.";
|
| return;
|
| }
|
| +
|
| const SkBitmap* bitmap = image_data->GetMappedBitmap();
|
| if (!bitmap) {
|
| LOG(ERROR) << "PpFrameWriter::PutFrame - "
|
| << "The image_data's mapped bitmap is NULL.";
|
| return;
|
| }
|
| + io_message_loop_->PostTaskAndReply(
|
| + FROM_HERE,
|
| + base::Bind(&FrameWriterDelegate::DeliverFrameOnIO, this,
|
| + static_cast<uint8*>(bitmap->getPixels()),
|
| + bitmap->rowBytes(),
|
| + bitmap->width(),
|
| + bitmap->height(),
|
| + time_stamp_ns),
|
| + base::Bind(&FrameWriterDelegate::FrameDelivered, this,
|
| + image_data));
|
| +}
|
|
|
| - const gfx::Size frame_size(bitmap->width(), bitmap->height());
|
| +void PpFrameWriter::FrameWriterDelegate::FrameDelivered(
|
| + const scoped_refptr<PPB_ImageData_Impl>& image_data) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + image_data->Unmap();
|
| +}
|
| +
|
| +void PpFrameWriter::FrameWriterDelegate::StartDeliverOnIO(
|
| + const VideoCaptureDeliverFrameCB& frame_callback) {
|
| + DCHECK(io_message_loop_->BelongsToCurrentThread());
|
| + new_frame_callback_ = frame_callback;
|
| +}
|
| +void PpFrameWriter::FrameWriterDelegate::StopDeliverOnIO() {
|
| + DCHECK(io_message_loop_->BelongsToCurrentThread());
|
| + new_frame_callback_.Reset();
|
| +}
|
| +
|
| +void PpFrameWriter::FrameWriterDelegate::DeliverFrameOnIO(
|
| + uint8* data, int stride, int width, int height, int64 time_stamp_ns) {
|
| + DCHECK(io_message_loop_->BelongsToCurrentThread());
|
| + TRACE_EVENT0("video", "PpFrameWriter::FrameWriterDelegate::DeliverFrameOnIO");
|
|
|
| - if (state() != MediaStreamVideoSource::STARTED)
|
| + if (new_frame_callback_.is_null())
|
| return;
|
|
|
| + const gfx::Size frame_size(width, height);
|
| const base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds(
|
| time_stamp_ns / base::Time::kNanosecondsPerMicrosecond);
|
|
|
| @@ -151,8 +153,8 @@ void PpFrameWriter::PutFrame(PPB_ImageData_Impl* image_data,
|
| MediaStreamVideoSource::kUnknownFrameRate,
|
| media::PIXEL_FORMAT_YV12);
|
|
|
| - libyuv::BGRAToI420(reinterpret_cast<uint8*>(bitmap->getPixels()),
|
| - bitmap->rowBytes(),
|
| + libyuv::BGRAToI420(data,
|
| + stride,
|
| new_frame->data(media::VideoFrame::kYPlane),
|
| new_frame->stride(media::VideoFrame::kYPlane),
|
| new_frame->data(media::VideoFrame::kUPlane),
|
| @@ -161,36 +163,58 @@ void PpFrameWriter::PutFrame(PPB_ImageData_Impl* image_data,
|
| new_frame->stride(media::VideoFrame::kVPlane),
|
| frame_size.width(), frame_size.height());
|
|
|
| - delegate_->DeliverFrame(new_frame, format);
|
| + // The local time when this frame is generated is unknown so give a null
|
| + // value to |estimated_capture_time|.
|
| + new_frame_callback_.Run(new_frame, format, base::TimeTicks());
|
| }
|
|
|
| -// PpFrameWriterProxy is a helper class to make sure the user won't use
|
| -// PpFrameWriter after it is released (IOW its owner - WebMediaStreamSource -
|
| -// is released).
|
| -class PpFrameWriterProxy : public FrameWriterInterface {
|
| - public:
|
| - explicit PpFrameWriterProxy(const base::WeakPtr<PpFrameWriter>& writer)
|
| - : writer_(writer) {
|
| - DCHECK(writer_ != NULL);
|
| - }
|
| +PpFrameWriter::PpFrameWriter() {
|
| + DVLOG(3) << "PpFrameWriter ctor";
|
| + delegate_ = new FrameWriterDelegate(io_message_loop());
|
| +}
|
|
|
| - virtual ~PpFrameWriterProxy() {}
|
| +PpFrameWriter::~PpFrameWriter() {
|
| + DVLOG(3) << "PpFrameWriter dtor";
|
| +}
|
|
|
| - virtual void PutFrame(PPB_ImageData_Impl* image_data,
|
| - int64 time_stamp_ns) override {
|
| - writer_->PutFrame(image_data, time_stamp_ns);
|
| - }
|
| +VideoDestinationHandler::FrameWriterCallback
|
| +PpFrameWriter::GetFrameWriterCallback() {
|
| + DCHECK(CalledOnValidThread());
|
| + return base::Bind(&PpFrameWriter::FrameWriterDelegate::DeliverFrame,
|
| + delegate_);
|
| +}
|
|
|
| - private:
|
| - base::WeakPtr<PpFrameWriter> writer_;
|
| +void PpFrameWriter::GetCurrentSupportedFormats(
|
| + int max_requested_width,
|
| + int max_requested_height,
|
| + double max_requested_frame_rate,
|
| + const VideoCaptureDeviceFormatsCB& callback) {
|
| + DCHECK(CalledOnValidThread());
|
| + DVLOG(3) << "PpFrameWriter::GetCurrentSupportedFormats()";
|
| + // Since the input is free to change the resolution at any point in time
|
| + // the supported formats are unknown.
|
| + media::VideoCaptureFormats formats;
|
| + callback.Run(formats);
|
| +}
|
|
|
| - DISALLOW_COPY_AND_ASSIGN(PpFrameWriterProxy);
|
| -};
|
| +void PpFrameWriter::StartSourceImpl(
|
| + const media::VideoCaptureFormat& format,
|
| + const VideoCaptureDeliverFrameCB& frame_callback) {
|
| + DCHECK(CalledOnValidThread());
|
| + DVLOG(3) << "PpFrameWriter::StartSourceImpl()";
|
| + delegate_->StartDeliver(frame_callback);
|
| + OnStartDone(MEDIA_DEVICE_OK);
|
| +}
|
| +
|
| +void PpFrameWriter::StopSourceImpl() {
|
| + DCHECK(CalledOnValidThread());
|
| + delegate_->StopDeliver();
|
| +}
|
|
|
| bool VideoDestinationHandler::Open(
|
| MediaStreamRegistryInterface* registry,
|
| const std::string& url,
|
| - FrameWriterInterface** frame_writer) {
|
| + FrameWriterCallback* frame_writer) {
|
| DVLOG(3) << "VideoDestinationHandler::Open";
|
| blink::WebMediaStream stream;
|
| if (registry) {
|
| @@ -214,6 +238,7 @@ bool VideoDestinationHandler::Open(
|
| base::Base64Encode(base::RandBytesAsString(64), &track_id);
|
|
|
| PpFrameWriter* writer = new PpFrameWriter();
|
| + *frame_writer = writer->GetFrameWriterCallback();
|
|
|
| // Create a new webkit video track.
|
| blink::WebMediaStreamSource webkit_source;
|
| @@ -231,7 +256,6 @@ bool VideoDestinationHandler::Open(
|
| writer, constraints, MediaStreamVideoSource::ConstraintsCallback(),
|
| track_enabled));
|
|
|
| - *frame_writer = new PpFrameWriterProxy(writer->AsWeakPtr());
|
| return true;
|
| }
|
|
|
|
|