Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(688)

Side by Side Diff: media/base/video_frame.cc

Issue 604743005: VideoCapture: Remove deep frame copy in the border to libJingle (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: scherkus@s comments Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/base/video_frame.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/aligned_memory.h" 12 #include "base/memory/aligned_memory.h"
13 #include "base/strings/string_piece.h" 13 #include "base/strings/string_piece.h"
14 #include "gpu/command_buffer/common/mailbox_holder.h" 14 #include "gpu/command_buffer/common/mailbox_holder.h"
15 #include "media/base/limits.h" 15 #include "media/base/limits.h"
16 #include "media/base/video_util.h" 16 #include "media/base/video_util.h"
17 #include "ui/gfx/point.h"
17 18
18 #if !defined(MEDIA_FOR_CAST_IOS) 19 #if !defined(MEDIA_FOR_CAST_IOS)
19 #include "third_party/skia/include/core/SkBitmap.h" 20 #include "third_party/skia/include/core/SkBitmap.h"
20 #endif 21 #endif
21 22
22 namespace media { 23 namespace media {
23 24
25 static bool IsPowerOfTwo(size_t x) {
26 return x != 0 && (x & (x - 1)) == 0;
27 }
28
24 static inline size_t RoundUp(size_t value, size_t alignment) { 29 static inline size_t RoundUp(size_t value, size_t alignment) {
25 // Check that |alignment| is a power of 2. 30 DCHECK(IsPowerOfTwo(alignment));
26 DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
27 return ((value + (alignment - 1)) & ~(alignment - 1)); 31 return ((value + (alignment - 1)) & ~(alignment - 1));
28 } 32 }
29 33
34 static inline size_t RoundDown(size_t value, size_t alignment) {
35 DCHECK(IsPowerOfTwo(alignment));
36 return value & ~(alignment - 1);
37 }
38
39 // Returns the pixel size per element for given |plane| and |format|. E.g. 2x2
40 // for the U-plane in I420.
41 static gfx::Size SampleSize(VideoFrame::Format format, size_t plane) {
42 DCHECK(VideoFrame::IsValidPlane(plane, format));
43
44 switch (plane) {
45 case VideoFrame::kYPlane:
46 case VideoFrame::kAPlane:
47 return gfx::Size(1, 1);
48
49 case VideoFrame::kUPlane: // and VideoFrame::kUVPlane:
50 case VideoFrame::kVPlane:
51 switch (format) {
52 case VideoFrame::YV24:
53 return gfx::Size(1, 1);
54
55 case VideoFrame::YV16:
56 return gfx::Size(2, 1);
57
58 case VideoFrame::YV12:
59 case VideoFrame::YV12J:
60 case VideoFrame::I420:
61 case VideoFrame::YV12A:
62 case VideoFrame::NV12:
63 return gfx::Size(2, 2);
64
65 case VideoFrame::UNKNOWN:
66 #if defined(VIDEO_HOLE)
67 case VideoFrame::HOLE:
68 #endif // defined(VIDEO_HOLE)
69 case VideoFrame::NATIVE_TEXTURE:
70 break;
71 }
72 }
73 NOTREACHED();
74 return gfx::Size();
75 }
76
77 // Return the alignment for the whole frame, calculated as the max of the
78 // alignment for each individual plane.
79 static gfx::Size CommonAlignment(VideoFrame::Format format) {
80 int max_sample_width = 0;
81 int max_sample_height = 0;
82 for (size_t plane = 0; plane < VideoFrame::NumPlanes(format); ++plane) {
83 const gfx::Size sample_size = SampleSize(format, plane);
84 max_sample_width = std::max(max_sample_width, sample_size.width());
85 max_sample_height = std::max(max_sample_height, sample_size.height());
86 }
87 return gfx::Size(max_sample_width, max_sample_height);
88 }
89
90 // Returns the number of bytes per element for given |plane| and |format|. E.g.
91 // 2 for the UV plane in NV12.
92 static int BytesPerElement(VideoFrame::Format format, size_t plane) {
93 DCHECK(VideoFrame::IsValidPlane(plane, format));
94 return (format == VideoFrame::NV12 && plane == VideoFrame::kUVPlane) ? 2 : 1;
95 }
96
30 // Rounds up |coded_size| if necessary for |format|. 97 // Rounds up |coded_size| if necessary for |format|.
31 static gfx::Size AdjustCodedSize(VideoFrame::Format format, 98 static gfx::Size AdjustCodedSize(VideoFrame::Format format,
32 const gfx::Size& coded_size) { 99 const gfx::Size& coded_size) {
33 gfx::Size new_coded_size(coded_size); 100 const gfx::Size alignment = CommonAlignment(format);
34 switch (format) { 101 return gfx::Size(RoundUp(coded_size.width(), alignment.width()),
35 case VideoFrame::YV12: 102 RoundUp(coded_size.height(), alignment.height()));
36 case VideoFrame::YV12A:
37 case VideoFrame::I420:
38 case VideoFrame::YV12J:
39 new_coded_size.set_height(RoundUp(new_coded_size.height(), 2));
40 // Fallthrough.
41 case VideoFrame::YV16:
42 new_coded_size.set_width(RoundUp(new_coded_size.width(), 2));
43 break;
44 default:
45 break;
46 }
47 return new_coded_size;
48 } 103 }
49 104
50 // static 105 // static
51 scoped_refptr<VideoFrame> VideoFrame::CreateFrame( 106 scoped_refptr<VideoFrame> VideoFrame::CreateFrame(
52 VideoFrame::Format format, 107 VideoFrame::Format format,
53 const gfx::Size& coded_size, 108 const gfx::Size& coded_size,
54 const gfx::Rect& visible_rect, 109 const gfx::Rect& visible_rect,
55 const gfx::Size& natural_size, 110 const gfx::Size& natural_size,
56 base::TimeDelta timestamp) { 111 base::TimeDelta timestamp) {
57 DCHECK(format != VideoFrame::UNKNOWN && 112 DCHECK(format != VideoFrame::UNKNOWN &&
58 format != VideoFrame::NV12 && 113 format != VideoFrame::NV12 &&
59 format != VideoFrame::NATIVE_TEXTURE); 114 format != VideoFrame::NATIVE_TEXTURE);
60 #if defined(VIDEO_HOLE) 115 #if defined(VIDEO_HOLE)
61 DCHECK(format != VideoFrame::HOLE); 116 DCHECK(format != VideoFrame::HOLE);
62 #endif // defined(VIDEO_HOLE) 117 #endif // defined(VIDEO_HOLE)
63 118
64 // Since we're creating a new YUV frame (and allocating memory for it 119 // Since we're creating a new YUV frame (and allocating memory for it
65 // ourselves), we can pad the requested |coded_size| if necessary if the 120 // ourselves), we can pad the requested |coded_size| if necessary if the
66 // request does not line up on sample boundaries. 121 // request does not line up on sample boundaries.
67 gfx::Size new_coded_size = AdjustCodedSize(format, coded_size); 122 const gfx::Size new_coded_size = AdjustCodedSize(format, coded_size);
68 DCHECK(IsValidConfig(format, new_coded_size, visible_rect, natural_size)); 123 DCHECK(IsValidConfig(format, new_coded_size, visible_rect, natural_size));
69 124
70 scoped_refptr<VideoFrame> frame( 125 scoped_refptr<VideoFrame> frame(
71 new VideoFrame(format, 126 new VideoFrame(format,
72 new_coded_size, 127 new_coded_size,
73 visible_rect, 128 visible_rect,
74 natural_size, 129 natural_size,
75 scoped_ptr<gpu::MailboxHolder>(), 130 scoped_ptr<gpu::MailboxHolder>(),
76 timestamp, 131 timestamp,
77 false)); 132 false));
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 natural_size.GetArea() > limits::kMaxCanvas || 179 natural_size.GetArea() > limits::kMaxCanvas ||
125 natural_size.width() > limits::kMaxDimension || 180 natural_size.width() > limits::kMaxDimension ||
126 natural_size.height() > limits::kMaxDimension) 181 natural_size.height() > limits::kMaxDimension)
127 return false; 182 return false;
128 183
129 // Check format-specific width/height requirements. 184 // Check format-specific width/height requirements.
130 switch (format) { 185 switch (format) {
131 case VideoFrame::UNKNOWN: 186 case VideoFrame::UNKNOWN:
132 return (coded_size.IsEmpty() && visible_rect.IsEmpty() && 187 return (coded_size.IsEmpty() && visible_rect.IsEmpty() &&
133 natural_size.IsEmpty()); 188 natural_size.IsEmpty());
189
190 // NATIVE_TEXTURE and HOLE have no software-allocated buffers and are
191 // allowed to skip the below check.
192 case VideoFrame::NATIVE_TEXTURE:
193 #if defined(VIDEO_HOLE)
194 case VideoFrame::HOLE:
195 #endif // defined(VIDEO_HOLE)
196 return true;
197
134 case VideoFrame::YV24: 198 case VideoFrame::YV24:
135 break;
136 case VideoFrame::YV12: 199 case VideoFrame::YV12:
137 case VideoFrame::YV12J: 200 case VideoFrame::YV12J:
138 case VideoFrame::I420: 201 case VideoFrame::I420:
139 case VideoFrame::YV12A: 202 case VideoFrame::YV12A:
140 case VideoFrame::NV12: 203 case VideoFrame::NV12:
141 // Subsampled YUV formats have width/height requirements.
142 if (static_cast<size_t>(coded_size.height()) <
143 RoundUp(visible_rect.bottom(), 2))
144 return false;
145 // Fallthrough.
146 case VideoFrame::YV16: 204 case VideoFrame::YV16:
147 if (static_cast<size_t>(coded_size.width()) < 205 // Check that software-allocated buffer formats are aligned correctly and
148 RoundUp(visible_rect.right(), 2)) 206 // not empty.
149 return false; 207 const gfx::Size alignment = CommonAlignment(format);
150 break; 208 return RoundUp(visible_rect.right(), alignment.width()) <=
151 case VideoFrame::NATIVE_TEXTURE: 209 static_cast<size_t>(coded_size.width()) &&
152 #if defined(VIDEO_HOLE) 210 RoundUp(visible_rect.bottom(), alignment.height()) <=
153 case VideoFrame::HOLE: 211 static_cast<size_t>(coded_size.height()) &&
154 #endif // defined(VIDEO_HOLE) 212 !coded_size.IsEmpty() && !visible_rect.IsEmpty() &&
155 // NATIVE_TEXTURE and HOLE have no software-allocated buffers and are 213 !natural_size.IsEmpty();
156 // allowed to skip the below check and be empty.
157 return true;
158 } 214 }
159 215
160 // Check that software-allocated buffer formats are not empty. 216 NOTREACHED();
161 return (!coded_size.IsEmpty() && !visible_rect.IsEmpty() && 217 return false;
162 !natural_size.IsEmpty());
163 } 218 }
164 219
165 // static 220 // static
166 scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture( 221 scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture(
167 scoped_ptr<gpu::MailboxHolder> mailbox_holder, 222 scoped_ptr<gpu::MailboxHolder> mailbox_holder,
168 const ReleaseMailboxCB& mailbox_holder_release_cb, 223 const ReleaseMailboxCB& mailbox_holder_release_cb,
169 const gfx::Size& coded_size, 224 const gfx::Size& coded_size,
170 const gfx::Rect& visible_rect, 225 const gfx::Rect& visible_rect,
171 const gfx::Size& natural_size, 226 const gfx::Size& natural_size,
172 base::TimeDelta timestamp, 227 base::TimeDelta timestamp,
(...skipping 23 matching lines...) Expand all
196 scoped_refptr<VideoFrame> VideoFrame::WrapExternalPackedMemory( 251 scoped_refptr<VideoFrame> VideoFrame::WrapExternalPackedMemory(
197 Format format, 252 Format format,
198 const gfx::Size& coded_size, 253 const gfx::Size& coded_size,
199 const gfx::Rect& visible_rect, 254 const gfx::Rect& visible_rect,
200 const gfx::Size& natural_size, 255 const gfx::Size& natural_size,
201 uint8* data, 256 uint8* data,
202 size_t data_size, 257 size_t data_size,
203 base::SharedMemoryHandle handle, 258 base::SharedMemoryHandle handle,
204 base::TimeDelta timestamp, 259 base::TimeDelta timestamp,
205 const base::Closure& no_longer_needed_cb) { 260 const base::Closure& no_longer_needed_cb) {
206 gfx::Size new_coded_size = AdjustCodedSize(format, coded_size); 261 const gfx::Size new_coded_size = AdjustCodedSize(format, coded_size);
207 262
208 if (!IsValidConfig(format, new_coded_size, visible_rect, natural_size)) 263 if (!IsValidConfig(format, new_coded_size, visible_rect, natural_size))
209 return NULL; 264 return NULL;
210 if (data_size < AllocationSize(format, new_coded_size)) 265 if (data_size < AllocationSize(format, new_coded_size))
211 return NULL; 266 return NULL;
212 267
213 switch (format) { 268 switch (format) {
214 case VideoFrame::I420: { 269 case VideoFrame::I420: {
215 scoped_refptr<VideoFrame> frame( 270 scoped_refptr<VideoFrame> frame(
216 new VideoFrame(format, 271 new VideoFrame(format,
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 #endif 339 #endif
285 340
286 #if defined(OS_MACOSX) 341 #if defined(OS_MACOSX)
287 // static 342 // static
288 scoped_refptr<VideoFrame> VideoFrame::WrapCVPixelBuffer( 343 scoped_refptr<VideoFrame> VideoFrame::WrapCVPixelBuffer(
289 CVPixelBufferRef cv_pixel_buffer, 344 CVPixelBufferRef cv_pixel_buffer,
290 base::TimeDelta timestamp) { 345 base::TimeDelta timestamp) {
291 DCHECK(cv_pixel_buffer); 346 DCHECK(cv_pixel_buffer);
292 DCHECK(CFGetTypeID(cv_pixel_buffer) == CVPixelBufferGetTypeID()); 347 DCHECK(CFGetTypeID(cv_pixel_buffer) == CVPixelBufferGetTypeID());
293 348
294 OSType cv_format = CVPixelBufferGetPixelFormatType(cv_pixel_buffer); 349 const OSType cv_format = CVPixelBufferGetPixelFormatType(cv_pixel_buffer);
295 Format format; 350 Format format;
296 // There are very few compatible CV pixel formats, so just check each. 351 // There are very few compatible CV pixel formats, so just check each.
297 if (cv_format == kCVPixelFormatType_420YpCbCr8Planar) { 352 if (cv_format == kCVPixelFormatType_420YpCbCr8Planar) {
298 format = Format::I420; 353 format = Format::I420;
299 } else if (cv_format == kCVPixelFormatType_444YpCbCr8) { 354 } else if (cv_format == kCVPixelFormatType_444YpCbCr8) {
300 format = Format::YV24; 355 format = Format::YV24;
301 } else if (cv_format == '420v') { 356 } else if (cv_format == '420v') {
302 // TODO(jfroy): Use kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange when the 357 // TODO(jfroy): Use kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange when the
303 // minimum OS X and iOS SDKs permits it. 358 // minimum OS X and iOS SDKs permits it.
304 format = Format::NV12; 359 format = Format::NV12;
305 } else { 360 } else {
306 DLOG(ERROR) << "CVPixelBuffer format not supported: " << cv_format; 361 DLOG(ERROR) << "CVPixelBuffer format not supported: " << cv_format;
307 return NULL; 362 return NULL;
308 } 363 }
309 364
310 gfx::Size coded_size(CVImageBufferGetEncodedSize(cv_pixel_buffer)); 365 const gfx::Size coded_size(CVImageBufferGetEncodedSize(cv_pixel_buffer));
311 gfx::Rect visible_rect(CVImageBufferGetCleanRect(cv_pixel_buffer)); 366 const gfx::Rect visible_rect(CVImageBufferGetCleanRect(cv_pixel_buffer));
312 gfx::Size natural_size(CVImageBufferGetDisplaySize(cv_pixel_buffer)); 367 const gfx::Size natural_size(CVImageBufferGetDisplaySize(cv_pixel_buffer));
313 368
314 if (!IsValidConfig(format, coded_size, visible_rect, natural_size)) 369 if (!IsValidConfig(format, coded_size, visible_rect, natural_size))
315 return NULL; 370 return NULL;
316 371
317 scoped_refptr<VideoFrame> frame( 372 scoped_refptr<VideoFrame> frame(
318 new VideoFrame(format, 373 new VideoFrame(format,
319 coded_size, 374 coded_size,
320 visible_rect, 375 visible_rect,
321 natural_size, 376 natural_size,
322 scoped_ptr<gpu::MailboxHolder>(), 377 scoped_ptr<gpu::MailboxHolder>(),
(...skipping 12 matching lines...) Expand all
335 const gfx::Rect& visible_rect, 390 const gfx::Rect& visible_rect,
336 const gfx::Size& natural_size, 391 const gfx::Size& natural_size,
337 int32 y_stride, 392 int32 y_stride,
338 int32 u_stride, 393 int32 u_stride,
339 int32 v_stride, 394 int32 v_stride,
340 uint8* y_data, 395 uint8* y_data,
341 uint8* u_data, 396 uint8* u_data,
342 uint8* v_data, 397 uint8* v_data,
343 base::TimeDelta timestamp, 398 base::TimeDelta timestamp,
344 const base::Closure& no_longer_needed_cb) { 399 const base::Closure& no_longer_needed_cb) {
345 gfx::Size new_coded_size = AdjustCodedSize(format, coded_size); 400 const gfx::Size new_coded_size = AdjustCodedSize(format, coded_size);
346 CHECK(IsValidConfig(format, new_coded_size, visible_rect, natural_size)); 401 CHECK(IsValidConfig(format, new_coded_size, visible_rect, natural_size));
347 402
348 scoped_refptr<VideoFrame> frame( 403 scoped_refptr<VideoFrame> frame(
349 new VideoFrame(format, 404 new VideoFrame(format,
350 new_coded_size, 405 new_coded_size,
351 visible_rect, 406 visible_rect,
352 natural_size, 407 natural_size,
353 scoped_ptr<gpu::MailboxHolder>(), 408 scoped_ptr<gpu::MailboxHolder>(),
354 timestamp, 409 timestamp,
355 false)); 410 false));
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 size_t total = 0; 545 size_t total = 0;
491 for (size_t i = 0; i < NumPlanes(format); ++i) 546 for (size_t i = 0; i < NumPlanes(format); ++i)
492 total += PlaneAllocationSize(format, i, coded_size); 547 total += PlaneAllocationSize(format, i, coded_size);
493 return total; 548 return total;
494 } 549 }
495 550
496 // static 551 // static
497 gfx::Size VideoFrame::PlaneSize(Format format, 552 gfx::Size VideoFrame::PlaneSize(Format format,
498 size_t plane, 553 size_t plane,
499 const gfx::Size& coded_size) { 554 const gfx::Size& coded_size) {
555 DCHECK(IsValidPlane(plane, format));
556
500 // Align to multiple-of-two size overall. This ensures that non-subsampled 557 // Align to multiple-of-two size overall. This ensures that non-subsampled
501 // planes can be addressed by pixel with the same scaling as the subsampled 558 // planes can be addressed by pixel with the same scaling as the subsampled
502 // planes. 559 // planes.
503 const int width = RoundUp(coded_size.width(), 2); 560 const int width = RoundUp(coded_size.width(), 2);
504 const int height = RoundUp(coded_size.height(), 2); 561 const int height = RoundUp(coded_size.height(), 2);
505 switch (format) { 562
506 case VideoFrame::YV24: 563 const gfx::Size subsample = SampleSize(format, plane);
507 switch (plane) { 564 DCHECK(width % subsample.width() == 0);
508 case VideoFrame::kYPlane: 565 DCHECK(height % subsample.height() == 0);
509 case VideoFrame::kUPlane: 566 return gfx::Size(BytesPerElement(format, plane) * width / subsample.width(),
510 case VideoFrame::kVPlane: 567 height / subsample.height());
511 return gfx::Size(width, height);
512 default:
513 break;
514 }
515 break;
516 case VideoFrame::YV12:
517 case VideoFrame::YV12J:
518 case VideoFrame::I420:
519 switch (plane) {
520 case VideoFrame::kYPlane:
521 return gfx::Size(width, height);
522 case VideoFrame::kUPlane:
523 case VideoFrame::kVPlane:
524 return gfx::Size(width / 2, height / 2);
525 default:
526 break;
527 }
528 break;
529 case VideoFrame::YV12A:
530 switch (plane) {
531 case VideoFrame::kYPlane:
532 case VideoFrame::kAPlane:
533 return gfx::Size(width, height);
534 case VideoFrame::kUPlane:
535 case VideoFrame::kVPlane:
536 return gfx::Size(width / 2, height / 2);
537 default:
538 break;
539 }
540 break;
541 case VideoFrame::YV16:
542 switch (plane) {
543 case VideoFrame::kYPlane:
544 return gfx::Size(width, height);
545 case VideoFrame::kUPlane:
546 case VideoFrame::kVPlane:
547 return gfx::Size(width / 2, height);
548 default:
549 break;
550 }
551 break;
552 case VideoFrame::NV12:
553 switch (plane) {
554 case VideoFrame::kYPlane:
555 return gfx::Size(width, height);
556 case VideoFrame::kUVPlane:
557 return gfx::Size(width, height / 2);
558 default:
559 break;
560 }
561 break;
562 case VideoFrame::UNKNOWN:
563 case VideoFrame::NATIVE_TEXTURE:
564 #if defined(VIDEO_HOLE)
565 case VideoFrame::HOLE:
566 #endif // defined(VIDEO_HOLE)
567 break;
568 }
569 NOTREACHED() << "Unsupported video frame format/plane: "
570 << format << "/" << plane;
571 return gfx::Size();
572 } 568 }
573 569
574 size_t VideoFrame::PlaneAllocationSize(Format format, 570 size_t VideoFrame::PlaneAllocationSize(Format format,
575 size_t plane, 571 size_t plane,
576 const gfx::Size& coded_size) { 572 const gfx::Size& coded_size) {
577 // VideoFrame formats are (so far) all YUV and 1 byte per sample. 573 // VideoFrame formats are (so far) all YUV and 1 byte per sample.
578 return PlaneSize(format, plane, coded_size).GetArea(); 574 return PlaneSize(format, plane, coded_size).GetArea();
579 } 575 }
580 576
581 // static 577 // static
582 int VideoFrame::PlaneHorizontalBitsPerPixel(Format format, size_t plane) { 578 int VideoFrame::PlaneHorizontalBitsPerPixel(Format format, size_t plane) {
583 switch (format) { 579 DCHECK(IsValidPlane(plane, format));
584 case VideoFrame::YV24: 580 const int bits_per_element = 8 * BytesPerElement(format, plane);
585 switch (plane) { 581 const int pixels_per_element = SampleSize(format, plane).GetArea();
586 case kYPlane: 582 DCHECK(bits_per_element % pixels_per_element == 0);
587 case kUPlane: 583 return bits_per_element / pixels_per_element;
588 case kVPlane:
589 return 8;
590 default:
591 break;
592 }
593 break;
594 case VideoFrame::YV12:
595 case VideoFrame::YV16:
596 case VideoFrame::I420:
597 case VideoFrame::YV12J:
598 switch (plane) {
599 case kYPlane:
600 return 8;
601 case kUPlane:
602 case kVPlane:
603 return 2;
604 default:
605 break;
606 }
607 break;
608 case VideoFrame::YV12A:
609 switch (plane) {
610 case kYPlane:
611 case kAPlane:
612 return 8;
613 case kUPlane:
614 case kVPlane:
615 return 2;
616 default:
617 break;
618 }
619 break;
620 case VideoFrame::NV12:
621 switch (plane) {
622 case kYPlane:
623 return 8;
624 case kUVPlane:
625 return 4;
626 default:
627 break;
628 }
629 break;
630 case VideoFrame::UNKNOWN:
631 #if defined(VIDEO_HOLE)
632 case VideoFrame::HOLE:
633 #endif // defined(VIDEO_HOLE)
634 case VideoFrame::NATIVE_TEXTURE:
635 break;
636 }
637 NOTREACHED() << "Unsupported video frame format/plane: "
638 << format << "/" << plane;
639 return 0;
640 } 584 }
641 585
642 // Release data allocated by AllocateYUV(). 586 // Release data allocated by AllocateYUV().
643 static void ReleaseData(uint8* data) { 587 static void ReleaseData(uint8* data) {
644 DCHECK(data); 588 DCHECK(data);
645 base::AlignedFree(data); 589 base::AlignedFree(data);
646 } 590 }
647 591
648 void VideoFrame::AllocateYUV() { 592 void VideoFrame::AllocateYUV() {
649 DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16 || 593 DCHECK(format_ == YV12 || format_ == YV16 || format_ == YV12A ||
650 format_ == VideoFrame::YV12A || format_ == VideoFrame::I420 || 594 format_ == I420 || format_ == YV12J || format_ == YV24);
651 format_ == VideoFrame::YV12J || format_ == VideoFrame::YV24); 595 COMPILE_ASSERT(0 == kYPlane, y_plane_data_must_be_index_0);
652 // Align Y rows at least at 16 byte boundaries. The stride for both
653 // YV12 and YV16 is 1/2 of the stride of Y. For YV12, every row of bytes for
654 // U and V applies to two rows of Y (one byte of UV for 4 bytes of Y), so in
655 // the case of YV12 the strides are identical for the same width surface, but
656 // the number of bytes allocated for YV12 is 1/2 the amount for U & V as
657 // YV16. We also round the height of the surface allocated to be an even
658 // number to avoid any potential of faulting by code that attempts to access
659 // the Y values of the final row, but assumes that the last row of U & V
660 // applies to a full two rows of Y. YV12A is the same as YV12, but with an
661 // additional alpha plane that has the same size and alignment as the Y plane.
662 size_t y_stride = RoundUp(row_bytes(VideoFrame::kYPlane),
663 kFrameSizeAlignment);
664 size_t uv_stride = RoundUp(row_bytes(VideoFrame::kUPlane),
665 kFrameSizeAlignment);
666 596
667 // The *2 here is because some formats (e.g. h264) allow interlaced coding, 597 size_t data_size = 0;
668 // and then the size needs to be a multiple of two macroblocks (vertically). 598 size_t offset[kMaxPlanes];
669 // See libavcodec/utils.c:avcodec_align_dimensions2(). 599 for (size_t plane = 0; plane < VideoFrame::NumPlanes(format_); ++plane) {
670 size_t y_height = RoundUp(coded_size_.height(), kFrameSizeAlignment * 2); 600 // The *2 in alignment for height is because some formats (e.g. h264) allow
671 size_t uv_height = 601 // interlaced coding, and then the size needs to be a multiple of two
672 (format_ == VideoFrame::YV12 || format_ == VideoFrame::YV12A || 602 // macroblocks (vertically). See
673 format_ == VideoFrame::I420) 603 // libavcodec/utils.c:avcodec_align_dimensions2().
674 ? y_height / 2 604 const size_t height = RoundUp(rows(plane), kFrameSizeAlignment * 2);
675 : y_height; 605 strides_[plane] = RoundUp(row_bytes(plane), kFrameSizeAlignment);
676 size_t y_bytes = y_height * y_stride; 606 offset[plane] = data_size;
677 size_t uv_bytes = uv_height * uv_stride; 607 data_size += height * strides_[plane];
678 size_t a_bytes = format_ == VideoFrame::YV12A ? y_bytes : 0; 608 }
679 609
680 // The extra line of UV being allocated is because h264 chroma MC 610 // The extra line of UV being allocated is because h264 chroma MC
681 // overreads by one line in some cases, see libavcodec/utils.c: 611 // overreads by one line in some cases, see libavcodec/utils.c:
682 // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm: 612 // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm:
683 // put_h264_chroma_mc4_ssse3(). 613 // put_h264_chroma_mc4_ssse3().
684 const size_t data_size = 614 DCHECK(IsValidPlane(kUPlane, format_));
685 y_bytes + (uv_bytes * 2 + uv_stride) + a_bytes + kFrameSizePadding; 615 data_size += strides_[kUPlane] + kFrameSizePadding;
616
617 // FFmpeg expects the initialize allocation to be zero-initialized. Failure
618 // to do so can lead to unitialized value usage. See http://crbug.com/390941
686 uint8* data = reinterpret_cast<uint8*>( 619 uint8* data = reinterpret_cast<uint8*>(
687 base::AlignedAlloc(data_size, kFrameAddressAlignment)); 620 base::AlignedAlloc(data_size, kFrameAddressAlignment));
688 // FFmpeg expects the initialize allocation to be zero-initialized. Failure
689 // to do so can lead to unitialized value usage. See http://crbug.com/390941
690 memset(data, 0, data_size); 621 memset(data, 0, data_size);
622
623 for (size_t plane = 0; plane < VideoFrame::NumPlanes(format_); ++plane)
624 data_[plane] = data + offset[plane];
625
691 no_longer_needed_cb_ = base::Bind(&ReleaseData, data); 626 no_longer_needed_cb_ = base::Bind(&ReleaseData, data);
692 COMPILE_ASSERT(0 == VideoFrame::kYPlane, y_plane_data_must_be_index_0);
693 data_[VideoFrame::kYPlane] = data;
694 data_[VideoFrame::kUPlane] = data + y_bytes;
695 data_[VideoFrame::kVPlane] = data + y_bytes + uv_bytes;
696 strides_[VideoFrame::kYPlane] = y_stride;
697 strides_[VideoFrame::kUPlane] = uv_stride;
698 strides_[VideoFrame::kVPlane] = uv_stride;
699 if (format_ == YV12A) {
700 data_[VideoFrame::kAPlane] = data + y_bytes + (2 * uv_bytes);
701 strides_[VideoFrame::kAPlane] = y_stride;
702 }
703 } 627 }
704 628
705 VideoFrame::VideoFrame(VideoFrame::Format format, 629 VideoFrame::VideoFrame(VideoFrame::Format format,
706 const gfx::Size& coded_size, 630 const gfx::Size& coded_size,
707 const gfx::Rect& visible_rect, 631 const gfx::Rect& visible_rect,
708 const gfx::Size& natural_size, 632 const gfx::Size& natural_size,
709 scoped_ptr<gpu::MailboxHolder> mailbox_holder, 633 scoped_ptr<gpu::MailboxHolder> mailbox_holder,
710 base::TimeDelta timestamp, 634 base::TimeDelta timestamp,
711 bool end_of_stream) 635 bool end_of_stream)
712 : format_(format), 636 : format_(format),
(...skipping 30 matching lines...) Expand all
743 bool VideoFrame::IsValidPlane(size_t plane, VideoFrame::Format format) { 667 bool VideoFrame::IsValidPlane(size_t plane, VideoFrame::Format format) {
744 return (plane < NumPlanes(format)); 668 return (plane < NumPlanes(format));
745 } 669 }
746 670
747 int VideoFrame::stride(size_t plane) const { 671 int VideoFrame::stride(size_t plane) const {
748 DCHECK(IsValidPlane(plane, format_)); 672 DCHECK(IsValidPlane(plane, format_));
749 return strides_[plane]; 673 return strides_[plane];
750 } 674 }
751 675
752 // static 676 // static
753 size_t VideoFrame::RowBytes(size_t plane, VideoFrame::Format format, 677 size_t VideoFrame::RowBytes(size_t plane,
678 VideoFrame::Format format,
754 int width) { 679 int width) {
755 DCHECK(IsValidPlane(plane, format)); 680 DCHECK(IsValidPlane(plane, format));
756 switch (format) { 681 return BytesPerElement(format, plane) * Columns(plane, format, width);
757 case VideoFrame::YV24:
758 switch (plane) {
759 case kYPlane:
760 case kUPlane:
761 case kVPlane:
762 return width;
763 default:
764 break;
765 }
766 break;
767 case VideoFrame::YV12:
768 case VideoFrame::YV16:
769 case VideoFrame::I420:
770 case VideoFrame::YV12J:
771 switch (plane) {
772 case kYPlane:
773 return width;
774 case kUPlane:
775 case kVPlane:
776 return RoundUp(width, 2) / 2;
777 default:
778 break;
779 }
780 break;
781 case VideoFrame::YV12A:
782 switch (plane) {
783 case kYPlane:
784 case kAPlane:
785 return width;
786 case kUPlane:
787 case kVPlane:
788 return RoundUp(width, 2) / 2;
789 default:
790 break;
791 }
792 break;
793 case VideoFrame::NV12:
794 switch (plane) {
795 case kYPlane:
796 case kUVPlane:
797 return width;
798 default:
799 break;
800 }
801 break;
802 case VideoFrame::UNKNOWN:
803 #if defined(VIDEO_HOLE)
804 case VideoFrame::HOLE:
805 #endif // defined(VIDEO_HOLE)
806 case VideoFrame::NATIVE_TEXTURE:
807 break;
808 }
809 NOTREACHED() << "Unsupported video frame format/plane: " << format << "/"
810 << plane;
811 return 0;
812 } 682 }
813 683
814 int VideoFrame::row_bytes(size_t plane) const { 684 int VideoFrame::row_bytes(size_t plane) const {
815 return RowBytes(plane, format_, coded_size_.width()); 685 return RowBytes(plane, format_, coded_size_.width());
816 } 686 }
817 687
818 // static 688 // static
819 size_t VideoFrame::Rows(size_t plane, VideoFrame::Format format, int height) { 689 size_t VideoFrame::Rows(size_t plane, VideoFrame::Format format, int height) {
820 DCHECK(IsValidPlane(plane, format)); 690 DCHECK(IsValidPlane(plane, format));
821 switch (format) { 691 const int sample_height = SampleSize(format, plane).height();
822 case VideoFrame::YV24: 692 return RoundUp(height, sample_height) / sample_height;
823 case VideoFrame::YV16: 693 }
824 switch (plane) { 694
825 case kYPlane: 695 // static
826 case kUPlane: 696 size_t VideoFrame::Columns(size_t plane, Format format, int width) {
827 case kVPlane: 697 DCHECK(IsValidPlane(plane, format));
828 return height; 698 const int sample_width = SampleSize(format, plane).width();
829 default: 699 return RoundUp(width, sample_width) / sample_width;
830 break;
831 }
832 break;
833 case VideoFrame::YV12:
834 case VideoFrame::YV12J:
835 case VideoFrame::I420:
836 switch (plane) {
837 case kYPlane:
838 return height;
839 case kUPlane:
840 case kVPlane:
841 return RoundUp(height, 2) / 2;
842 default:
843 break;
844 }
845 break;
846 case VideoFrame::YV12A:
847 switch (plane) {
848 case kYPlane:
849 case kAPlane:
850 return height;
851 case kUPlane:
852 case kVPlane:
853 return RoundUp(height, 2) / 2;
854 default:
855 break;
856 }
857 break;
858 case VideoFrame::NV12:
859 switch (plane) {
860 case kYPlane:
861 return height;
862 case kUVPlane:
863 return RoundUp(height, 2) / 2;
864 default:
865 break;
866 }
867 break;
868 case VideoFrame::UNKNOWN:
869 #if defined(VIDEO_HOLE)
870 case VideoFrame::HOLE:
871 #endif // defined(VIDEO_HOLE)
872 case VideoFrame::NATIVE_TEXTURE:
873 break;
874 }
875 NOTREACHED() << "Unsupported video frame format/plane: " << format << "/"
876 << plane;
877 return 0;
878 } 700 }
879 701
880 int VideoFrame::rows(size_t plane) const { 702 int VideoFrame::rows(size_t plane) const {
881 return Rows(plane, format_, coded_size_.height()); 703 return Rows(plane, format_, coded_size_.height());
882 } 704 }
883 705
884 uint8* VideoFrame::data(size_t plane) const { 706 const uint8* VideoFrame::data(size_t plane) const {
885 DCHECK(IsValidPlane(plane, format_)); 707 DCHECK(IsValidPlane(plane, format_));
886 return data_[plane]; 708 return data_[plane];
887 } 709 }
888 710
711 uint8* VideoFrame::data(size_t plane) {
712 DCHECK(IsValidPlane(plane, format_));
713 return data_[plane];
714 }
715
716 const uint8* VideoFrame::visible_data(size_t plane) const {
717 DCHECK(IsValidPlane(plane, format_));
718
719 // Calculate an offset that is properly aligned for all planes.
720 const gfx::Size alignment = CommonAlignment(format_);
721 const gfx::Point offset(RoundDown(visible_rect_.x(), alignment.width()),
722 RoundDown(visible_rect_.y(), alignment.height()));
723
724 const gfx::Size subsample = SampleSize(format_, plane);
725 DCHECK(offset.x() % subsample.width() == 0);
726 DCHECK(offset.y() % subsample.height() == 0);
727 return data(plane) +
728 stride(plane) * (offset.y() / subsample.height()) + // Row offset.
729 BytesPerElement(format_, plane) * // Column offset.
730 (offset.x() / subsample.width());
731 }
732
733 uint8* VideoFrame::visible_data(size_t plane) {
734 return const_cast<uint8*>(
735 static_cast<const VideoFrame*>(this)->visible_data(plane));
736 }
737
889 const gpu::MailboxHolder* VideoFrame::mailbox_holder() const { 738 const gpu::MailboxHolder* VideoFrame::mailbox_holder() const {
890 DCHECK_EQ(format_, NATIVE_TEXTURE); 739 DCHECK_EQ(format_, NATIVE_TEXTURE);
891 return mailbox_holder_.get(); 740 return mailbox_holder_.get();
892 } 741 }
893 742
894 base::SharedMemoryHandle VideoFrame::shared_memory_handle() const { 743 base::SharedMemoryHandle VideoFrame::shared_memory_handle() const {
895 return shared_memory_handle_; 744 return shared_memory_handle_;
896 } 745 }
897 746
898 void VideoFrame::UpdateReleaseSyncPoint(SyncPointClient* client) { 747 void VideoFrame::UpdateReleaseSyncPoint(SyncPointClient* client) {
(...skipping 13 matching lines...) Expand all
912 } 761 }
913 #endif 762 #endif
914 763
915 #if defined(OS_MACOSX) 764 #if defined(OS_MACOSX)
916 CVPixelBufferRef VideoFrame::cv_pixel_buffer() const { 765 CVPixelBufferRef VideoFrame::cv_pixel_buffer() const {
917 return cv_pixel_buffer_.get(); 766 return cv_pixel_buffer_.get();
918 } 767 }
919 #endif 768 #endif
920 769
921 void VideoFrame::HashFrameForTesting(base::MD5Context* context) { 770 void VideoFrame::HashFrameForTesting(base::MD5Context* context) {
922 for (int plane = 0; plane < kMaxPlanes; ++plane) { 771 for (size_t plane = 0; plane < NumPlanes(format_); ++plane) {
923 if (!IsValidPlane(plane, format_))
924 break;
925 for (int row = 0; row < rows(plane); ++row) { 772 for (int row = 0; row < rows(plane); ++row) {
926 base::MD5Update(context, base::StringPiece( 773 base::MD5Update(context, base::StringPiece(
927 reinterpret_cast<char*>(data(plane) + stride(plane) * row), 774 reinterpret_cast<char*>(data(plane) + stride(plane) * row),
928 row_bytes(plane))); 775 row_bytes(plane)));
929 } 776 }
930 } 777 }
931 } 778 }
932 779
933 } // namespace media 780 } // namespace media
OLDNEW
« no previous file with comments | « media/base/video_frame.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698