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 16 matching lines...) Expand all Loading... |
27 DCHECK(IsValidConfig(format, coded_size, visible_rect, natural_size)); | 27 DCHECK(IsValidConfig(format, coded_size, visible_rect, natural_size)); |
28 scoped_refptr<VideoFrame> frame(new VideoFrame( | 28 scoped_refptr<VideoFrame> frame(new VideoFrame( |
29 format, coded_size, visible_rect, natural_size, timestamp)); | 29 format, coded_size, visible_rect, natural_size, timestamp)); |
30 switch (format) { | 30 switch (format) { |
31 case VideoFrame::RGB32: | 31 case VideoFrame::RGB32: |
32 frame->AllocateRGB(4u); | 32 frame->AllocateRGB(4u); |
33 break; | 33 break; |
34 case VideoFrame::YV12: | 34 case VideoFrame::YV12: |
35 case VideoFrame::YV12A: | 35 case VideoFrame::YV12A: |
36 case VideoFrame::YV16: | 36 case VideoFrame::YV16: |
| 37 case VideoFrame::I420: |
37 frame->AllocateYUV(); | 38 frame->AllocateYUV(); |
38 break; | 39 break; |
39 default: | 40 default: |
40 LOG(FATAL) << "Unsupported frame format: " << format; | 41 LOG(FATAL) << "Unsupported frame format: " << format; |
41 } | 42 } |
42 return frame; | 43 return frame; |
43 } | 44 } |
44 | 45 |
45 // static | 46 // static |
46 std::string VideoFrame::FormatToString(VideoFrame::Format format) { | 47 std::string VideoFrame::FormatToString(VideoFrame::Format format) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 return frame; | 111 return frame; |
111 } | 112 } |
112 | 113 |
113 void VideoFrame::ReadPixelsFromNativeTexture(const SkBitmap& pixels) { | 114 void VideoFrame::ReadPixelsFromNativeTexture(const SkBitmap& pixels) { |
114 DCHECK_EQ(format_, NATIVE_TEXTURE); | 115 DCHECK_EQ(format_, NATIVE_TEXTURE); |
115 if (!read_pixels_cb_.is_null()) | 116 if (!read_pixels_cb_.is_null()) |
116 read_pixels_cb_.Run(pixels); | 117 read_pixels_cb_.Run(pixels); |
117 } | 118 } |
118 | 119 |
119 // static | 120 // static |
| 121 scoped_refptr<VideoFrame> VideoFrame::WrapExternalSharedMemory( |
| 122 Format format, |
| 123 const gfx::Size& coded_size, |
| 124 const gfx::Rect& visible_rect, |
| 125 const gfx::Size& natural_size, |
| 126 uint8* data, |
| 127 base::SharedMemoryHandle handle, |
| 128 base::TimeDelta timestamp, |
| 129 const base::Closure& no_longer_needed_cb) { |
| 130 switch (format) { |
| 131 case I420: { |
| 132 scoped_refptr<VideoFrame> frame(new VideoFrame( |
| 133 format, coded_size, visible_rect, natural_size, timestamp)); |
| 134 frame->shared_memory_handle_ = handle; |
| 135 frame->strides_[kYPlane] = coded_size.width(); |
| 136 frame->strides_[kUPlane] = coded_size.width() / 2; |
| 137 frame->strides_[kVPlane] = coded_size.width() / 2; |
| 138 frame->data_[kYPlane] = data; |
| 139 frame->data_[kUPlane] = data + coded_size.GetArea(); |
| 140 frame->data_[kVPlane] = data + (coded_size.GetArea() * 5 / 4); |
| 141 frame->no_longer_needed_cb_ = no_longer_needed_cb; |
| 142 return frame; |
| 143 } |
| 144 default: |
| 145 NOTIMPLEMENTED(); |
| 146 return NULL; |
| 147 } |
| 148 } |
| 149 |
| 150 // static |
120 scoped_refptr<VideoFrame> VideoFrame::WrapExternalYuvData( | 151 scoped_refptr<VideoFrame> VideoFrame::WrapExternalYuvData( |
121 Format format, | 152 Format format, |
122 const gfx::Size& coded_size, | 153 const gfx::Size& coded_size, |
123 const gfx::Rect& visible_rect, | 154 const gfx::Rect& visible_rect, |
124 const gfx::Size& natural_size, | 155 const gfx::Size& natural_size, |
125 int32 y_stride, int32 u_stride, int32 v_stride, | 156 int32 y_stride, |
126 uint8* y_data, uint8* u_data, uint8* v_data, | 157 int32 u_stride, |
| 158 int32 v_stride, |
| 159 uint8* y_data, |
| 160 uint8* u_data, |
| 161 uint8* v_data, |
127 base::TimeDelta timestamp, | 162 base::TimeDelta timestamp, |
128 base::SharedMemoryHandle shm_handle, | |
129 const base::Closure& no_longer_needed_cb) { | 163 const base::Closure& no_longer_needed_cb) { |
130 DCHECK(format == YV12 || format == YV16 || format == I420) << format; | 164 DCHECK(format == YV12 || format == YV16 || format == I420) << format; |
131 scoped_refptr<VideoFrame> frame(new VideoFrame( | 165 scoped_refptr<VideoFrame> frame(new VideoFrame( |
132 format, coded_size, visible_rect, natural_size, timestamp)); | 166 format, coded_size, visible_rect, natural_size, timestamp)); |
133 frame->shared_memory_handle_ = shm_handle; | |
134 frame->strides_[kYPlane] = y_stride; | 167 frame->strides_[kYPlane] = y_stride; |
135 frame->strides_[kUPlane] = u_stride; | 168 frame->strides_[kUPlane] = u_stride; |
136 frame->strides_[kVPlane] = v_stride; | 169 frame->strides_[kVPlane] = v_stride; |
137 frame->data_[kYPlane] = y_data; | 170 frame->data_[kYPlane] = y_data; |
138 frame->data_[kUPlane] = u_data; | 171 frame->data_[kUPlane] = u_data; |
139 frame->data_[kVPlane] = v_data; | 172 frame->data_[kVPlane] = v_data; |
140 frame->no_longer_needed_cb_ = no_longer_needed_cb; | 173 frame->no_longer_needed_cb_ = no_longer_needed_cb; |
141 return frame; | 174 return frame; |
142 } | 175 } |
143 | 176 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 switch (format) { | 224 switch (format) { |
192 case VideoFrame::NATIVE_TEXTURE: | 225 case VideoFrame::NATIVE_TEXTURE: |
193 #if defined(GOOGLE_TV) | 226 #if defined(GOOGLE_TV) |
194 case VideoFrame::HOLE: | 227 case VideoFrame::HOLE: |
195 #endif | 228 #endif |
196 return 0; | 229 return 0; |
197 case VideoFrame::RGB32: | 230 case VideoFrame::RGB32: |
198 return 1; | 231 return 1; |
199 case VideoFrame::YV12: | 232 case VideoFrame::YV12: |
200 case VideoFrame::YV16: | 233 case VideoFrame::YV16: |
| 234 case VideoFrame::I420: |
201 return 3; | 235 return 3; |
202 case VideoFrame::YV12A: | 236 case VideoFrame::YV12A: |
203 return 4; | 237 return 4; |
204 case VideoFrame::EMPTY: | 238 case VideoFrame::EMPTY: |
205 case VideoFrame::I420: | |
206 case VideoFrame::INVALID: | 239 case VideoFrame::INVALID: |
207 break; | 240 break; |
208 } | 241 } |
209 NOTREACHED() << "Unsupported video frame format: " << format; | 242 NOTREACHED() << "Unsupported video frame format: " << format; |
210 return 0; | 243 return 0; |
211 } | 244 } |
212 | 245 |
213 static inline size_t RoundUp(size_t value, size_t alignment) { | 246 static inline size_t RoundUp(size_t value, size_t alignment) { |
214 // Check that |alignment| is a power of 2. | 247 // Check that |alignment| is a power of 2. |
215 DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1))); | 248 DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1))); |
(...skipping 16 matching lines...) Expand all Loading... |
232 data_[VideoFrame::kRGBPlane] = reinterpret_cast<uint8*>( | 265 data_[VideoFrame::kRGBPlane] = reinterpret_cast<uint8*>( |
233 base::AlignedAlloc(bytes_per_row * aligned_height + kFrameSizePadding, | 266 base::AlignedAlloc(bytes_per_row * aligned_height + kFrameSizePadding, |
234 kFrameAddressAlignment)); | 267 kFrameAddressAlignment)); |
235 no_longer_needed_cb_ = base::Bind(&ReleaseData, data_[VideoFrame::kRGBPlane]); | 268 no_longer_needed_cb_ = base::Bind(&ReleaseData, data_[VideoFrame::kRGBPlane]); |
236 DCHECK(!(reinterpret_cast<intptr_t>(data_[VideoFrame::kRGBPlane]) & 7)); | 269 DCHECK(!(reinterpret_cast<intptr_t>(data_[VideoFrame::kRGBPlane]) & 7)); |
237 COMPILE_ASSERT(0 == VideoFrame::kRGBPlane, RGB_data_must_be_index_0); | 270 COMPILE_ASSERT(0 == VideoFrame::kRGBPlane, RGB_data_must_be_index_0); |
238 } | 271 } |
239 | 272 |
240 void VideoFrame::AllocateYUV() { | 273 void VideoFrame::AllocateYUV() { |
241 DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16 || | 274 DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16 || |
242 format_ == VideoFrame::YV12A); | 275 format_ == VideoFrame::YV12A || format_ == VideoFrame::I420); |
243 // Align Y rows at least at 16 byte boundaries. The stride for both | 276 // Align Y rows at least at 16 byte boundaries. The stride for both |
244 // YV12 and YV16 is 1/2 of the stride of Y. For YV12, every row of bytes for | 277 // YV12 and YV16 is 1/2 of the stride of Y. For YV12, every row of bytes for |
245 // U and V applies to two rows of Y (one byte of UV for 4 bytes of Y), so in | 278 // U and V applies to two rows of Y (one byte of UV for 4 bytes of Y), so in |
246 // the case of YV12 the strides are identical for the same width surface, but | 279 // the case of YV12 the strides are identical for the same width surface, but |
247 // the number of bytes allocated for YV12 is 1/2 the amount for U & V as | 280 // the number of bytes allocated for YV12 is 1/2 the amount for U & V as |
248 // YV16. We also round the height of the surface allocated to be an even | 281 // YV16. We also round the height of the surface allocated to be an even |
249 // number to avoid any potential of faulting by code that attempts to access | 282 // number to avoid any potential of faulting by code that attempts to access |
250 // the Y values of the final row, but assumes that the last row of U & V | 283 // the Y values of the final row, but assumes that the last row of U & V |
251 // applies to a full two rows of Y. YV12A is the same as YV12, but with an | 284 // applies to a full two rows of Y. YV12A is the same as YV12, but with an |
252 // additional alpha plane that has the same size and alignment as the Y plane. | 285 // additional alpha plane that has the same size and alignment as the Y plane. |
253 | 286 |
254 size_t y_stride = RoundUp(row_bytes(VideoFrame::kYPlane), | 287 size_t y_stride = RoundUp(row_bytes(VideoFrame::kYPlane), |
255 kFrameSizeAlignment); | 288 kFrameSizeAlignment); |
256 size_t uv_stride = RoundUp(row_bytes(VideoFrame::kUPlane), | 289 size_t uv_stride = RoundUp(row_bytes(VideoFrame::kUPlane), |
257 kFrameSizeAlignment); | 290 kFrameSizeAlignment); |
258 // The *2 here is because some formats (e.g. h264) allow interlaced coding, | 291 // The *2 here is because some formats (e.g. h264) allow interlaced coding, |
259 // and then the size needs to be a multiple of two macroblocks (vertically). | 292 // and then the size needs to be a multiple of two macroblocks (vertically). |
260 // See libavcodec/utils.c:avcodec_align_dimensions2(). | 293 // See libavcodec/utils.c:avcodec_align_dimensions2(). |
261 size_t y_height = RoundUp(coded_size_.height(), kFrameSizeAlignment * 2); | 294 size_t y_height = RoundUp(coded_size_.height(), kFrameSizeAlignment * 2); |
262 size_t uv_height = (format_ == VideoFrame::YV12 || | 295 size_t uv_height = |
263 format_ == VideoFrame::YV12A) ? | 296 (format_ == VideoFrame::YV12 || format_ == VideoFrame::YV12A || |
264 y_height / 2 : y_height; | 297 format_ == VideoFrame::I420) |
| 298 ? y_height / 2 |
| 299 : y_height; |
265 size_t y_bytes = y_height * y_stride; | 300 size_t y_bytes = y_height * y_stride; |
266 size_t uv_bytes = uv_height * uv_stride; | 301 size_t uv_bytes = uv_height * uv_stride; |
267 size_t a_bytes = format_ == VideoFrame::YV12A ? y_bytes : 0; | 302 size_t a_bytes = format_ == VideoFrame::YV12A ? y_bytes : 0; |
268 | 303 |
269 // The extra line of UV being allocated is because h264 chroma MC | 304 // The extra line of UV being allocated is because h264 chroma MC |
270 // overreads by one line in some cases, see libavcodec/utils.c: | 305 // overreads by one line in some cases, see libavcodec/utils.c: |
271 // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm: | 306 // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm: |
272 // put_h264_chroma_mc4_ssse3(). | 307 // put_h264_chroma_mc4_ssse3(). |
273 uint8* data = reinterpret_cast<uint8*>( | 308 uint8* data = reinterpret_cast<uint8*>( |
274 base::AlignedAlloc( | 309 base::AlignedAlloc( |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 | 355 |
321 int VideoFrame::row_bytes(size_t plane) const { | 356 int VideoFrame::row_bytes(size_t plane) const { |
322 DCHECK(IsValidPlane(plane)); | 357 DCHECK(IsValidPlane(plane)); |
323 int width = coded_size_.width(); | 358 int width = coded_size_.width(); |
324 switch (format_) { | 359 switch (format_) { |
325 // 32bpp. | 360 // 32bpp. |
326 case RGB32: | 361 case RGB32: |
327 return width * 4; | 362 return width * 4; |
328 | 363 |
329 // Planar, 8bpp. | 364 // Planar, 8bpp. |
| 365 case YV12A: |
| 366 if (plane == kAPlane) |
| 367 return width; |
| 368 // Fallthrough. |
330 case YV12: | 369 case YV12: |
331 case YV16: | 370 case YV16: |
332 case YV12A: | 371 case I420: |
333 if (plane == kYPlane || plane == kAPlane) | 372 if (plane == kYPlane) |
334 return width; | 373 return width; |
335 return RoundUp(width, 2) / 2; | 374 return RoundUp(width, 2) / 2; |
336 | 375 |
337 default: | 376 default: |
338 break; | 377 break; |
339 } | 378 } |
340 | 379 |
341 // Intentionally leave out non-production formats. | 380 // Intentionally leave out non-production formats. |
342 NOTREACHED() << "Unsupported video frame format: " << format_; | 381 NOTREACHED() << "Unsupported video frame format: " << format_; |
343 return 0; | 382 return 0; |
344 } | 383 } |
345 | 384 |
346 int VideoFrame::rows(size_t plane) const { | 385 int VideoFrame::rows(size_t plane) const { |
347 DCHECK(IsValidPlane(plane)); | 386 DCHECK(IsValidPlane(plane)); |
348 int height = coded_size_.height(); | 387 int height = coded_size_.height(); |
349 switch (format_) { | 388 switch (format_) { |
350 case RGB32: | 389 case RGB32: |
351 case YV16: | 390 case YV16: |
352 return height; | 391 return height; |
353 | 392 |
| 393 case YV12A: |
| 394 if (plane == kAPlane) |
| 395 return height; |
| 396 // Fallthrough. |
354 case YV12: | 397 case YV12: |
355 case YV12A: | 398 case I420: |
356 if (plane == kYPlane || plane == kAPlane) | 399 if (plane == kYPlane) |
357 return height; | 400 return height; |
358 return RoundUp(height, 2) / 2; | 401 return RoundUp(height, 2) / 2; |
359 | 402 |
360 default: | 403 default: |
361 break; | 404 break; |
362 } | 405 } |
363 | 406 |
364 // Intentionally leave out non-production formats. | 407 // Intentionally leave out non-production formats. |
365 NOTREACHED() << "Unsupported video frame format: " << format_; | 408 NOTREACHED() << "Unsupported video frame format: " << format_; |
366 return 0; | 409 return 0; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 : mailbox_(mailbox), | 452 : mailbox_(mailbox), |
410 sync_point_(sync_point), | 453 sync_point_(sync_point), |
411 release_callback_(release_callback) {} | 454 release_callback_(release_callback) {} |
412 | 455 |
413 VideoFrame::MailboxHolder::~MailboxHolder() { | 456 VideoFrame::MailboxHolder::~MailboxHolder() { |
414 if (!release_callback_.is_null()) | 457 if (!release_callback_.is_null()) |
415 release_callback_.Run(sync_point_); | 458 release_callback_.Run(sync_point_); |
416 } | 459 } |
417 | 460 |
418 } // namespace media | 461 } // namespace media |
OLD | NEW |