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