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