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