OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "content/renderer/media/webrtc/media_stream_remote_video_source.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/location.h" |
| 9 #include "content/renderer/media/native_handle_impl.h" |
| 10 #include "media/base/video_frame.h" |
| 11 #include "media/base/video_util.h" |
| 12 #include "third_party/libjingle/source/talk/media/base/videoframe.h" |
| 13 |
| 14 namespace content { |
| 15 |
| 16 MediaStreamRemoteVideoSource::MediaStreamRemoteVideoSource( |
| 17 webrtc::VideoTrackInterface* remote_track) |
| 18 : MediaStreamVideoSource(NULL), |
| 19 message_loop_proxy_(base::MessageLoopProxy::current()), |
| 20 remote_track_(remote_track), |
| 21 last_state_(remote_track_->state()), |
| 22 first_frame_received_(false) { |
| 23 remote_track_->AddRenderer(this); |
| 24 remote_track_->RegisterObserver(this); |
| 25 } |
| 26 |
| 27 MediaStreamRemoteVideoSource::~MediaStreamRemoteVideoSource() { |
| 28 StopSourceImpl(); |
| 29 } |
| 30 |
| 31 void MediaStreamRemoteVideoSource::GetCurrentSupportedFormats( |
| 32 int max_requested_width, |
| 33 int max_requested_height) { |
| 34 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
| 35 if (format_.IsValid()) { |
| 36 media::VideoCaptureFormats formats; |
| 37 formats.push_back(format_); |
| 38 OnSupportedFormats(formats); |
| 39 } |
| 40 } |
| 41 |
| 42 void MediaStreamRemoteVideoSource::StartSourceImpl( |
| 43 const media::VideoCaptureParams& params) { |
| 44 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
| 45 OnStartDone(true); |
| 46 } |
| 47 |
| 48 void MediaStreamRemoteVideoSource::StopSourceImpl() { |
| 49 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
| 50 remote_track_->RemoveRenderer(this); |
| 51 remote_track_->UnregisterObserver(this); |
| 52 } |
| 53 |
| 54 webrtc::VideoSourceInterface* MediaStreamRemoteVideoSource::GetAdapter() { |
| 55 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
| 56 return remote_track_->GetSource(); |
| 57 } |
| 58 |
| 59 void MediaStreamRemoteVideoSource::SetSize(int width, int height) { |
| 60 } |
| 61 |
| 62 void MediaStreamRemoteVideoSource::RenderFrame( |
| 63 const cricket::VideoFrame* frame) { |
| 64 base::TimeDelta timestamp = base::TimeDelta::FromMilliseconds( |
| 65 frame->GetTimeStamp() / talk_base::kNumNanosecsPerMillisec); |
| 66 |
| 67 scoped_refptr<media::VideoFrame> video_frame; |
| 68 if (frame->GetNativeHandle() != NULL) { |
| 69 NativeHandleImpl* handle = |
| 70 static_cast<NativeHandleImpl*>(frame->GetNativeHandle()); |
| 71 video_frame = static_cast<media::VideoFrame*>(handle->GetHandle()); |
| 72 video_frame->SetTimestamp(timestamp); |
| 73 } else { |
| 74 gfx::Size size(frame->GetWidth(), frame->GetHeight()); |
| 75 video_frame = frame_pool_.CreateFrame( |
| 76 media::VideoFrame::I420, size, gfx::Rect(size), size, timestamp); |
| 77 |
| 78 // Non-square pixels are unsupported. |
| 79 DCHECK_EQ(frame->GetPixelWidth(), 1u); |
| 80 DCHECK_EQ(frame->GetPixelHeight(), 1u); |
| 81 |
| 82 int y_rows = frame->GetHeight(); |
| 83 int uv_rows = frame->GetChromaHeight(); |
| 84 CopyYPlane( |
| 85 frame->GetYPlane(), frame->GetYPitch(), y_rows, video_frame.get()); |
| 86 CopyUPlane( |
| 87 frame->GetUPlane(), frame->GetUPitch(), uv_rows, video_frame.get()); |
| 88 CopyVPlane( |
| 89 frame->GetVPlane(), frame->GetVPitch(), uv_rows, video_frame.get()); |
| 90 } |
| 91 |
| 92 if (!first_frame_received_) { |
| 93 first_frame_received_ = true; |
| 94 media::VideoPixelFormat pixel_format = ( |
| 95 video_frame->format() == media::VideoFrame::I420) ? |
| 96 media::PIXEL_FORMAT_I420 : media::PIXEL_FORMAT_TEXTURE; |
| 97 media::VideoCaptureFormat format( |
| 98 gfx::Size(video_frame->natural_size().width(), |
| 99 video_frame->natural_size().height()), |
| 100 MediaStreamVideoSource::kDefaultFrameRate, |
| 101 pixel_format); |
| 102 message_loop_proxy_->PostTask( |
| 103 FROM_HERE, |
| 104 base::Bind(&MediaStreamRemoteVideoSource::FrameFormatOnMainThread, |
| 105 AsWeakPtr(), format)); |
| 106 } |
| 107 |
| 108 // TODO(perkj): Consider delivering the frame on whatever thread the frame is |
| 109 // delivered on once crbug/335327 is fixed. |
| 110 message_loop_proxy_->PostTask( |
| 111 FROM_HERE, |
| 112 base::Bind(&MediaStreamRemoteVideoSource::DoRenderFrameOnMainThread, |
| 113 AsWeakPtr(), video_frame)); |
| 114 } |
| 115 |
| 116 void MediaStreamRemoteVideoSource::OnChanged() { |
| 117 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
| 118 webrtc::MediaStreamTrackInterface::TrackState state = remote_track_->state(); |
| 119 if (state != last_state_) { |
| 120 last_state_ = state; |
| 121 switch (state) { |
| 122 case webrtc::MediaStreamTrackInterface::kInitializing: |
| 123 // Ignore the kInitializing state since there is no match in |
| 124 // WebMediaStreamSource::ReadyState. |
| 125 break; |
| 126 case webrtc::MediaStreamTrackInterface::kLive: |
| 127 SetReadyState(blink::WebMediaStreamSource::ReadyStateLive); |
| 128 break; |
| 129 case webrtc::MediaStreamTrackInterface::kEnded: |
| 130 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded); |
| 131 break; |
| 132 default: |
| 133 NOTREACHED(); |
| 134 break; |
| 135 } |
| 136 } |
| 137 } |
| 138 |
| 139 void MediaStreamRemoteVideoSource::FrameFormatOnMainThread( |
| 140 const media::VideoCaptureFormat& format) { |
| 141 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
| 142 format_ = format; |
| 143 if (state() == RETRIEVING_CAPABILITIES) { |
| 144 media::VideoCaptureFormats formats; |
| 145 formats.push_back(format); |
| 146 OnSupportedFormats(formats); |
| 147 } |
| 148 } |
| 149 |
| 150 void MediaStreamRemoteVideoSource::DoRenderFrameOnMainThread( |
| 151 scoped_refptr<media::VideoFrame> video_frame) { |
| 152 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
| 153 if (state() == STARTED) |
| 154 DeliverVideoFrame(video_frame); |
| 155 } |
| 156 |
| 157 } // namespace content |
OLD | NEW |