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

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

Issue 10824141: Remove VideoDecoder::natural_size() & added VideoFrame::natural_size(). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Minor cleanup Created 8 years, 4 months 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
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/logging.h" 7 #include "base/logging.h"
8 #include "base/string_piece.h" 8 #include "base/string_piece.h"
9 #include "media/base/limits.h" 9 #include "media/base/limits.h"
10 #include "media/base/video_util.h" 10 #include "media/base/video_util.h"
11 #if !defined(OS_ANDROID) 11 #if !defined(OS_ANDROID)
12 #include "media/ffmpeg/ffmpeg_common.h" 12 #include "media/ffmpeg/ffmpeg_common.h"
13 #endif 13 #endif
14 14
15 #include <algorithm> 15 #include <algorithm>
16 16
17 namespace media { 17 namespace media {
18 18
19 // static 19 // static
20 scoped_refptr<VideoFrame> VideoFrame::CreateFrame( 20 scoped_refptr<VideoFrame> VideoFrame::CreateFrame(
21 VideoFrame::Format format, 21 VideoFrame::Format format,
22 size_t width, 22 const gfx::Size& size,
23 size_t height, 23 const gfx::Size& natural_size,
24 base::TimeDelta timestamp) { 24 base::TimeDelta timestamp) {
25 DCHECK(IsValidConfig(format, width, height)); 25 DCHECK(IsValidConfig(format, size));
26 scoped_refptr<VideoFrame> frame(new VideoFrame( 26 scoped_refptr<VideoFrame> frame(new VideoFrame(
27 format, width, height, timestamp)); 27 format, size, natural_size, timestamp));
28 switch (format) { 28 switch (format) {
29 case VideoFrame::RGB32: 29 case VideoFrame::RGB32:
30 frame->AllocateRGB(4u); 30 frame->AllocateRGB(4u);
31 break; 31 break;
32 case VideoFrame::YV12: 32 case VideoFrame::YV12:
33 case VideoFrame::YV16: 33 case VideoFrame::YV16:
34 frame->AllocateYUV(); 34 frame->AllocateYUV();
35 break; 35 break;
36 default: 36 default:
37 LOG(FATAL) << "Unsupported frame format: " << format; 37 LOG(FATAL) << "Unsupported frame format: " << format;
38 } 38 }
39 return frame; 39 return frame;
40 } 40 }
41 41
42 // static 42 // static
43 bool VideoFrame::IsValidConfig( 43 bool VideoFrame::IsValidConfig(VideoFrame::Format format,
44 VideoFrame::Format format, 44 const gfx::Size& size) {
Ami GONE FROM CHROMIUM 2012/08/02 17:34:45 shouldn't this now also inspect natural_size?
acolwell GONE FROM CHROMIUM 2012/08/02 20:20:21 Done.
45 size_t width,
46 size_t height) {
47
48 return (format != VideoFrame::INVALID && 45 return (format != VideoFrame::INVALID &&
49 width > 0 && height > 0 && 46 size.width() > 0 && size.height() > 0 &&
50 width <= limits::kMaxDimension && height <= limits::kMaxDimension && 47 size.width() <= limits::kMaxDimension &&
51 width * height <= limits::kMaxCanvas); 48 size.height() <= limits::kMaxDimension &&
49 size.width() * size.height() <= limits::kMaxCanvas);
52 } 50 }
53 51
54 // static 52 // static
55 scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture( 53 scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture(
56 uint32 texture_id, 54 uint32 texture_id,
57 uint32 texture_target, 55 uint32 texture_target,
58 size_t width, 56 const gfx::Size& size,
59 size_t height, 57 const gfx::Size& natural_size,
60 base::TimeDelta timestamp, 58 base::TimeDelta timestamp,
61 const base::Closure& no_longer_needed) { 59 const base::Closure& no_longer_needed) {
62 scoped_refptr<VideoFrame> frame( 60 scoped_refptr<VideoFrame> frame(
63 new VideoFrame(NATIVE_TEXTURE, width, height, timestamp)); 61 new VideoFrame(NATIVE_TEXTURE, size, natural_size, timestamp));
64 frame->texture_id_ = texture_id; 62 frame->texture_id_ = texture_id;
65 frame->texture_target_ = texture_target; 63 frame->texture_target_ = texture_target;
66 frame->texture_no_longer_needed_ = no_longer_needed; 64 frame->texture_no_longer_needed_ = no_longer_needed;
67 return frame; 65 return frame;
68 } 66 }
69 67
70 // static 68 // static
71 scoped_refptr<VideoFrame> VideoFrame::CreateEmptyFrame() { 69 scoped_refptr<VideoFrame> VideoFrame::CreateEmptyFrame() {
72 return new VideoFrame( 70 return new VideoFrame(
73 VideoFrame::EMPTY, 0, 0, base::TimeDelta()); 71 VideoFrame::EMPTY, gfx::Size(), gfx::Size(), base::TimeDelta());
74 } 72 }
75 73
76 // static 74 // static
77 scoped_refptr<VideoFrame> VideoFrame::CreateBlackFrame(int width, int height) { 75 scoped_refptr<VideoFrame> VideoFrame::CreateBlackFrame(const gfx::Size& size) {
78 DCHECK_GT(width, 0); 76 DCHECK(IsValidConfig(VideoFrame::YV12, size));
79 DCHECK_GT(height, 0);
80 77
81 // Create our frame. 78 // Create our frame.
82 const base::TimeDelta kZero; 79 const base::TimeDelta kZero;
83 scoped_refptr<VideoFrame> frame = 80 scoped_refptr<VideoFrame> frame =
84 VideoFrame::CreateFrame(VideoFrame::YV12, width, height, kZero); 81 VideoFrame::CreateFrame(VideoFrame::YV12, size, size, kZero);
85 82
86 // Now set the data to YUV(0,128,128). 83 // Now set the data to YUV(0,128,128).
87 const uint8 kBlackY = 0x00; 84 const uint8 kBlackY = 0x00;
88 const uint8 kBlackUV = 0x80; 85 const uint8 kBlackUV = 0x80;
89 FillYUV(frame, kBlackY, kBlackUV, kBlackUV); 86 FillYUV(frame, kBlackY, kBlackUV, kBlackUV);
90 return frame; 87 return frame;
91 } 88 }
92 89
93 static inline size_t RoundUp(size_t value, size_t alignment) { 90 static inline size_t RoundUp(size_t value, size_t alignment) {
94 // Check that |alignment| is a power of 2. 91 // Check that |alignment| is a power of 2.
95 DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1))); 92 DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
96 return ((value + (alignment - 1)) & ~(alignment-1)); 93 return ((value + (alignment - 1)) & ~(alignment-1));
97 } 94 }
98 95
99 static const int kFrameSizeAlignment = 16; 96 static const int kFrameSizeAlignment = 16;
100 // Allows faster SIMD YUV convert. Also, FFmpeg overreads/-writes occasionally. 97 // Allows faster SIMD YUV convert. Also, FFmpeg overreads/-writes occasionally.
101 static const int kFramePadBytes = 15; 98 static const int kFramePadBytes = 15;
102 99
103 void VideoFrame::AllocateRGB(size_t bytes_per_pixel) { 100 void VideoFrame::AllocateRGB(size_t bytes_per_pixel) {
104 // Round up to align at least at a 16-byte boundary for each row. 101 // Round up to align at least at a 16-byte boundary for each row.
105 // This is sufficient for MMX and SSE2 reads (movq/movdqa). 102 // This is sufficient for MMX and SSE2 reads (movq/movdqa).
106 size_t bytes_per_row = RoundUp(width_, kFrameSizeAlignment) * bytes_per_pixel; 103 size_t bytes_per_row = RoundUp(size_.width(),
107 size_t aligned_height = RoundUp(height_, kFrameSizeAlignment); 104 kFrameSizeAlignment) * bytes_per_pixel;
105 size_t aligned_height = RoundUp(size_.height(), kFrameSizeAlignment);
108 strides_[VideoFrame::kRGBPlane] = bytes_per_row; 106 strides_[VideoFrame::kRGBPlane] = bytes_per_row;
109 #if !defined(OS_ANDROID) 107 #if !defined(OS_ANDROID)
110 // TODO(dalecurtis): use DataAligned or so, so this #ifdef hackery 108 // TODO(dalecurtis): use DataAligned or so, so this #ifdef hackery
111 // doesn't need to be repeated in every single user of aligned data. 109 // doesn't need to be repeated in every single user of aligned data.
112 data_[VideoFrame::kRGBPlane] = reinterpret_cast<uint8*>( 110 data_[VideoFrame::kRGBPlane] = reinterpret_cast<uint8*>(
113 av_malloc(bytes_per_row * aligned_height + kFramePadBytes)); 111 av_malloc(bytes_per_row * aligned_height + kFramePadBytes));
114 #else 112 #else
115 data_[VideoFrame::kRGBPlane] = new uint8_t[bytes_per_row * aligned_height]; 113 data_[VideoFrame::kRGBPlane] = new uint8_t[bytes_per_row * aligned_height];
116 #endif 114 #endif
117 DCHECK(!(reinterpret_cast<intptr_t>(data_[VideoFrame::kRGBPlane]) & 7)); 115 DCHECK(!(reinterpret_cast<intptr_t>(data_[VideoFrame::kRGBPlane]) & 7));
(...skipping 11 matching lines...) Expand all
129 // number to avoid any potential of faulting by code that attempts to access 127 // number to avoid any potential of faulting by code that attempts to access
130 // the Y values of the final row, but assumes that the last row of U & V 128 // the Y values of the final row, but assumes that the last row of U & V
131 // applies to a full two rows of Y. 129 // applies to a full two rows of Y.
132 size_t y_stride = RoundUp(row_bytes(VideoFrame::kYPlane), 130 size_t y_stride = RoundUp(row_bytes(VideoFrame::kYPlane),
133 kFrameSizeAlignment); 131 kFrameSizeAlignment);
134 size_t uv_stride = RoundUp(row_bytes(VideoFrame::kUPlane), 132 size_t uv_stride = RoundUp(row_bytes(VideoFrame::kUPlane),
135 kFrameSizeAlignment); 133 kFrameSizeAlignment);
136 // The *2 here is because some formats (e.g. h264) allow interlaced coding, 134 // The *2 here is because some formats (e.g. h264) allow interlaced coding,
137 // and then the size needs to be a multiple of two macroblocks (vertically). 135 // and then the size needs to be a multiple of two macroblocks (vertically).
138 // See libavcodec/utils.c:avcodec_align_dimensions2(). 136 // See libavcodec/utils.c:avcodec_align_dimensions2().
139 size_t y_height = RoundUp(height_, kFrameSizeAlignment * 2); 137 size_t y_height = RoundUp(size_.height(), kFrameSizeAlignment * 2);
140 size_t uv_height = format_ == VideoFrame::YV12 ? y_height / 2 : y_height; 138 size_t uv_height = format_ == VideoFrame::YV12 ? y_height / 2 : y_height;
141 size_t y_bytes = y_height * y_stride; 139 size_t y_bytes = y_height * y_stride;
142 size_t uv_bytes = uv_height * uv_stride; 140 size_t uv_bytes = uv_height * uv_stride;
143 141
144 #if !defined(OS_ANDROID) 142 #if !defined(OS_ANDROID)
145 // TODO(dalecurtis): use DataAligned or so, so this #ifdef hackery 143 // TODO(dalecurtis): use DataAligned or so, so this #ifdef hackery
146 // doesn't need to be repeated in every single user of aligned data. 144 // doesn't need to be repeated in every single user of aligned data.
147 // The extra line of UV being allocated is because h264 chroma MC 145 // The extra line of UV being allocated is because h264 chroma MC
148 // overreads by one line in some cases, see libavcodec/utils.c: 146 // overreads by one line in some cases, see libavcodec/utils.c:
149 // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm: 147 // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm:
150 // put_h264_chroma_mc4_ssse3(). 148 // put_h264_chroma_mc4_ssse3().
151 uint8* data = reinterpret_cast<uint8*>( 149 uint8* data = reinterpret_cast<uint8*>(
152 av_malloc(y_bytes + (uv_bytes * 2 + uv_stride) + kFramePadBytes)); 150 av_malloc(y_bytes + (uv_bytes * 2 + uv_stride) + kFramePadBytes));
153 #else 151 #else
154 uint8* data = new uint8_t[y_bytes + (uv_bytes * 2)]; 152 uint8* data = new uint8_t[y_bytes + (uv_bytes * 2)];
155 #endif 153 #endif
156 COMPILE_ASSERT(0 == VideoFrame::kYPlane, y_plane_data_must_be_index_0); 154 COMPILE_ASSERT(0 == VideoFrame::kYPlane, y_plane_data_must_be_index_0);
157 data_[VideoFrame::kYPlane] = data; 155 data_[VideoFrame::kYPlane] = data;
158 data_[VideoFrame::kUPlane] = data + y_bytes; 156 data_[VideoFrame::kUPlane] = data + y_bytes;
159 data_[VideoFrame::kVPlane] = data + y_bytes + uv_bytes; 157 data_[VideoFrame::kVPlane] = data + y_bytes + uv_bytes;
160 strides_[VideoFrame::kYPlane] = y_stride; 158 strides_[VideoFrame::kYPlane] = y_stride;
161 strides_[VideoFrame::kUPlane] = uv_stride; 159 strides_[VideoFrame::kUPlane] = uv_stride;
162 strides_[VideoFrame::kVPlane] = uv_stride; 160 strides_[VideoFrame::kVPlane] = uv_stride;
163 } 161 }
164 162
165 VideoFrame::VideoFrame(VideoFrame::Format format, 163 VideoFrame::VideoFrame(VideoFrame::Format format,
166 size_t width, 164 const gfx::Size& size,
167 size_t height, 165 const gfx::Size& natural_size,
168 base::TimeDelta timestamp) 166 base::TimeDelta timestamp)
169 : format_(format), 167 : format_(format),
170 width_(width), 168 size_(size),
171 height_(height), 169 natural_size_(natural_size),
172 texture_id_(0), 170 texture_id_(0),
173 texture_target_(0), 171 texture_target_(0),
174 timestamp_(timestamp) { 172 timestamp_(timestamp) {
175 memset(&strides_, 0, sizeof(strides_)); 173 memset(&strides_, 0, sizeof(strides_));
176 memset(&data_, 0, sizeof(data_)); 174 memset(&data_, 0, sizeof(data_));
177 } 175 }
178 176
179 VideoFrame::~VideoFrame() { 177 VideoFrame::~VideoFrame() {
180 if (format_ == NATIVE_TEXTURE && !texture_no_longer_needed_.is_null()) { 178 if (format_ == NATIVE_TEXTURE && !texture_no_longer_needed_.is_null()) {
181 texture_no_longer_needed_.Run(); 179 texture_no_longer_needed_.Run();
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 return false; 214 return false;
217 } 215 }
218 216
219 int VideoFrame::stride(size_t plane) const { 217 int VideoFrame::stride(size_t plane) const {
220 DCHECK(IsValidPlane(plane)); 218 DCHECK(IsValidPlane(plane));
221 return strides_[plane]; 219 return strides_[plane];
222 } 220 }
223 221
224 int VideoFrame::row_bytes(size_t plane) const { 222 int VideoFrame::row_bytes(size_t plane) const {
225 DCHECK(IsValidPlane(plane)); 223 DCHECK(IsValidPlane(plane));
224 int width = size_.width();
226 switch (format_) { 225 switch (format_) {
227 // 32bpp. 226 // 32bpp.
228 case RGB32: 227 case RGB32:
229 return width_ * 4; 228 return width * 4;
230 229
231 // Planar, 8bpp. 230 // Planar, 8bpp.
232 case YV12: 231 case YV12:
233 case YV16: 232 case YV16:
234 if (plane == kYPlane) 233 if (plane == kYPlane)
235 return width_; 234 return width;
236 return RoundUp(width_, 2) / 2; 235 return RoundUp(width, 2) / 2;
237 236
238 default: 237 default:
239 break; 238 break;
240 } 239 }
241 240
242 // Intentionally leave out non-production formats. 241 // Intentionally leave out non-production formats.
243 NOTREACHED() << "Unsupported video frame format: " << format_; 242 NOTREACHED() << "Unsupported video frame format: " << format_;
244 return 0; 243 return 0;
245 } 244 }
246 245
247 int VideoFrame::rows(size_t plane) const { 246 int VideoFrame::rows(size_t plane) const {
248 DCHECK(IsValidPlane(plane)); 247 DCHECK(IsValidPlane(plane));
248 int height = size_.height();
249 switch (format_) { 249 switch (format_) {
250 case RGB32: 250 case RGB32:
251 case YV16: 251 case YV16:
252 return height_; 252 return height;
253 253
254 case YV12: 254 case YV12:
255 if (plane == kYPlane) 255 if (plane == kYPlane)
256 return height_; 256 return height;
257 return RoundUp(height_, 2) / 2; 257 return RoundUp(height, 2) / 2;
258 258
259 default: 259 default:
260 break; 260 break;
261 } 261 }
262 262
263 // Intentionally leave out non-production formats. 263 // Intentionally leave out non-production formats.
264 NOTREACHED() << "Unsupported video frame format: " << format_; 264 NOTREACHED() << "Unsupported video frame format: " << format_;
265 return 0; 265 return 0;
266 } 266 }
267 267
(...skipping 22 matching lines...) Expand all
290 break; 290 break;
291 for(int row = 0; row < rows(plane); row++) { 291 for(int row = 0; row < rows(plane); row++) {
292 base::MD5Update(context, base::StringPiece( 292 base::MD5Update(context, base::StringPiece(
293 reinterpret_cast<char*>(data(plane) + stride(plane) * row), 293 reinterpret_cast<char*>(data(plane) + stride(plane) * row),
294 row_bytes(plane))); 294 row_bytes(plane)));
295 } 295 }
296 } 296 }
297 } 297 }
298 298
299 } // namespace media 299 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698