OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "media/base/video_frame.h" | 5 #include "media/base/video_frame.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 new_coded_size.set_height((new_coded_size.height() + 1) / 2 * 2); | 43 new_coded_size.set_height((new_coded_size.height() + 1) / 2 * 2); |
44 // Fallthrough. | 44 // Fallthrough. |
45 case VideoFrame::YV16: | 45 case VideoFrame::YV16: |
46 new_coded_size.set_width((new_coded_size.width() + 1) / 2 * 2); | 46 new_coded_size.set_width((new_coded_size.width() + 1) / 2 * 2); |
47 break; | 47 break; |
48 default: | 48 default: |
49 LOG(FATAL) << "Only YUV formats supported: " << format; | 49 LOG(FATAL) << "Only YUV formats supported: " << format; |
50 return NULL; | 50 return NULL; |
51 } | 51 } |
52 DCHECK(IsValidConfig(format, new_coded_size, visible_rect, natural_size)); | 52 DCHECK(IsValidConfig(format, new_coded_size, visible_rect, natural_size)); |
53 scoped_refptr<VideoFrame> frame(new VideoFrame( | 53 scoped_refptr<VideoFrame> frame( |
54 format, new_coded_size, visible_rect, natural_size, timestamp, false)); | 54 new VideoFrame(format, |
| 55 new_coded_size, |
| 56 visible_rect, |
| 57 natural_size, |
| 58 scoped_ptr<gpu::MailboxHolder>(), |
| 59 timestamp, |
| 60 false)); |
55 frame->AllocateYUV(); | 61 frame->AllocateYUV(); |
56 return frame; | 62 return frame; |
57 } | 63 } |
58 | 64 |
59 // static | 65 // static |
60 std::string VideoFrame::FormatToString(VideoFrame::Format format) { | 66 std::string VideoFrame::FormatToString(VideoFrame::Format format) { |
61 switch (format) { | 67 switch (format) { |
62 case VideoFrame::UNKNOWN: | 68 case VideoFrame::UNKNOWN: |
63 return "UNKNOWN"; | 69 return "UNKNOWN"; |
64 case VideoFrame::YV12: | 70 case VideoFrame::YV12: |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 const ReleaseMailboxCB& mailbox_holder_release_cb, | 144 const ReleaseMailboxCB& mailbox_holder_release_cb, |
139 const gfx::Size& coded_size, | 145 const gfx::Size& coded_size, |
140 const gfx::Rect& visible_rect, | 146 const gfx::Rect& visible_rect, |
141 const gfx::Size& natural_size, | 147 const gfx::Size& natural_size, |
142 base::TimeDelta timestamp, | 148 base::TimeDelta timestamp, |
143 const ReadPixelsCB& read_pixels_cb) { | 149 const ReadPixelsCB& read_pixels_cb) { |
144 scoped_refptr<VideoFrame> frame(new VideoFrame(NATIVE_TEXTURE, | 150 scoped_refptr<VideoFrame> frame(new VideoFrame(NATIVE_TEXTURE, |
145 coded_size, | 151 coded_size, |
146 visible_rect, | 152 visible_rect, |
147 natural_size, | 153 natural_size, |
| 154 mailbox_holder.Pass(), |
148 timestamp, | 155 timestamp, |
149 false)); | 156 false)); |
150 frame->mailbox_holder_ = mailbox_holder.Pass(); | |
151 frame->mailbox_holder_release_cb_ = mailbox_holder_release_cb; | 157 frame->mailbox_holder_release_cb_ = mailbox_holder_release_cb; |
152 frame->read_pixels_cb_ = read_pixels_cb; | 158 frame->read_pixels_cb_ = read_pixels_cb; |
153 | 159 |
154 return frame; | 160 return frame; |
155 } | 161 } |
156 | 162 |
157 void VideoFrame::ReadPixelsFromNativeTexture(const SkBitmap& pixels) { | 163 void VideoFrame::ReadPixelsFromNativeTexture(const SkBitmap& pixels) { |
158 DCHECK_EQ(format_, NATIVE_TEXTURE); | 164 DCHECK_EQ(format_, NATIVE_TEXTURE); |
159 if (!read_pixels_cb_.is_null()) | 165 if (!read_pixels_cb_.is_null()) |
160 read_pixels_cb_.Run(pixels); | 166 read_pixels_cb_.Run(pixels); |
(...skipping 10 matching lines...) Expand all Loading... |
171 base::SharedMemoryHandle handle, | 177 base::SharedMemoryHandle handle, |
172 base::TimeDelta timestamp, | 178 base::TimeDelta timestamp, |
173 const base::Closure& no_longer_needed_cb) { | 179 const base::Closure& no_longer_needed_cb) { |
174 if (!IsValidConfig(format, coded_size, visible_rect, natural_size)) | 180 if (!IsValidConfig(format, coded_size, visible_rect, natural_size)) |
175 return NULL; | 181 return NULL; |
176 if (data_size < AllocationSize(format, coded_size)) | 182 if (data_size < AllocationSize(format, coded_size)) |
177 return NULL; | 183 return NULL; |
178 | 184 |
179 switch (format) { | 185 switch (format) { |
180 case I420: { | 186 case I420: { |
181 scoped_refptr<VideoFrame> frame(new VideoFrame( | 187 scoped_refptr<VideoFrame> frame( |
182 format, coded_size, visible_rect, natural_size, timestamp, false)); | 188 new VideoFrame(format, |
| 189 coded_size, |
| 190 visible_rect, |
| 191 natural_size, |
| 192 scoped_ptr<gpu::MailboxHolder>(), |
| 193 timestamp, |
| 194 false)); |
183 frame->shared_memory_handle_ = handle; | 195 frame->shared_memory_handle_ = handle; |
184 frame->strides_[kYPlane] = coded_size.width(); | 196 frame->strides_[kYPlane] = coded_size.width(); |
185 frame->strides_[kUPlane] = coded_size.width() / 2; | 197 frame->strides_[kUPlane] = coded_size.width() / 2; |
186 frame->strides_[kVPlane] = coded_size.width() / 2; | 198 frame->strides_[kVPlane] = coded_size.width() / 2; |
187 frame->data_[kYPlane] = data; | 199 frame->data_[kYPlane] = data; |
188 frame->data_[kUPlane] = data + coded_size.GetArea(); | 200 frame->data_[kUPlane] = data + coded_size.GetArea(); |
189 frame->data_[kVPlane] = data + (coded_size.GetArea() * 5 / 4); | 201 frame->data_[kVPlane] = data + (coded_size.GetArea() * 5 / 4); |
190 frame->no_longer_needed_cb_ = no_longer_needed_cb; | 202 frame->no_longer_needed_cb_ = no_longer_needed_cb; |
191 return frame; | 203 return frame; |
192 } | 204 } |
(...skipping 13 matching lines...) Expand all Loading... |
206 int32 u_stride, | 218 int32 u_stride, |
207 int32 v_stride, | 219 int32 v_stride, |
208 uint8* y_data, | 220 uint8* y_data, |
209 uint8* u_data, | 221 uint8* u_data, |
210 uint8* v_data, | 222 uint8* v_data, |
211 base::TimeDelta timestamp, | 223 base::TimeDelta timestamp, |
212 const base::Closure& no_longer_needed_cb) { | 224 const base::Closure& no_longer_needed_cb) { |
213 if (!IsValidConfig(format, coded_size, visible_rect, natural_size)) | 225 if (!IsValidConfig(format, coded_size, visible_rect, natural_size)) |
214 return NULL; | 226 return NULL; |
215 | 227 |
216 scoped_refptr<VideoFrame> frame(new VideoFrame( | 228 scoped_refptr<VideoFrame> frame( |
217 format, coded_size, visible_rect, natural_size, timestamp, false)); | 229 new VideoFrame(format, |
| 230 coded_size, |
| 231 visible_rect, |
| 232 natural_size, |
| 233 scoped_ptr<gpu::MailboxHolder>(), |
| 234 timestamp, |
| 235 false)); |
218 frame->strides_[kYPlane] = y_stride; | 236 frame->strides_[kYPlane] = y_stride; |
219 frame->strides_[kUPlane] = u_stride; | 237 frame->strides_[kUPlane] = u_stride; |
220 frame->strides_[kVPlane] = v_stride; | 238 frame->strides_[kVPlane] = v_stride; |
221 frame->data_[kYPlane] = y_data; | 239 frame->data_[kYPlane] = y_data; |
222 frame->data_[kUPlane] = u_data; | 240 frame->data_[kUPlane] = u_data; |
223 frame->data_[kVPlane] = v_data; | 241 frame->data_[kVPlane] = v_data; |
224 frame->no_longer_needed_cb_ = no_longer_needed_cb; | 242 frame->no_longer_needed_cb_ = no_longer_needed_cb; |
225 return frame; | 243 return frame; |
226 } | 244 } |
227 | 245 |
228 // static | 246 // static |
229 scoped_refptr<VideoFrame> VideoFrame::WrapVideoFrame( | 247 scoped_refptr<VideoFrame> VideoFrame::WrapVideoFrame( |
230 const scoped_refptr<VideoFrame>& frame, | 248 const scoped_refptr<VideoFrame>& frame, |
231 const gfx::Rect& visible_rect, | 249 const gfx::Rect& visible_rect, |
232 const gfx::Size& natural_size, | 250 const gfx::Size& natural_size, |
233 const base::Closure& no_longer_needed_cb) { | 251 const base::Closure& no_longer_needed_cb) { |
234 // NATIVE_TEXTURE frames need mailbox info propagated, and there's no support | 252 // NATIVE_TEXTURE frames need mailbox info propagated, and there's no support |
235 // for that here yet, see http://crbug/362521. | 253 // for that here yet, see http://crbug/362521. |
236 CHECK(frame->format() != NATIVE_TEXTURE); | 254 CHECK(frame->format() != NATIVE_TEXTURE); |
237 | 255 |
238 DCHECK(frame->visible_rect().Contains(visible_rect)); | 256 DCHECK(frame->visible_rect().Contains(visible_rect)); |
239 scoped_refptr<VideoFrame> wrapped_frame(new VideoFrame( | 257 scoped_refptr<VideoFrame> wrapped_frame( |
240 frame->format(), frame->coded_size(), visible_rect, natural_size, | 258 new VideoFrame(frame->format(), |
241 frame->timestamp(), frame->end_of_stream())); | 259 frame->coded_size(), |
| 260 visible_rect, |
| 261 natural_size, |
| 262 scoped_ptr<gpu::MailboxHolder>(), |
| 263 frame->timestamp(), |
| 264 frame->end_of_stream())); |
242 | 265 |
243 for (size_t i = 0; i < NumPlanes(frame->format()); ++i) { | 266 for (size_t i = 0; i < NumPlanes(frame->format()); ++i) { |
244 wrapped_frame->strides_[i] = frame->stride(i); | 267 wrapped_frame->strides_[i] = frame->stride(i); |
245 wrapped_frame->data_[i] = frame->data(i); | 268 wrapped_frame->data_[i] = frame->data(i); |
246 } | 269 } |
247 | 270 |
248 wrapped_frame->no_longer_needed_cb_ = no_longer_needed_cb; | 271 wrapped_frame->no_longer_needed_cb_ = no_longer_needed_cb; |
249 return wrapped_frame; | 272 return wrapped_frame; |
250 } | 273 } |
251 | 274 |
252 // static | 275 // static |
253 scoped_refptr<VideoFrame> VideoFrame::CreateEOSFrame() { | 276 scoped_refptr<VideoFrame> VideoFrame::CreateEOSFrame() { |
254 return new VideoFrame(VideoFrame::UNKNOWN, | 277 return new VideoFrame(VideoFrame::UNKNOWN, |
255 gfx::Size(), | 278 gfx::Size(), |
256 gfx::Rect(), | 279 gfx::Rect(), |
257 gfx::Size(), | 280 gfx::Size(), |
| 281 scoped_ptr<gpu::MailboxHolder>(), |
258 kNoTimestamp(), | 282 kNoTimestamp(), |
259 true); | 283 true); |
260 } | 284 } |
261 | 285 |
262 // static | 286 // static |
263 scoped_refptr<VideoFrame> VideoFrame::CreateColorFrame( | 287 scoped_refptr<VideoFrame> VideoFrame::CreateColorFrame( |
264 const gfx::Size& size, | 288 const gfx::Size& size, |
265 uint8 y, uint8 u, uint8 v, | 289 uint8 y, uint8 u, uint8 v, |
266 base::TimeDelta timestamp) { | 290 base::TimeDelta timestamp) { |
267 scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame( | 291 scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame( |
(...skipping 15 matching lines...) Expand all Loading... |
283 // maintained by the general compositor team. Please contact the following | 307 // maintained by the general compositor team. Please contact the following |
284 // people instead: | 308 // people instead: |
285 // | 309 // |
286 // wonsik@chromium.org | 310 // wonsik@chromium.org |
287 // ycheo@chromium.org | 311 // ycheo@chromium.org |
288 | 312 |
289 // static | 313 // static |
290 scoped_refptr<VideoFrame> VideoFrame::CreateHoleFrame( | 314 scoped_refptr<VideoFrame> VideoFrame::CreateHoleFrame( |
291 const gfx::Size& size) { | 315 const gfx::Size& size) { |
292 DCHECK(IsValidConfig(VideoFrame::HOLE, size, gfx::Rect(size), size)); | 316 DCHECK(IsValidConfig(VideoFrame::HOLE, size, gfx::Rect(size), size)); |
293 scoped_refptr<VideoFrame> frame(new VideoFrame( | 317 scoped_refptr<VideoFrame> frame( |
294 VideoFrame::HOLE, size, gfx::Rect(size), size, base::TimeDelta(), false)); | 318 new VideoFrame(VideoFrame::HOLE, |
| 319 size, |
| 320 gfx::Rect(size), |
| 321 size, |
| 322 scoped_ptr<gpu::MailboxHolder>(), |
| 323 base::TimeDelta(), |
| 324 false)); |
295 return frame; | 325 return frame; |
296 } | 326 } |
297 #endif // defined(VIDEO_HOLE) | 327 #endif // defined(VIDEO_HOLE) |
298 | 328 |
299 // static | 329 // static |
300 size_t VideoFrame::NumPlanes(Format format) { | 330 size_t VideoFrame::NumPlanes(Format format) { |
301 switch (format) { | 331 switch (format) { |
302 case VideoFrame::NATIVE_TEXTURE: | 332 case VideoFrame::NATIVE_TEXTURE: |
303 #if defined(VIDEO_HOLE) | 333 #if defined(VIDEO_HOLE) |
304 case VideoFrame::HOLE: | 334 case VideoFrame::HOLE: |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
446 if (format_ == YV12A) { | 476 if (format_ == YV12A) { |
447 data_[VideoFrame::kAPlane] = data + y_bytes + (2 * uv_bytes); | 477 data_[VideoFrame::kAPlane] = data + y_bytes + (2 * uv_bytes); |
448 strides_[VideoFrame::kAPlane] = y_stride; | 478 strides_[VideoFrame::kAPlane] = y_stride; |
449 } | 479 } |
450 } | 480 } |
451 | 481 |
452 VideoFrame::VideoFrame(VideoFrame::Format format, | 482 VideoFrame::VideoFrame(VideoFrame::Format format, |
453 const gfx::Size& coded_size, | 483 const gfx::Size& coded_size, |
454 const gfx::Rect& visible_rect, | 484 const gfx::Rect& visible_rect, |
455 const gfx::Size& natural_size, | 485 const gfx::Size& natural_size, |
| 486 scoped_ptr<gpu::MailboxHolder> mailbox_holder, |
456 base::TimeDelta timestamp, | 487 base::TimeDelta timestamp, |
457 bool end_of_stream) | 488 bool end_of_stream) |
458 : format_(format), | 489 : format_(format), |
459 coded_size_(coded_size), | 490 coded_size_(coded_size), |
460 visible_rect_(visible_rect), | 491 visible_rect_(visible_rect), |
461 natural_size_(natural_size), | 492 natural_size_(natural_size), |
| 493 mailbox_holder_(mailbox_holder.Pass()), |
462 shared_memory_handle_(base::SharedMemory::NULLHandle()), | 494 shared_memory_handle_(base::SharedMemory::NULLHandle()), |
463 timestamp_(timestamp), | 495 timestamp_(timestamp), |
464 end_of_stream_(end_of_stream) { | 496 end_of_stream_(end_of_stream) { |
465 DCHECK(IsValidConfig(format_, coded_size_, visible_rect_, natural_size_)); | 497 DCHECK(IsValidConfig(format_, coded_size_, visible_rect_, natural_size_)); |
466 | 498 |
467 memset(&strides_, 0, sizeof(strides_)); | 499 memset(&strides_, 0, sizeof(strides_)); |
468 memset(&data_, 0, sizeof(data_)); | 500 memset(&data_, 0, sizeof(data_)); |
469 } | 501 } |
470 | 502 |
471 VideoFrame::~VideoFrame() { | 503 VideoFrame::~VideoFrame() { |
472 if (!mailbox_holder_release_cb_.is_null()) { | 504 if (!mailbox_holder_release_cb_.is_null()) { |
473 base::ResetAndReturn(&mailbox_holder_release_cb_) | 505 std::vector<uint32> release_sync_points; |
474 .Run(mailbox_holder_.Pass()); | 506 { |
| 507 base::AutoLock locker(release_sync_point_lock_); |
| 508 release_sync_points_.swap(release_sync_points); |
| 509 } |
| 510 base::ResetAndReturn(&mailbox_holder_release_cb_).Run(release_sync_points); |
475 } | 511 } |
476 if (!no_longer_needed_cb_.is_null()) | 512 if (!no_longer_needed_cb_.is_null()) |
477 base::ResetAndReturn(&no_longer_needed_cb_).Run(); | 513 base::ResetAndReturn(&no_longer_needed_cb_).Run(); |
478 } | 514 } |
479 | 515 |
480 bool VideoFrame::IsValidPlane(size_t plane) const { | 516 bool VideoFrame::IsValidPlane(size_t plane) const { |
481 return (plane < NumPlanes(format_)); | 517 return (plane < NumPlanes(format_)); |
482 } | 518 } |
483 | 519 |
484 int VideoFrame::stride(size_t plane) const { | 520 int VideoFrame::stride(size_t plane) const { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 // Intentionally leave out non-production formats. | 572 // Intentionally leave out non-production formats. |
537 NOTREACHED() << "Unsupported video frame format: " << format_; | 573 NOTREACHED() << "Unsupported video frame format: " << format_; |
538 return 0; | 574 return 0; |
539 } | 575 } |
540 | 576 |
541 uint8* VideoFrame::data(size_t plane) const { | 577 uint8* VideoFrame::data(size_t plane) const { |
542 DCHECK(IsValidPlane(plane)); | 578 DCHECK(IsValidPlane(plane)); |
543 return data_[plane]; | 579 return data_[plane]; |
544 } | 580 } |
545 | 581 |
546 gpu::MailboxHolder* VideoFrame::mailbox_holder() const { | 582 const gpu::MailboxHolder* VideoFrame::mailbox_holder() const { |
547 DCHECK_EQ(format_, NATIVE_TEXTURE); | 583 DCHECK_EQ(format_, NATIVE_TEXTURE); |
548 return mailbox_holder_.get(); | 584 return mailbox_holder_.get(); |
549 } | 585 } |
550 | 586 |
551 base::SharedMemoryHandle VideoFrame::shared_memory_handle() const { | 587 base::SharedMemoryHandle VideoFrame::shared_memory_handle() const { |
552 return shared_memory_handle_; | 588 return shared_memory_handle_; |
553 } | 589 } |
554 | 590 |
| 591 void VideoFrame::AppendReleaseSyncPoint(uint32 sync_point) { |
| 592 DCHECK_EQ(format_, NATIVE_TEXTURE); |
| 593 if (!sync_point) |
| 594 return; |
| 595 base::AutoLock locker(release_sync_point_lock_); |
| 596 release_sync_points_.push_back(sync_point); |
| 597 } |
| 598 |
555 void VideoFrame::HashFrameForTesting(base::MD5Context* context) { | 599 void VideoFrame::HashFrameForTesting(base::MD5Context* context) { |
556 for (int plane = 0; plane < kMaxPlanes; ++plane) { | 600 for (int plane = 0; plane < kMaxPlanes; ++plane) { |
557 if (!IsValidPlane(plane)) | 601 if (!IsValidPlane(plane)) |
558 break; | 602 break; |
559 for (int row = 0; row < rows(plane); ++row) { | 603 for (int row = 0; row < rows(plane); ++row) { |
560 base::MD5Update(context, base::StringPiece( | 604 base::MD5Update(context, base::StringPiece( |
561 reinterpret_cast<char*>(data(plane) + stride(plane) * row), | 605 reinterpret_cast<char*>(data(plane) + stride(plane) * row), |
562 row_bytes(plane))); | 606 row_bytes(plane))); |
563 } | 607 } |
564 } | 608 } |
565 } | 609 } |
566 | 610 |
567 } // namespace media | 611 } // namespace media |
OLD | NEW |