OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/pepper/pepper_media_stream_video_track_host.h" | 5 #include "content/renderer/pepper/pepper_media_stream_video_track_host.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "media/base/yuv_convert.h" | 8 #include "media/base/yuv_convert.h" |
9 #include "ppapi/c/pp_errors.h" | 9 #include "ppapi/c/pp_errors.h" |
10 #include "ppapi/c/ppb_video_frame.h" | 10 #include "ppapi/c/ppb_video_frame.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 case PP_VIDEOFRAME_FORMAT_I420: | 44 case PP_VIDEOFRAME_FORMAT_I420: |
45 return VideoFrame::I420; | 45 return VideoFrame::I420; |
46 default: | 46 default: |
47 DVLOG(1) << "Unsupported pixel format " << format; | 47 DVLOG(1) << "Unsupported pixel format " << format; |
48 return VideoFrame::UNKNOWN; | 48 return VideoFrame::UNKNOWN; |
49 } | 49 } |
50 } | 50 } |
51 | 51 |
52 // Compute size base on the size of frame received from MediaStreamVideoSink | 52 // Compute size base on the size of frame received from MediaStreamVideoSink |
53 // and size specified by plugin. | 53 // and size specified by plugin. |
54 gfx::Size GetTargetSize(const gfx::Size& source, | 54 gfx::Size GetTargetSize(const gfx::Size& source, const gfx::Size& plugin) { |
55 const gfx::Size& plugin) { | |
56 return gfx::Size(plugin.width() ? plugin.width() : source.width(), | 55 return gfx::Size(plugin.width() ? plugin.width() : source.width(), |
57 plugin.height() ? plugin.height() : source.height()); | 56 plugin.height() ? plugin.height() : source.height()); |
58 } | 57 } |
59 | 58 |
60 // Compute format base on the format of frame received from MediaStreamVideoSink | 59 // Compute format base on the format of frame received from MediaStreamVideoSink |
61 // and format specified by plugin. | 60 // and format specified by plugin. |
62 PP_VideoFrame_Format GetTargetFormat(PP_VideoFrame_Format source, | 61 PP_VideoFrame_Format GetTargetFormat(PP_VideoFrame_Format source, |
63 PP_VideoFrame_Format plugin) { | 62 PP_VideoFrame_Format plugin) { |
64 return plugin != PP_VIDEOFRAME_FORMAT_UNKNOWN ? plugin : source; | 63 return plugin != PP_VIDEOFRAME_FORMAT_UNKNOWN ? plugin : source; |
65 } | 64 } |
66 | 65 |
67 void ConvertFromMediaVideoFrame(const scoped_refptr<media::VideoFrame>& src, | 66 void ConvertFromMediaVideoFrame(const scoped_refptr<media::VideoFrame>& src, |
68 PP_VideoFrame_Format dst_format, | 67 PP_VideoFrame_Format dst_format, |
69 const gfx::Size& dst_size, | 68 const gfx::Size& dst_size, |
70 uint8_t* dst) { | 69 uint8_t* dst) { |
71 CHECK(src->format() == VideoFrame::YV12 || | 70 CHECK(src->format() == VideoFrame::YV12 || src->format() == VideoFrame::I420); |
72 src->format() == VideoFrame::I420); | |
73 if (dst_format == PP_VIDEOFRAME_FORMAT_BGRA) { | 71 if (dst_format == PP_VIDEOFRAME_FORMAT_BGRA) { |
74 if (src->coded_size() == dst_size) { | 72 if (src->coded_size() == dst_size) { |
75 libyuv::I420ToARGB(src->data(VideoFrame::kYPlane), | 73 libyuv::I420ToARGB(src->data(VideoFrame::kYPlane), |
76 src->stride(VideoFrame::kYPlane), | 74 src->stride(VideoFrame::kYPlane), |
77 src->data(VideoFrame::kUPlane), | 75 src->data(VideoFrame::kUPlane), |
78 src->stride(VideoFrame::kUPlane), | 76 src->stride(VideoFrame::kUPlane), |
79 src->data(VideoFrame::kVPlane), | 77 src->data(VideoFrame::kVPlane), |
80 src->stride(VideoFrame::kVPlane), | 78 src->stride(VideoFrame::kVPlane), |
81 dst, | 79 dst, |
82 dst_size.width() * 4, | 80 dst_size.width() * 4, |
(...skipping 11 matching lines...) Expand all Loading... |
94 src->stride(VideoFrame::kYPlane), | 92 src->stride(VideoFrame::kYPlane), |
95 src->stride(VideoFrame::kUPlane), | 93 src->stride(VideoFrame::kUPlane), |
96 dst_size.width() * 4, | 94 dst_size.width() * 4, |
97 media::YV12, | 95 media::YV12, |
98 media::ROTATE_0, | 96 media::ROTATE_0, |
99 media::FILTER_BILINEAR); | 97 media::FILTER_BILINEAR); |
100 } | 98 } |
101 } else if (dst_format == PP_VIDEOFRAME_FORMAT_YV12 || | 99 } else if (dst_format == PP_VIDEOFRAME_FORMAT_YV12 || |
102 dst_format == PP_VIDEOFRAME_FORMAT_I420) { | 100 dst_format == PP_VIDEOFRAME_FORMAT_I420) { |
103 static const size_t kPlanesOrder[][3] = { | 101 static const size_t kPlanesOrder[][3] = { |
104 { VideoFrame::kYPlane, VideoFrame::kVPlane, VideoFrame::kUPlane }, // YV12 | 102 {VideoFrame::kYPlane, VideoFrame::kVPlane, |
105 { VideoFrame::kYPlane, VideoFrame::kUPlane, VideoFrame::kVPlane }, // I420 | 103 VideoFrame::kUPlane}, // YV12 |
| 104 {VideoFrame::kYPlane, VideoFrame::kUPlane, |
| 105 VideoFrame::kVPlane}, // I420 |
106 }; | 106 }; |
107 const int plane_order = (dst_format == PP_VIDEOFRAME_FORMAT_YV12) ? 0 : 1; | 107 const int plane_order = (dst_format == PP_VIDEOFRAME_FORMAT_YV12) ? 0 : 1; |
108 int dst_width = dst_size.width(); | 108 int dst_width = dst_size.width(); |
109 int dst_height = dst_size.height(); | 109 int dst_height = dst_size.height(); |
110 libyuv::ScalePlane(src->data(kPlanesOrder[plane_order][0]), | 110 libyuv::ScalePlane(src->data(kPlanesOrder[plane_order][0]), |
111 src->stride(kPlanesOrder[plane_order][0]), | 111 src->stride(kPlanesOrder[plane_order][0]), |
112 src->coded_size().width(), | 112 src->coded_size().width(), |
113 src->coded_size().height(), | 113 src->coded_size().height(), |
114 dst, dst_width, dst_width, dst_height, | 114 dst, |
| 115 dst_width, |
| 116 dst_width, |
| 117 dst_height, |
115 kFilterMode); | 118 kFilterMode); |
116 dst += dst_width * dst_height; | 119 dst += dst_width * dst_height; |
117 const int src_halfwidth = (src->coded_size().width() + 1) >> 1; | 120 const int src_halfwidth = (src->coded_size().width() + 1) >> 1; |
118 const int src_halfheight = (src->coded_size().height() + 1) >> 1; | 121 const int src_halfheight = (src->coded_size().height() + 1) >> 1; |
119 const int dst_halfwidth = (dst_width + 1) >> 1; | 122 const int dst_halfwidth = (dst_width + 1) >> 1; |
120 const int dst_halfheight = (dst_height + 1) >> 1; | 123 const int dst_halfheight = (dst_height + 1) >> 1; |
121 libyuv::ScalePlane(src->data(kPlanesOrder[plane_order][1]), | 124 libyuv::ScalePlane(src->data(kPlanesOrder[plane_order][1]), |
122 src->stride(kPlanesOrder[plane_order][1]), | 125 src->stride(kPlanesOrder[plane_order][1]), |
123 src_halfwidth, src_halfheight, | 126 src_halfwidth, |
124 dst, dst_halfwidth, dst_halfwidth, dst_halfheight, | 127 src_halfheight, |
| 128 dst, |
| 129 dst_halfwidth, |
| 130 dst_halfwidth, |
| 131 dst_halfheight, |
125 kFilterMode); | 132 kFilterMode); |
126 dst += dst_halfwidth * dst_halfheight; | 133 dst += dst_halfwidth * dst_halfheight; |
127 libyuv::ScalePlane(src->data(kPlanesOrder[plane_order][2]), | 134 libyuv::ScalePlane(src->data(kPlanesOrder[plane_order][2]), |
128 src->stride(kPlanesOrder[plane_order][2]), | 135 src->stride(kPlanesOrder[plane_order][2]), |
129 src_halfwidth, src_halfheight, | 136 src_halfwidth, |
130 dst, dst_halfwidth, dst_halfwidth, dst_halfheight, | 137 src_halfheight, |
| 138 dst, |
| 139 dst_halfwidth, |
| 140 dst_halfwidth, |
| 141 dst_halfheight, |
131 kFilterMode); | 142 kFilterMode); |
132 } else { | 143 } else { |
133 NOTREACHED(); | 144 NOTREACHED(); |
134 } | 145 } |
135 } | 146 } |
136 | 147 |
137 } // namespace | 148 } // namespace |
138 | 149 |
139 namespace content { | 150 namespace content { |
140 | 151 |
(...skipping 14 matching lines...) Expand all Loading... |
155 | 166 |
156 PepperMediaStreamVideoTrackHost::~PepperMediaStreamVideoTrackHost() { | 167 PepperMediaStreamVideoTrackHost::~PepperMediaStreamVideoTrackHost() { |
157 OnClose(); | 168 OnClose(); |
158 } | 169 } |
159 | 170 |
160 void PepperMediaStreamVideoTrackHost::InitBuffers() { | 171 void PepperMediaStreamVideoTrackHost::InitBuffers() { |
161 gfx::Size size = GetTargetSize(source_frame_size_, plugin_frame_size_); | 172 gfx::Size size = GetTargetSize(source_frame_size_, plugin_frame_size_); |
162 DCHECK(!size.IsEmpty()); | 173 DCHECK(!size.IsEmpty()); |
163 | 174 |
164 PP_VideoFrame_Format format = | 175 PP_VideoFrame_Format format = |
165 GetTargetFormat(source_frame_format_, plugin_frame_format_); | 176 GetTargetFormat(source_frame_format_, plugin_frame_format_); |
166 DCHECK_NE(format, PP_VIDEOFRAME_FORMAT_UNKNOWN); | 177 DCHECK_NE(format, PP_VIDEOFRAME_FORMAT_UNKNOWN); |
167 | 178 |
168 if (format == PP_VIDEOFRAME_FORMAT_BGRA) { | 179 if (format == PP_VIDEOFRAME_FORMAT_BGRA) { |
169 frame_data_size_ = size.width() * size.height() * 4; | 180 frame_data_size_ = size.width() * size.height() * 4; |
170 } else { | 181 } else { |
171 frame_data_size_ = VideoFrame::AllocationSize(FromPpapiFormat(format), | 182 frame_data_size_ = |
172 size); | 183 VideoFrame::AllocationSize(FromPpapiFormat(format), size); |
173 } | 184 } |
174 | 185 |
175 DCHECK_GT(frame_data_size_, 0U); | 186 DCHECK_GT(frame_data_size_, 0U); |
176 int32_t buffer_size = | 187 int32_t buffer_size = |
177 sizeof(ppapi::MediaStreamBuffer::Video) + frame_data_size_; | 188 sizeof(ppapi::MediaStreamBuffer::Video) + frame_data_size_; |
178 bool result = PepperMediaStreamTrackHostBase::InitBuffers(number_of_buffers_, | 189 bool result = PepperMediaStreamTrackHostBase::InitBuffers(number_of_buffers_, |
179 buffer_size); | 190 buffer_size); |
180 CHECK(result); | 191 CHECK(result); |
181 } | 192 } |
182 | 193 |
(...skipping 22 matching lines...) Expand all Loading... |
205 // Drop frames if the underlying buffer is full. | 216 // Drop frames if the underlying buffer is full. |
206 if (index < 0) { | 217 if (index < 0) { |
207 DVLOG(1) << "A frame is dropped."; | 218 DVLOG(1) << "A frame is dropped."; |
208 return; | 219 return; |
209 } | 220 } |
210 | 221 |
211 CHECK(frame->coded_size() == source_frame_size_) << "Frame size is changed"; | 222 CHECK(frame->coded_size() == source_frame_size_) << "Frame size is changed"; |
212 CHECK_EQ(ppformat, source_frame_format_) << "Frame format is changed."; | 223 CHECK_EQ(ppformat, source_frame_format_) << "Frame format is changed."; |
213 | 224 |
214 gfx::Size size = GetTargetSize(source_frame_size_, plugin_frame_size_); | 225 gfx::Size size = GetTargetSize(source_frame_size_, plugin_frame_size_); |
215 PP_VideoFrame_Format format = GetTargetFormat(source_frame_format_, | 226 PP_VideoFrame_Format format = |
216 plugin_frame_format_); | 227 GetTargetFormat(source_frame_format_, plugin_frame_format_); |
217 ppapi::MediaStreamBuffer::Video* buffer = | 228 ppapi::MediaStreamBuffer::Video* buffer = |
218 &(buffer_manager()->GetBufferPointer(index)->video); | 229 &(buffer_manager()->GetBufferPointer(index)->video); |
219 buffer->header.size = buffer_manager()->buffer_size(); | 230 buffer->header.size = buffer_manager()->buffer_size(); |
220 buffer->header.type = ppapi::MediaStreamBuffer::TYPE_VIDEO; | 231 buffer->header.type = ppapi::MediaStreamBuffer::TYPE_VIDEO; |
221 buffer->timestamp = frame->timestamp().InSecondsF(); | 232 buffer->timestamp = frame->timestamp().InSecondsF(); |
222 buffer->format = format; | 233 buffer->format = format; |
223 buffer->size.width = size.width(); | 234 buffer->size.width = size.width(); |
224 buffer->size.height = size.height(); | 235 buffer->size.height = size.height(); |
225 buffer->data_size = frame_data_size_; | 236 buffer->data_size = frame_data_size_; |
226 ConvertFromMediaVideoFrame(frame, format, size, buffer->data); | 237 ConvertFromMediaVideoFrame(frame, format, size, buffer->data); |
227 SendEnqueueBufferMessageToPlugin(index); | 238 SendEnqueueBufferMessageToPlugin(index); |
228 } | 239 } |
229 | 240 |
230 void PepperMediaStreamVideoTrackHost::DidConnectPendingHostToResource() { | 241 void PepperMediaStreamVideoTrackHost::DidConnectPendingHostToResource() { |
231 if (!connected_) { | 242 if (!connected_) { |
232 MediaStreamVideoSink::AddToVideoTrack(this, track_); | 243 MediaStreamVideoSink::AddToVideoTrack(this, track_); |
233 connected_ = true; | 244 connected_ = true; |
234 } | 245 } |
235 } | 246 } |
236 | 247 |
237 int32_t PepperMediaStreamVideoTrackHost::OnResourceMessageReceived( | 248 int32_t PepperMediaStreamVideoTrackHost::OnResourceMessageReceived( |
238 const IPC::Message& msg, | 249 const IPC::Message& msg, |
239 HostMessageContext* context) { | 250 HostMessageContext* context) { |
240 IPC_BEGIN_MESSAGE_MAP(PepperMediaStreamVideoTrackHost, msg) | 251 IPC_BEGIN_MESSAGE_MAP(PepperMediaStreamVideoTrackHost, msg) |
241 PPAPI_DISPATCH_HOST_RESOURCE_CALL( | 252 PPAPI_DISPATCH_HOST_RESOURCE_CALL( |
242 PpapiHostMsg_MediaStreamVideoTrack_Configure, | 253 PpapiHostMsg_MediaStreamVideoTrack_Configure, OnHostMsgConfigure) |
243 OnHostMsgConfigure) | |
244 IPC_END_MESSAGE_MAP() | 254 IPC_END_MESSAGE_MAP() |
245 return PepperMediaStreamTrackHostBase::OnResourceMessageReceived(msg, | 255 return PepperMediaStreamTrackHostBase::OnResourceMessageReceived(msg, |
246 context); | 256 context); |
247 } | 257 } |
248 | 258 |
249 int32_t PepperMediaStreamVideoTrackHost::OnHostMsgConfigure( | 259 int32_t PepperMediaStreamVideoTrackHost::OnHostMsgConfigure( |
250 HostMessageContext* context, | 260 HostMessageContext* context, |
251 const MediaStreamVideoTrackShared::Attributes& attributes) { | 261 const MediaStreamVideoTrackShared::Attributes& attributes) { |
252 CHECK(MediaStreamVideoTrackShared::VerifyAttributes(attributes)); | 262 CHECK(MediaStreamVideoTrackShared::VerifyAttributes(attributes)); |
253 | 263 |
254 bool changed = false; | 264 bool changed = false; |
255 gfx::Size new_size(attributes.width, attributes.height); | 265 gfx::Size new_size(attributes.width, attributes.height); |
256 if (GetTargetSize(source_frame_size_, plugin_frame_size_) != | 266 if (GetTargetSize(source_frame_size_, plugin_frame_size_) != |
257 GetTargetSize(source_frame_size_, new_size)) { | 267 GetTargetSize(source_frame_size_, new_size)) { |
258 changed = true; | 268 changed = true; |
259 } | 269 } |
260 plugin_frame_size_ = new_size; | 270 plugin_frame_size_ = new_size; |
261 | 271 |
262 int32_t buffers = attributes.buffers ? | 272 int32_t buffers = attributes.buffers |
263 std::min(kMaxNumberOfBuffers, attributes.buffers) : | 273 ? std::min(kMaxNumberOfBuffers, attributes.buffers) |
264 kDefaultNumberOfBuffers; | 274 : kDefaultNumberOfBuffers; |
265 if (buffers != number_of_buffers_) | 275 if (buffers != number_of_buffers_) |
266 changed = true; | 276 changed = true; |
267 number_of_buffers_ = buffers; | 277 number_of_buffers_ = buffers; |
268 | 278 |
269 if (GetTargetFormat(source_frame_format_, plugin_frame_format_) != | 279 if (GetTargetFormat(source_frame_format_, plugin_frame_format_) != |
270 GetTargetFormat(source_frame_format_, attributes.format)) { | 280 GetTargetFormat(source_frame_format_, attributes.format)) { |
271 changed = true; | 281 changed = true; |
272 } | 282 } |
273 plugin_frame_format_ = attributes.format; | 283 plugin_frame_format_ = attributes.format; |
274 | 284 |
275 // If the first frame has been received, we will re-initialize buffers with | 285 // If the first frame has been received, we will re-initialize buffers with |
276 // new settings. Otherwise, we will initialize buffer when we receive | 286 // new settings. Otherwise, we will initialize buffer when we receive |
277 // the first frame, because plugin can only provide part of attributes | 287 // the first frame, because plugin can only provide part of attributes |
278 // which are not enough to initialize buffers. | 288 // which are not enough to initialize buffers. |
279 if (changed && !source_frame_size_.IsEmpty()) | 289 if (changed && !source_frame_size_.IsEmpty()) |
280 InitBuffers(); | 290 InitBuffers(); |
281 | 291 |
282 context->reply_msg = PpapiPluginMsg_MediaStreamVideoTrack_ConfigureReply(); | 292 context->reply_msg = PpapiPluginMsg_MediaStreamVideoTrack_ConfigureReply(); |
283 return PP_OK; | 293 return PP_OK; |
284 } | 294 } |
285 | 295 |
286 } // namespace content | 296 } // namespace content |
OLD | NEW |