| 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 |