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

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: Fix copyright year. 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
« no previous file with comments | « media/base/video_frame.h ('k') | media/base/video_frame_unittest.cc » ('j') | 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/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& data_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, data_size, natural_size));
26 scoped_refptr<VideoFrame> frame(new VideoFrame( 26 scoped_refptr<VideoFrame> frame(new VideoFrame(
27 format, width, height, timestamp)); 27 format, data_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& data_size,
45 size_t width, 45 const gfx::Size& natural_size) {
46 size_t height) {
47
48 return (format != VideoFrame::INVALID && 46 return (format != VideoFrame::INVALID &&
49 width > 0 && height > 0 && 47 data_size.width() > 0 && data_size.height() > 0 &&
50 width <= limits::kMaxDimension && height <= limits::kMaxDimension && 48 data_size.width() <= limits::kMaxDimension &&
51 width * height <= limits::kMaxCanvas); 49 data_size.height() <= limits::kMaxDimension &&
50 data_size.width() * data_size.height() <= limits::kMaxCanvas &&
51 natural_size.width() > 0 && natural_size.height() > 0 &&
52 natural_size.width() <= limits::kMaxDimension &&
53 natural_size.height() <= limits::kMaxDimension &&
54 natural_size.width() * natural_size.height() <= limits::kMaxCanvas);
52 } 55 }
53 56
54 // static 57 // static
55 scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture( 58 scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture(
56 uint32 texture_id, 59 uint32 texture_id,
57 uint32 texture_target, 60 uint32 texture_target,
58 size_t width, 61 const gfx::Size& data_size,
59 size_t height, 62 const gfx::Size& natural_size,
60 base::TimeDelta timestamp, 63 base::TimeDelta timestamp,
61 const base::Closure& no_longer_needed) { 64 const base::Closure& no_longer_needed) {
62 scoped_refptr<VideoFrame> frame( 65 scoped_refptr<VideoFrame> frame(
63 new VideoFrame(NATIVE_TEXTURE, width, height, timestamp)); 66 new VideoFrame(NATIVE_TEXTURE, data_size, natural_size, timestamp));
64 frame->texture_id_ = texture_id; 67 frame->texture_id_ = texture_id;
65 frame->texture_target_ = texture_target; 68 frame->texture_target_ = texture_target;
66 frame->texture_no_longer_needed_ = no_longer_needed; 69 frame->texture_no_longer_needed_ = no_longer_needed;
67 return frame; 70 return frame;
68 } 71 }
69 72
70 // static 73 // static
71 scoped_refptr<VideoFrame> VideoFrame::CreateEmptyFrame() { 74 scoped_refptr<VideoFrame> VideoFrame::CreateEmptyFrame() {
72 return new VideoFrame( 75 return new VideoFrame(
73 VideoFrame::EMPTY, 0, 0, base::TimeDelta()); 76 VideoFrame::EMPTY, gfx::Size(), gfx::Size(), base::TimeDelta());
74 } 77 }
75 78
76 // static 79 // static
77 scoped_refptr<VideoFrame> VideoFrame::CreateBlackFrame(int width, int height) { 80 scoped_refptr<VideoFrame> VideoFrame::CreateBlackFrame(
78 DCHECK_GT(width, 0); 81 const gfx::Size& data_size) {
79 DCHECK_GT(height, 0); 82 DCHECK(IsValidConfig(VideoFrame::YV12, data_size, data_size));
80 83
81 // Create our frame. 84 // Create our frame.
82 const base::TimeDelta kZero; 85 const base::TimeDelta kZero;
83 scoped_refptr<VideoFrame> frame = 86 scoped_refptr<VideoFrame> frame =
84 VideoFrame::CreateFrame(VideoFrame::YV12, width, height, kZero); 87 VideoFrame::CreateFrame(VideoFrame::YV12, data_size, data_size, kZero);
85 88
86 // Now set the data to YUV(0,128,128). 89 // Now set the data to YUV(0,128,128).
87 const uint8 kBlackY = 0x00; 90 const uint8 kBlackY = 0x00;
88 const uint8 kBlackUV = 0x80; 91 const uint8 kBlackUV = 0x80;
89 FillYUV(frame, kBlackY, kBlackUV, kBlackUV); 92 FillYUV(frame, kBlackY, kBlackUV, kBlackUV);
90 return frame; 93 return frame;
91 } 94 }
92 95
93 static inline size_t RoundUp(size_t value, size_t alignment) { 96 static inline size_t RoundUp(size_t value, size_t alignment) {
94 // Check that |alignment| is a power of 2. 97 // Check that |alignment| is a power of 2.
95 DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1))); 98 DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
96 return ((value + (alignment - 1)) & ~(alignment-1)); 99 return ((value + (alignment - 1)) & ~(alignment-1));
97 } 100 }
98 101
99 static const int kFrameSizeAlignment = 16; 102 static const int kFrameSizeAlignment = 16;
100 // Allows faster SIMD YUV convert. Also, FFmpeg overreads/-writes occasionally. 103 // Allows faster SIMD YUV convert. Also, FFmpeg overreads/-writes occasionally.
101 static const int kFramePadBytes = 15; 104 static const int kFramePadBytes = 15;
102 105
103 void VideoFrame::AllocateRGB(size_t bytes_per_pixel) { 106 void VideoFrame::AllocateRGB(size_t bytes_per_pixel) {
104 // Round up to align at least at a 16-byte boundary for each row. 107 // 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). 108 // This is sufficient for MMX and SSE2 reads (movq/movdqa).
106 size_t bytes_per_row = RoundUp(width_, kFrameSizeAlignment) * bytes_per_pixel; 109 size_t bytes_per_row = RoundUp(data_size_.width(),
107 size_t aligned_height = RoundUp(height_, kFrameSizeAlignment); 110 kFrameSizeAlignment) * bytes_per_pixel;
111 size_t aligned_height = RoundUp(data_size_.height(), kFrameSizeAlignment);
108 strides_[VideoFrame::kRGBPlane] = bytes_per_row; 112 strides_[VideoFrame::kRGBPlane] = bytes_per_row;
109 #if !defined(OS_ANDROID) 113 #if !defined(OS_ANDROID)
110 // TODO(dalecurtis): use DataAligned or so, so this #ifdef hackery 114 // TODO(dalecurtis): use DataAligned or so, so this #ifdef hackery
111 // doesn't need to be repeated in every single user of aligned data. 115 // doesn't need to be repeated in every single user of aligned data.
112 data_[VideoFrame::kRGBPlane] = reinterpret_cast<uint8*>( 116 data_[VideoFrame::kRGBPlane] = reinterpret_cast<uint8*>(
113 av_malloc(bytes_per_row * aligned_height + kFramePadBytes)); 117 av_malloc(bytes_per_row * aligned_height + kFramePadBytes));
114 #else 118 #else
115 data_[VideoFrame::kRGBPlane] = new uint8_t[bytes_per_row * aligned_height]; 119 data_[VideoFrame::kRGBPlane] = new uint8_t[bytes_per_row * aligned_height];
116 #endif 120 #endif
117 DCHECK(!(reinterpret_cast<intptr_t>(data_[VideoFrame::kRGBPlane]) & 7)); 121 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 133 // 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 134 // 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. 135 // applies to a full two rows of Y.
132 size_t y_stride = RoundUp(row_bytes(VideoFrame::kYPlane), 136 size_t y_stride = RoundUp(row_bytes(VideoFrame::kYPlane),
133 kFrameSizeAlignment); 137 kFrameSizeAlignment);
134 size_t uv_stride = RoundUp(row_bytes(VideoFrame::kUPlane), 138 size_t uv_stride = RoundUp(row_bytes(VideoFrame::kUPlane),
135 kFrameSizeAlignment); 139 kFrameSizeAlignment);
136 // The *2 here is because some formats (e.g. h264) allow interlaced coding, 140 // 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). 141 // and then the size needs to be a multiple of two macroblocks (vertically).
138 // See libavcodec/utils.c:avcodec_align_dimensions2(). 142 // See libavcodec/utils.c:avcodec_align_dimensions2().
139 size_t y_height = RoundUp(height_, kFrameSizeAlignment * 2); 143 size_t y_height = RoundUp(data_size_.height(), kFrameSizeAlignment * 2);
140 size_t uv_height = format_ == VideoFrame::YV12 ? y_height / 2 : y_height; 144 size_t uv_height = format_ == VideoFrame::YV12 ? y_height / 2 : y_height;
141 size_t y_bytes = y_height * y_stride; 145 size_t y_bytes = y_height * y_stride;
142 size_t uv_bytes = uv_height * uv_stride; 146 size_t uv_bytes = uv_height * uv_stride;
143 147
144 #if !defined(OS_ANDROID) 148 #if !defined(OS_ANDROID)
145 // TODO(dalecurtis): use DataAligned or so, so this #ifdef hackery 149 // TODO(dalecurtis): use DataAligned or so, so this #ifdef hackery
146 // doesn't need to be repeated in every single user of aligned data. 150 // 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 151 // The extra line of UV being allocated is because h264 chroma MC
148 // overreads by one line in some cases, see libavcodec/utils.c: 152 // overreads by one line in some cases, see libavcodec/utils.c:
149 // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm: 153 // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm:
150 // put_h264_chroma_mc4_ssse3(). 154 // put_h264_chroma_mc4_ssse3().
151 uint8* data = reinterpret_cast<uint8*>( 155 uint8* data = reinterpret_cast<uint8*>(
152 av_malloc(y_bytes + (uv_bytes * 2 + uv_stride) + kFramePadBytes)); 156 av_malloc(y_bytes + (uv_bytes * 2 + uv_stride) + kFramePadBytes));
153 #else 157 #else
154 uint8* data = new uint8_t[y_bytes + (uv_bytes * 2)]; 158 uint8* data = new uint8_t[y_bytes + (uv_bytes * 2)];
155 #endif 159 #endif
156 COMPILE_ASSERT(0 == VideoFrame::kYPlane, y_plane_data_must_be_index_0); 160 COMPILE_ASSERT(0 == VideoFrame::kYPlane, y_plane_data_must_be_index_0);
157 data_[VideoFrame::kYPlane] = data; 161 data_[VideoFrame::kYPlane] = data;
158 data_[VideoFrame::kUPlane] = data + y_bytes; 162 data_[VideoFrame::kUPlane] = data + y_bytes;
159 data_[VideoFrame::kVPlane] = data + y_bytes + uv_bytes; 163 data_[VideoFrame::kVPlane] = data + y_bytes + uv_bytes;
160 strides_[VideoFrame::kYPlane] = y_stride; 164 strides_[VideoFrame::kYPlane] = y_stride;
161 strides_[VideoFrame::kUPlane] = uv_stride; 165 strides_[VideoFrame::kUPlane] = uv_stride;
162 strides_[VideoFrame::kVPlane] = uv_stride; 166 strides_[VideoFrame::kVPlane] = uv_stride;
163 } 167 }
164 168
165 VideoFrame::VideoFrame(VideoFrame::Format format, 169 VideoFrame::VideoFrame(VideoFrame::Format format,
166 size_t width, 170 const gfx::Size& data_size,
167 size_t height, 171 const gfx::Size& natural_size,
168 base::TimeDelta timestamp) 172 base::TimeDelta timestamp)
169 : format_(format), 173 : format_(format),
170 width_(width), 174 data_size_(data_size),
171 height_(height), 175 natural_size_(natural_size),
172 texture_id_(0), 176 texture_id_(0),
173 texture_target_(0), 177 texture_target_(0),
174 timestamp_(timestamp) { 178 timestamp_(timestamp) {
175 memset(&strides_, 0, sizeof(strides_)); 179 memset(&strides_, 0, sizeof(strides_));
176 memset(&data_, 0, sizeof(data_)); 180 memset(&data_, 0, sizeof(data_));
177 } 181 }
178 182
179 VideoFrame::~VideoFrame() { 183 VideoFrame::~VideoFrame() {
180 if (format_ == NATIVE_TEXTURE && !texture_no_longer_needed_.is_null()) { 184 if (format_ == NATIVE_TEXTURE && !texture_no_longer_needed_.is_null()) {
181 texture_no_longer_needed_.Run(); 185 texture_no_longer_needed_.Run();
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 return false; 220 return false;
217 } 221 }
218 222
219 int VideoFrame::stride(size_t plane) const { 223 int VideoFrame::stride(size_t plane) const {
220 DCHECK(IsValidPlane(plane)); 224 DCHECK(IsValidPlane(plane));
221 return strides_[plane]; 225 return strides_[plane];
222 } 226 }
223 227
224 int VideoFrame::row_bytes(size_t plane) const { 228 int VideoFrame::row_bytes(size_t plane) const {
225 DCHECK(IsValidPlane(plane)); 229 DCHECK(IsValidPlane(plane));
230 int width = data_size_.width();
226 switch (format_) { 231 switch (format_) {
227 // 32bpp. 232 // 32bpp.
228 case RGB32: 233 case RGB32:
229 return width_ * 4; 234 return width * 4;
230 235
231 // Planar, 8bpp. 236 // Planar, 8bpp.
232 case YV12: 237 case YV12:
233 case YV16: 238 case YV16:
234 if (plane == kYPlane) 239 if (plane == kYPlane)
235 return width_; 240 return width;
236 return RoundUp(width_, 2) / 2; 241 return RoundUp(width, 2) / 2;
237 242
238 default: 243 default:
239 break; 244 break;
240 } 245 }
241 246
242 // Intentionally leave out non-production formats. 247 // Intentionally leave out non-production formats.
243 NOTREACHED() << "Unsupported video frame format: " << format_; 248 NOTREACHED() << "Unsupported video frame format: " << format_;
244 return 0; 249 return 0;
245 } 250 }
246 251
247 int VideoFrame::rows(size_t plane) const { 252 int VideoFrame::rows(size_t plane) const {
248 DCHECK(IsValidPlane(plane)); 253 DCHECK(IsValidPlane(plane));
254 int height = data_size_.height();
249 switch (format_) { 255 switch (format_) {
250 case RGB32: 256 case RGB32:
251 case YV16: 257 case YV16:
252 return height_; 258 return height;
253 259
254 case YV12: 260 case YV12:
255 if (plane == kYPlane) 261 if (plane == kYPlane)
256 return height_; 262 return height;
257 return RoundUp(height_, 2) / 2; 263 return RoundUp(height, 2) / 2;
258 264
259 default: 265 default:
260 break; 266 break;
261 } 267 }
262 268
263 // Intentionally leave out non-production formats. 269 // Intentionally leave out non-production formats.
264 NOTREACHED() << "Unsupported video frame format: " << format_; 270 NOTREACHED() << "Unsupported video frame format: " << format_;
265 return 0; 271 return 0;
266 } 272 }
267 273
(...skipping 22 matching lines...) Expand all
290 break; 296 break;
291 for(int row = 0; row < rows(plane); row++) { 297 for(int row = 0; row < rows(plane); row++) {
292 base::MD5Update(context, base::StringPiece( 298 base::MD5Update(context, base::StringPiece(
293 reinterpret_cast<char*>(data(plane) + stride(plane) * row), 299 reinterpret_cast<char*>(data(plane) + stride(plane) * row),
294 row_bytes(plane))); 300 row_bytes(plane)));
295 } 301 }
296 } 302 }
297 } 303 }
298 304
299 } // namespace media 305 } // namespace media
OLDNEW
« no previous file with comments | « media/base/video_frame.h ('k') | media/base/video_frame_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698