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 14 matching lines...) Expand all Loading... |
25 const gfx::Size& natural_size, | 25 const gfx::Size& natural_size, |
26 base::TimeDelta timestamp) { | 26 base::TimeDelta timestamp) { |
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::YV16: | 36 case VideoFrame::YV16: |
36 frame->AllocateYUV(); | 37 frame->AllocateYUV(); |
37 break; | 38 break; |
38 default: | 39 default: |
39 LOG(FATAL) << "Unsupported frame format: " << format; | 40 LOG(FATAL) << "Unsupported frame format: " << format; |
40 } | 41 } |
41 return frame; | 42 return frame; |
42 } | 43 } |
43 | 44 |
44 // static | 45 // static |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 case VideoFrame::NATIVE_TEXTURE: | 161 case VideoFrame::NATIVE_TEXTURE: |
161 #if defined(GOOGLE_TV) | 162 #if defined(GOOGLE_TV) |
162 case VideoFrame::HOLE: | 163 case VideoFrame::HOLE: |
163 #endif | 164 #endif |
164 return 0; | 165 return 0; |
165 case VideoFrame::RGB32: | 166 case VideoFrame::RGB32: |
166 return 1; | 167 return 1; |
167 case VideoFrame::YV12: | 168 case VideoFrame::YV12: |
168 case VideoFrame::YV16: | 169 case VideoFrame::YV16: |
169 return 3; | 170 return 3; |
| 171 case VideoFrame::YV12A: |
| 172 return 4; |
170 case VideoFrame::EMPTY: | 173 case VideoFrame::EMPTY: |
171 case VideoFrame::I420: | 174 case VideoFrame::I420: |
172 case VideoFrame::INVALID: | 175 case VideoFrame::INVALID: |
173 break; | 176 break; |
174 } | 177 } |
175 NOTREACHED() << "Unsupported video frame format: " << format; | 178 NOTREACHED() << "Unsupported video frame format: " << format; |
176 return 0; | 179 return 0; |
177 } | 180 } |
178 | 181 |
179 static inline size_t RoundUp(size_t value, size_t alignment) { | 182 static inline size_t RoundUp(size_t value, size_t alignment) { |
(...skipping 17 matching lines...) Expand all Loading... |
197 strides_[VideoFrame::kRGBPlane] = bytes_per_row; | 200 strides_[VideoFrame::kRGBPlane] = bytes_per_row; |
198 data_[VideoFrame::kRGBPlane] = reinterpret_cast<uint8*>( | 201 data_[VideoFrame::kRGBPlane] = reinterpret_cast<uint8*>( |
199 base::AlignedAlloc(bytes_per_row * aligned_height + kFrameSizePadding, | 202 base::AlignedAlloc(bytes_per_row * aligned_height + kFrameSizePadding, |
200 kFrameAddressAlignment)); | 203 kFrameAddressAlignment)); |
201 no_longer_needed_cb_ = base::Bind(&ReleaseData, data_[VideoFrame::kRGBPlane]); | 204 no_longer_needed_cb_ = base::Bind(&ReleaseData, data_[VideoFrame::kRGBPlane]); |
202 DCHECK(!(reinterpret_cast<intptr_t>(data_[VideoFrame::kRGBPlane]) & 7)); | 205 DCHECK(!(reinterpret_cast<intptr_t>(data_[VideoFrame::kRGBPlane]) & 7)); |
203 COMPILE_ASSERT(0 == VideoFrame::kRGBPlane, RGB_data_must_be_index_0); | 206 COMPILE_ASSERT(0 == VideoFrame::kRGBPlane, RGB_data_must_be_index_0); |
204 } | 207 } |
205 | 208 |
206 void VideoFrame::AllocateYUV() { | 209 void VideoFrame::AllocateYUV() { |
207 DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16); | 210 DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16 || |
| 211 format_ == VideoFrame::YV12A); |
208 // Align Y rows at least at 16 byte boundaries. The stride for both | 212 // Align Y rows at least at 16 byte boundaries. The stride for both |
209 // YV12 and YV16 is 1/2 of the stride of Y. For YV12, every row of bytes for | 213 // YV12 and YV16 is 1/2 of the stride of Y. For YV12, every row of bytes for |
210 // U and V applies to two rows of Y (one byte of UV for 4 bytes of Y), so in | 214 // U and V applies to two rows of Y (one byte of UV for 4 bytes of Y), so in |
211 // the case of YV12 the strides are identical for the same width surface, but | 215 // the case of YV12 the strides are identical for the same width surface, but |
212 // the number of bytes allocated for YV12 is 1/2 the amount for U & V as | 216 // the number of bytes allocated for YV12 is 1/2 the amount for U & V as |
213 // YV16. We also round the height of the surface allocated to be an even | 217 // YV16. We also round the height of the surface allocated to be an even |
214 // number to avoid any potential of faulting by code that attempts to access | 218 // number to avoid any potential of faulting by code that attempts to access |
215 // the Y values of the final row, but assumes that the last row of U & V | 219 // the Y values of the final row, but assumes that the last row of U & V |
216 // applies to a full two rows of Y. | 220 // applies to a full two rows of Y. YV12A is the same as YV12, but with an |
| 221 // additional alpha plane that has the same size and alignment as the Y plane. |
| 222 |
217 size_t y_stride = RoundUp(row_bytes(VideoFrame::kYPlane), | 223 size_t y_stride = RoundUp(row_bytes(VideoFrame::kYPlane), |
218 kFrameSizeAlignment); | 224 kFrameSizeAlignment); |
219 size_t uv_stride = RoundUp(row_bytes(VideoFrame::kUPlane), | 225 size_t uv_stride = RoundUp(row_bytes(VideoFrame::kUPlane), |
220 kFrameSizeAlignment); | 226 kFrameSizeAlignment); |
221 // The *2 here is because some formats (e.g. h264) allow interlaced coding, | 227 // The *2 here is because some formats (e.g. h264) allow interlaced coding, |
222 // and then the size needs to be a multiple of two macroblocks (vertically). | 228 // and then the size needs to be a multiple of two macroblocks (vertically). |
223 // See libavcodec/utils.c:avcodec_align_dimensions2(). | 229 // See libavcodec/utils.c:avcodec_align_dimensions2(). |
224 size_t y_height = RoundUp(coded_size_.height(), kFrameSizeAlignment * 2); | 230 size_t y_height = RoundUp(coded_size_.height(), kFrameSizeAlignment * 2); |
225 size_t uv_height = format_ == VideoFrame::YV12 ? y_height / 2 : y_height; | 231 size_t uv_height = (format_ == VideoFrame::YV12 || |
| 232 format_ == VideoFrame::YV12A) ? |
| 233 y_height / 2 : y_height; |
226 size_t y_bytes = y_height * y_stride; | 234 size_t y_bytes = y_height * y_stride; |
227 size_t uv_bytes = uv_height * uv_stride; | 235 size_t uv_bytes = uv_height * uv_stride; |
| 236 size_t a_bytes = format_ == VideoFrame::YV12A ? y_bytes : 0; |
228 | 237 |
229 // The extra line of UV being allocated is because h264 chroma MC | 238 // The extra line of UV being allocated is because h264 chroma MC |
230 // overreads by one line in some cases, see libavcodec/utils.c: | 239 // overreads by one line in some cases, see libavcodec/utils.c: |
231 // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm: | 240 // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm: |
232 // put_h264_chroma_mc4_ssse3(). | 241 // put_h264_chroma_mc4_ssse3(). |
233 uint8* data = reinterpret_cast<uint8*>( | 242 uint8* data = reinterpret_cast<uint8*>( |
234 base::AlignedAlloc( | 243 base::AlignedAlloc( |
235 y_bytes + (uv_bytes * 2 + uv_stride) + kFrameSizePadding, | 244 y_bytes + (uv_bytes * 2 + uv_stride) + a_bytes + kFrameSizePadding, |
236 kFrameAddressAlignment)); | 245 kFrameAddressAlignment)); |
237 no_longer_needed_cb_ = base::Bind(&ReleaseData, data); | 246 no_longer_needed_cb_ = base::Bind(&ReleaseData, data); |
238 COMPILE_ASSERT(0 == VideoFrame::kYPlane, y_plane_data_must_be_index_0); | 247 COMPILE_ASSERT(0 == VideoFrame::kYPlane, y_plane_data_must_be_index_0); |
239 data_[VideoFrame::kYPlane] = data; | 248 data_[VideoFrame::kYPlane] = data; |
240 data_[VideoFrame::kUPlane] = data + y_bytes; | 249 data_[VideoFrame::kUPlane] = data + y_bytes; |
241 data_[VideoFrame::kVPlane] = data + y_bytes + uv_bytes; | 250 data_[VideoFrame::kVPlane] = data + y_bytes + uv_bytes; |
242 strides_[VideoFrame::kYPlane] = y_stride; | 251 strides_[VideoFrame::kYPlane] = y_stride; |
243 strides_[VideoFrame::kUPlane] = uv_stride; | 252 strides_[VideoFrame::kUPlane] = uv_stride; |
244 strides_[VideoFrame::kVPlane] = uv_stride; | 253 strides_[VideoFrame::kVPlane] = uv_stride; |
| 254 if (format_ == YV12A) { |
| 255 data_[VideoFrame::kAPlane] = data + y_bytes + (2 * uv_bytes); |
| 256 strides_[VideoFrame::kAPlane] = y_stride; |
| 257 } |
245 } | 258 } |
246 | 259 |
247 VideoFrame::VideoFrame(VideoFrame::Format format, | 260 VideoFrame::VideoFrame(VideoFrame::Format format, |
248 const gfx::Size& coded_size, | 261 const gfx::Size& coded_size, |
249 const gfx::Rect& visible_rect, | 262 const gfx::Rect& visible_rect, |
250 const gfx::Size& natural_size, | 263 const gfx::Size& natural_size, |
251 base::TimeDelta timestamp) | 264 base::TimeDelta timestamp) |
252 : format_(format), | 265 : format_(format), |
253 coded_size_(coded_size), | 266 coded_size_(coded_size), |
254 visible_rect_(visible_rect), | 267 visible_rect_(visible_rect), |
(...skipping 23 matching lines...) Expand all Loading... |
278 DCHECK(IsValidPlane(plane)); | 291 DCHECK(IsValidPlane(plane)); |
279 int width = coded_size_.width(); | 292 int width = coded_size_.width(); |
280 switch (format_) { | 293 switch (format_) { |
281 // 32bpp. | 294 // 32bpp. |
282 case RGB32: | 295 case RGB32: |
283 return width * 4; | 296 return width * 4; |
284 | 297 |
285 // Planar, 8bpp. | 298 // Planar, 8bpp. |
286 case YV12: | 299 case YV12: |
287 case YV16: | 300 case YV16: |
288 if (plane == kYPlane) | 301 case YV12A: |
| 302 if (plane == kYPlane || plane == kAPlane) |
289 return width; | 303 return width; |
290 return RoundUp(width, 2) / 2; | 304 return RoundUp(width, 2) / 2; |
291 | 305 |
292 default: | 306 default: |
293 break; | 307 break; |
294 } | 308 } |
295 | 309 |
296 // Intentionally leave out non-production formats. | 310 // Intentionally leave out non-production formats. |
297 NOTREACHED() << "Unsupported video frame format: " << format_; | 311 NOTREACHED() << "Unsupported video frame format: " << format_; |
298 return 0; | 312 return 0; |
299 } | 313 } |
300 | 314 |
301 int VideoFrame::rows(size_t plane) const { | 315 int VideoFrame::rows(size_t plane) const { |
302 DCHECK(IsValidPlane(plane)); | 316 DCHECK(IsValidPlane(plane)); |
303 int height = coded_size_.height(); | 317 int height = coded_size_.height(); |
304 switch (format_) { | 318 switch (format_) { |
305 case RGB32: | 319 case RGB32: |
306 case YV16: | 320 case YV16: |
307 return height; | 321 return height; |
308 | 322 |
309 case YV12: | 323 case YV12: |
310 if (plane == kYPlane) | 324 case YV12A: |
| 325 if (plane == kYPlane || plane == kAPlane) |
311 return height; | 326 return height; |
312 return RoundUp(height, 2) / 2; | 327 return RoundUp(height, 2) / 2; |
313 | 328 |
314 default: | 329 default: |
315 break; | 330 break; |
316 } | 331 } |
317 | 332 |
318 // Intentionally leave out non-production formats. | 333 // Intentionally leave out non-production formats. |
319 NOTREACHED() << "Unsupported video frame format: " << format_; | 334 NOTREACHED() << "Unsupported video frame format: " << format_; |
320 return 0; | 335 return 0; |
(...skipping 24 matching lines...) Expand all Loading... |
345 break; | 360 break; |
346 for (int row = 0; row < rows(plane); ++row) { | 361 for (int row = 0; row < rows(plane); ++row) { |
347 base::MD5Update(context, base::StringPiece( | 362 base::MD5Update(context, base::StringPiece( |
348 reinterpret_cast<char*>(data(plane) + stride(plane) * row), | 363 reinterpret_cast<char*>(data(plane) + stride(plane) * row), |
349 row_bytes(plane))); | 364 row_bytes(plane))); |
350 } | 365 } |
351 } | 366 } |
352 } | 367 } |
353 | 368 |
354 } // namespace media | 369 } // namespace media |
OLD | NEW |