Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(417)

Side by Side Diff: media/base/video_frame.cc

Issue 11413005: YUV software decode path stride fixes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: WebKit nits. Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« cc/texture_uploader_unittest.cc ('K') | « cc/video_layer_impl.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "base/bits.h"
7 #include "base/logging.h" 8 #include "base/logging.h"
8 #include "base/string_piece.h" 9 #include "base/string_piece.h"
9 #include "media/base/limits.h" 10 #include "media/base/limits.h"
10 #include "media/base/video_util.h" 11 #include "media/base/video_util.h"
11 #if !defined(OS_ANDROID) 12 #if !defined(OS_ANDROID)
12 #include "media/ffmpeg/ffmpeg_common.h" 13 #include "media/ffmpeg/ffmpeg_common.h"
13 #endif 14 #endif
14 15
15 #include <algorithm> 16 #include <algorithm>
16 17
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 } 107 }
107 108
108 // static 109 // static
109 scoped_refptr<VideoFrame> VideoFrame::CreateBlackFrame(const gfx::Size& size) { 110 scoped_refptr<VideoFrame> VideoFrame::CreateBlackFrame(const gfx::Size& size) {
110 const uint8 kBlackY = 0x00; 111 const uint8 kBlackY = 0x00;
111 const uint8 kBlackUV = 0x80; 112 const uint8 kBlackUV = 0x80;
112 const base::TimeDelta kZero; 113 const base::TimeDelta kZero;
113 return CreateColorFrame(size, kBlackY, kBlackUV, kBlackUV, kZero); 114 return CreateColorFrame(size, kBlackY, kBlackUV, kBlackUV, kZero);
114 } 115 }
115 116
116 static inline size_t RoundUp(size_t value, size_t alignment) {
117 // Check that |alignment| is a power of 2.
118 DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
119 return ((value + (alignment - 1)) & ~(alignment-1));
120 }
121
122 static const int kFrameSizeAlignment = 16; 117 static const int kFrameSizeAlignment = 16;
123 // Allows faster SIMD YUV convert. Also, FFmpeg overreads/-writes occasionally. 118 // Allows faster SIMD YUV convert. Also, FFmpeg overreads/-writes occasionally.
124 static const int kFramePadBytes = 15; 119 static const int kFramePadBytes = 15;
125 120
126 void VideoFrame::AllocateRGB(size_t bytes_per_pixel) { 121 void VideoFrame::AllocateRGB(size_t bytes_per_pixel) {
127 // Round up to align at least at a 16-byte boundary for each row. 122 // Round up to align at least at a 16-byte boundary for each row.
128 // This is sufficient for MMX and SSE2 reads (movq/movdqa). 123 // This is sufficient for MMX and SSE2 reads (movq/movdqa).
129 size_t bytes_per_row = RoundUp(coded_size_.width(), 124 size_t bytes_per_row = base::bits::RoundUp(
130 kFrameSizeAlignment) * bytes_per_pixel; 125 coded_size_.width(), kFrameSizeAlignment) * bytes_per_pixel;
131 size_t aligned_height = RoundUp(coded_size_.height(), kFrameSizeAlignment); 126 size_t aligned_height = base::bits::RoundUp(
127 coded_size_.height(), kFrameSizeAlignment);
132 strides_[VideoFrame::kRGBPlane] = bytes_per_row; 128 strides_[VideoFrame::kRGBPlane] = bytes_per_row;
133 #if !defined(OS_ANDROID) 129 #if !defined(OS_ANDROID)
134 // TODO(dalecurtis): use DataAligned or so, so this #ifdef hackery 130 // TODO(dalecurtis): use DataAligned or so, so this #ifdef hackery
135 // doesn't need to be repeated in every single user of aligned data. 131 // doesn't need to be repeated in every single user of aligned data.
136 data_[VideoFrame::kRGBPlane] = reinterpret_cast<uint8*>( 132 data_[VideoFrame::kRGBPlane] = reinterpret_cast<uint8*>(
137 av_malloc(bytes_per_row * aligned_height + kFramePadBytes)); 133 av_malloc(bytes_per_row * aligned_height + kFramePadBytes));
138 #else 134 #else
139 data_[VideoFrame::kRGBPlane] = new uint8_t[bytes_per_row * aligned_height]; 135 data_[VideoFrame::kRGBPlane] = new uint8_t[bytes_per_row * aligned_height];
140 #endif 136 #endif
141 DCHECK(!(reinterpret_cast<intptr_t>(data_[VideoFrame::kRGBPlane]) & 7)); 137 DCHECK(!(reinterpret_cast<intptr_t>(data_[VideoFrame::kRGBPlane]) & 7));
142 COMPILE_ASSERT(0 == VideoFrame::kRGBPlane, RGB_data_must_be_index_0); 138 COMPILE_ASSERT(0 == VideoFrame::kRGBPlane, RGB_data_must_be_index_0);
143 } 139 }
144 140
145 void VideoFrame::AllocateYUV() { 141 void VideoFrame::AllocateYUV() {
146 DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16); 142 DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16);
147 // Align Y rows at least at 16 byte boundaries. The stride for both 143 // Align Y rows at least at 16 byte boundaries. The stride for both
148 // YV12 and YV16 is 1/2 of the stride of Y. For YV12, every row of bytes for 144 // YV12 and YV16 is 1/2 of the stride of Y. For YV12, every row of bytes for
149 // U and V applies to two rows of Y (one byte of UV for 4 bytes of Y), so in 145 // U and V applies to two rows of Y (one byte of UV for 4 bytes of Y), so in
150 // the case of YV12 the strides are identical for the same width surface, but 146 // the case of YV12 the strides are identical for the same width surface, but
151 // the number of bytes allocated for YV12 is 1/2 the amount for U & V as 147 // the number of bytes allocated for YV12 is 1/2 the amount for U & V as
152 // YV16. We also round the height of the surface allocated to be an even 148 // YV16. We also round the height of the surface allocated to be an even
153 // number to avoid any potential of faulting by code that attempts to access 149 // number to avoid any potential of faulting by code that attempts to access
154 // the Y values of the final row, but assumes that the last row of U & V 150 // the Y values of the final row, but assumes that the last row of U & V
155 // applies to a full two rows of Y. 151 // applies to a full two rows of Y.
156 size_t y_stride = RoundUp(row_bytes(VideoFrame::kYPlane), 152 size_t y_stride = base::bits::RoundUp(row_bytes(VideoFrame::kYPlane),
157 kFrameSizeAlignment); 153 kFrameSizeAlignment);
158 size_t uv_stride = RoundUp(row_bytes(VideoFrame::kUPlane), 154 size_t uv_stride = base::bits::RoundUp(row_bytes(VideoFrame::kUPlane),
159 kFrameSizeAlignment); 155 kFrameSizeAlignment);
160 // The *2 here is because some formats (e.g. h264) allow interlaced coding, 156 // The *2 here is because some formats (e.g. h264) allow interlaced coding,
161 // and then the size needs to be a multiple of two macroblocks (vertically). 157 // and then the size needs to be a multiple of two macroblocks (vertically).
162 // See libavcodec/utils.c:avcodec_align_dimensions2(). 158 // See libavcodec/utils.c:avcodec_align_dimensions2().
163 size_t y_height = RoundUp(coded_size_.height(), kFrameSizeAlignment * 2); 159 size_t y_height = base::bits::RoundUp(coded_size_.height(),
160 kFrameSizeAlignment * 2);
164 size_t uv_height = format_ == VideoFrame::YV12 ? y_height / 2 : y_height; 161 size_t uv_height = format_ == VideoFrame::YV12 ? y_height / 2 : y_height;
165 size_t y_bytes = y_height * y_stride; 162 size_t y_bytes = y_height * y_stride;
166 size_t uv_bytes = uv_height * uv_stride; 163 size_t uv_bytes = uv_height * uv_stride;
167 164
168 #if !defined(OS_ANDROID) 165 #if !defined(OS_ANDROID)
169 // TODO(dalecurtis): use DataAligned or so, so this #ifdef hackery 166 // TODO(dalecurtis): use DataAligned or so, so this #ifdef hackery
170 // doesn't need to be repeated in every single user of aligned data. 167 // doesn't need to be repeated in every single user of aligned data.
171 // The extra line of UV being allocated is because h264 chroma MC 168 // The extra line of UV being allocated is because h264 chroma MC
172 // overreads by one line in some cases, see libavcodec/utils.c: 169 // overreads by one line in some cases, see libavcodec/utils.c:
173 // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm: 170 // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm:
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 switch (format_) { 250 switch (format_) {
254 // 32bpp. 251 // 32bpp.
255 case RGB32: 252 case RGB32:
256 return width * 4; 253 return width * 4;
257 254
258 // Planar, 8bpp. 255 // Planar, 8bpp.
259 case YV12: 256 case YV12:
260 case YV16: 257 case YV16:
261 if (plane == kYPlane) 258 if (plane == kYPlane)
262 return width; 259 return width;
263 return RoundUp(width, 2) / 2; 260 return base::bits::RoundUp(width, 2) / 2;
264 261
265 default: 262 default:
266 break; 263 break;
267 } 264 }
268 265
269 // Intentionally leave out non-production formats. 266 // Intentionally leave out non-production formats.
270 NOTREACHED() << "Unsupported video frame format: " << format_; 267 NOTREACHED() << "Unsupported video frame format: " << format_;
271 return 0; 268 return 0;
272 } 269 }
273 270
274 int VideoFrame::rows(size_t plane) const { 271 int VideoFrame::rows(size_t plane) const {
275 DCHECK(IsValidPlane(plane)); 272 DCHECK(IsValidPlane(plane));
276 int height = coded_size_.height(); 273 int height = coded_size_.height();
277 switch (format_) { 274 switch (format_) {
278 case RGB32: 275 case RGB32:
279 case YV16: 276 case YV16:
280 return height; 277 return height;
281 278
282 case YV12: 279 case YV12:
283 if (plane == kYPlane) 280 if (plane == kYPlane)
284 return height; 281 return height;
285 return RoundUp(height, 2) / 2; 282 return base::bits::RoundUp(height, 2) / 2;
286 283
287 default: 284 default:
288 break; 285 break;
289 } 286 }
290 287
291 // Intentionally leave out non-production formats. 288 // Intentionally leave out non-production formats.
292 NOTREACHED() << "Unsupported video frame format: " << format_; 289 NOTREACHED() << "Unsupported video frame format: " << format_;
293 return 0; 290 return 0;
294 } 291 }
295 292
(...skipping 22 matching lines...) Expand all
318 break; 315 break;
319 for(int row = 0; row < rows(plane); row++) { 316 for(int row = 0; row < rows(plane); row++) {
320 base::MD5Update(context, base::StringPiece( 317 base::MD5Update(context, base::StringPiece(
321 reinterpret_cast<char*>(data(plane) + stride(plane) * row), 318 reinterpret_cast<char*>(data(plane) + stride(plane) * row),
322 row_bytes(plane))); 319 row_bytes(plane)));
323 } 320 }
324 } 321 }
325 } 322 }
326 323
327 } // namespace media 324 } // namespace media
OLDNEW
« cc/texture_uploader_unittest.cc ('K') | « cc/video_layer_impl.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698