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

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

Issue 1154153003: Relanding 1143663007: VideoFrame: Separate Pixel Format from Storage Type. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added NV12 support in CrOS Created 5 years, 6 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
« 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 <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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 switch (format) { 46 switch (format) {
47 case VideoFrame::YV24: 47 case VideoFrame::YV24:
48 return gfx::Size(1, 1); 48 return gfx::Size(1, 1);
49 49
50 case VideoFrame::YV16: 50 case VideoFrame::YV16:
51 return gfx::Size(2, 1); 51 return gfx::Size(2, 1);
52 52
53 case VideoFrame::YV12: 53 case VideoFrame::YV12:
54 case VideoFrame::I420: 54 case VideoFrame::I420:
55 case VideoFrame::YV12A: 55 case VideoFrame::YV12A:
56 #if defined(OS_MACOSX) || defined(OS_CHROMEOS)
56 case VideoFrame::NV12: 57 case VideoFrame::NV12:
58 #endif
57 return gfx::Size(2, 2); 59 return gfx::Size(2, 2);
58 60
59 case VideoFrame::UNKNOWN: 61 case VideoFrame::UNKNOWN:
60 #if defined(VIDEO_HOLE)
61 case VideoFrame::HOLE:
62 #endif // defined(VIDEO_HOLE)
63 case VideoFrame::NATIVE_TEXTURE:
64 case VideoFrame::ARGB: 62 case VideoFrame::ARGB:
63 case VideoFrame::XRGB:
65 break; 64 break;
66 } 65 }
67 } 66 }
68 NOTREACHED(); 67 NOTREACHED();
69 return gfx::Size(); 68 return gfx::Size();
70 } 69 }
71 70
72 // Return the alignment for the whole frame, calculated as the max of the 71 // Return the alignment for the whole frame, calculated as the max of the
73 // alignment for each individual plane. 72 // alignment for each individual plane.
74 static gfx::Size CommonAlignment(VideoFrame::Format format) { 73 static gfx::Size CommonAlignment(VideoFrame::Format format) {
75 int max_sample_width = 0; 74 int max_sample_width = 0;
76 int max_sample_height = 0; 75 int max_sample_height = 0;
77 for (size_t plane = 0; plane < VideoFrame::NumPlanes(format); ++plane) { 76 for (size_t plane = 0; plane < VideoFrame::NumPlanes(format); ++plane) {
78 const gfx::Size sample_size = SampleSize(format, plane); 77 const gfx::Size sample_size = SampleSize(format, plane);
79 max_sample_width = std::max(max_sample_width, sample_size.width()); 78 max_sample_width = std::max(max_sample_width, sample_size.width());
80 max_sample_height = std::max(max_sample_height, sample_size.height()); 79 max_sample_height = std::max(max_sample_height, sample_size.height());
81 } 80 }
82 return gfx::Size(max_sample_width, max_sample_height); 81 return gfx::Size(max_sample_width, max_sample_height);
83 } 82 }
84 83
85 // Returns the number of bytes per element for given |plane| and |format|. E.g. 84 // Returns the number of bytes per element for given |plane| and |format|.
86 // 2 for the UV plane in NV12.
87 static int BytesPerElement(VideoFrame::Format format, size_t plane) { 85 static int BytesPerElement(VideoFrame::Format format, size_t plane) {
88 DCHECK(VideoFrame::IsValidPlane(plane, format)); 86 DCHECK(VideoFrame::IsValidPlane(plane, format));
89 if (format == VideoFrame::ARGB) 87 if (format == VideoFrame::ARGB || format == VideoFrame::XRGB)
90 return 4; 88 return 4;
91
92 if (format == VideoFrame::NV12 && plane == VideoFrame::kUVPlane)
93 return 2;
94
95 return 1; 89 return 1;
96 } 90 }
97 91
98 // Rounds up |coded_size| if necessary for |format|. 92 // Rounds up |coded_size| if necessary for |format|.
99 static gfx::Size AdjustCodedSize(VideoFrame::Format format, 93 static gfx::Size AdjustCodedSize(VideoFrame::Format format,
100 const gfx::Size& coded_size) { 94 const gfx::Size& coded_size) {
101 const gfx::Size alignment = CommonAlignment(format); 95 const gfx::Size alignment = CommonAlignment(format);
102 return gfx::Size(RoundUp(coded_size.width(), alignment.width()), 96 return gfx::Size(RoundUp(coded_size.width(), alignment.width()),
103 RoundUp(coded_size.height(), alignment.height())); 97 RoundUp(coded_size.height(), alignment.height()));
104 } 98 }
105 99
106 // static 100 // Release data allocated by AllocateYUV().
107 scoped_refptr<VideoFrame> VideoFrame::CreateFrame( 101 static void ReleaseData(uint8* data) {
108 VideoFrame::Format format, 102 DCHECK(data);
109 const gfx::Size& coded_size, 103 base::AlignedFree(data);
110 const gfx::Rect& visible_rect, 104 }
111 const gfx::Size& natural_size, 105
112 base::TimeDelta timestamp) { 106 //static
107 bool VideoFrame::IsYuvPlanar(Format format) {
113 switch (format) { 108 switch (format) {
114 case VideoFrame::YV12: 109 case YV12:
115 case VideoFrame::YV16: 110 case I420:
116 case VideoFrame::I420: 111 case YV16:
117 case VideoFrame::YV12A: 112 case YV12A:
118 case VideoFrame::YV24: 113 case YV24:
119 break; 114 return true;
115 #if defined(OS_MACOSX) || defined(OS_CHROMEOS)
116 case NV12:
117 #endif
118 case UNKNOWN:
119 case ARGB:
120 case XRGB:
121 return false;
122 }
123 return false;
124 }
120 125
121 case VideoFrame::UNKNOWN: 126 //static
122 case VideoFrame::NV12: 127 bool VideoFrame::IsMappable(StorageType storage_type) {
123 case VideoFrame::NATIVE_TEXTURE: 128 return storage_type == STORAGE_SHMEM ||
124 #if defined(VIDEO_HOLE) 129 storage_type == STORAGE_OWNED_MEMORY ||
125 case VideoFrame::HOLE: 130 storage_type == STORAGE_UNOWNED_MEMORY;
126 #endif // defined(VIDEO_HOLE)
127 case VideoFrame::ARGB:
128 NOTIMPLEMENTED();
129 return nullptr;
130 }
131
132 // Since we're creating a new YUV frame (and allocating memory for it
133 // ourselves), we can pad the requested |coded_size| if necessary if the
134 // request does not line up on sample boundaries.
135 const gfx::Size new_coded_size = AdjustCodedSize(format, coded_size);
136 DCHECK(IsValidConfig(format, new_coded_size, visible_rect, natural_size));
137
138 gpu::MailboxHolder mailboxes[kMaxPlanes];
139 scoped_refptr<VideoFrame> frame(
140 new VideoFrame(format, new_coded_size, visible_rect, natural_size,
141 mailboxes, TEXTURE_RGBA, timestamp, false));
142 frame->AllocateYUV();
143 return frame;
144 } 131 }
145 132
146 // static 133 // static
147 std::string VideoFrame::FormatToString(VideoFrame::Format format) { 134 std::string VideoFrame::FormatToString(Format format) {
148 switch (format) { 135 switch (format) {
149 case VideoFrame::UNKNOWN: 136 case UNKNOWN:
150 return "UNKNOWN"; 137 return "UNKNOWN";
151 case VideoFrame::YV12: 138 case YV12:
152 return "YV12"; 139 return "YV12";
153 case VideoFrame::YV16: 140 case YV16:
154 return "YV16"; 141 return "YV16";
155 case VideoFrame::I420: 142 case I420:
156 return "I420"; 143 return "I420";
157 case VideoFrame::NATIVE_TEXTURE: 144 case YV12A:
158 return "NATIVE_TEXTURE";
159 #if defined(VIDEO_HOLE)
160 case VideoFrame::HOLE:
161 return "HOLE";
162 #endif // defined(VIDEO_HOLE)
163 case VideoFrame::YV12A:
164 return "YV12A"; 145 return "YV12A";
165 case VideoFrame::NV12: 146 case YV24:
147 return "YV24";
148 case ARGB:
149 return "ARGB";
150 case XRGB:
151 return "XRGB";
152 #if defined(OS_MACOSX) || defined(OS_CHROMEOS)
153 case NV12:
166 return "NV12"; 154 return "NV12";
167 case VideoFrame::YV24: 155 #endif
168 return "YV24";
169 case VideoFrame::ARGB:
170 return "ARGB";
171 } 156 }
172 NOTREACHED() << "Invalid videoframe format provided: " << format; 157 NOTREACHED() << "Invalid VideoFrame format provided: " << format;
173 return ""; 158 return "";
174 } 159 }
175 160
176 // static 161 // static
177 bool VideoFrame::IsValidConfig(VideoFrame::Format format, 162 bool VideoFrame::IsValidConfig(Format format,
163 StorageType storage_type,
178 const gfx::Size& coded_size, 164 const gfx::Size& coded_size,
179 const gfx::Rect& visible_rect, 165 const gfx::Rect& visible_rect,
180 const gfx::Size& natural_size) { 166 const gfx::Size& natural_size) {
181 // Check maximum limits for all formats. 167 // Check maximum limits for all formats.
182 if (coded_size.GetArea() > limits::kMaxCanvas || 168 if (coded_size.GetArea() > limits::kMaxCanvas ||
183 coded_size.width() > limits::kMaxDimension || 169 coded_size.width() > limits::kMaxDimension ||
184 coded_size.height() > limits::kMaxDimension || 170 coded_size.height() > limits::kMaxDimension ||
185 visible_rect.x() < 0 || visible_rect.y() < 0 || 171 visible_rect.x() < 0 || visible_rect.y() < 0 ||
186 visible_rect.right() > coded_size.width() || 172 visible_rect.right() > coded_size.width() ||
187 visible_rect.bottom() > coded_size.height() || 173 visible_rect.bottom() > coded_size.height() ||
188 natural_size.GetArea() > limits::kMaxCanvas || 174 natural_size.GetArea() > limits::kMaxCanvas ||
189 natural_size.width() > limits::kMaxDimension || 175 natural_size.width() > limits::kMaxDimension ||
190 natural_size.height() > limits::kMaxDimension) 176 natural_size.height() > limits::kMaxDimension)
191 return false; 177 return false;
192 178
179 // TODO(mcasas): Remove parameter |storage_type| when STORAGE_HOLE and
180 // STORAGE_TEXTURE comply with the checks below. Right now we skip them.
181 #if defined(VIDEO_HOLE)
182 if (storage_type == STORAGE_HOLE)
183 return true;
184 #endif
185 if(storage_type == STORAGE_TEXTURE)
186 return true;
187
193 // Check format-specific width/height requirements. 188 // Check format-specific width/height requirements.
194 switch (format) { 189 switch (format) {
195 case VideoFrame::UNKNOWN: 190 case UNKNOWN:
196 return (coded_size.IsEmpty() && visible_rect.IsEmpty() && 191 return (coded_size.IsEmpty() && visible_rect.IsEmpty() &&
197 natural_size.IsEmpty()); 192 natural_size.IsEmpty());
198 193 case YV24:
199 // NATIVE_TEXTURE and HOLE have no software-allocated buffers and are 194 case YV12:
200 // allowed to skip the below check. 195 case I420:
201 case VideoFrame::NATIVE_TEXTURE: 196 case YV12A:
202 #if defined(VIDEO_HOLE) 197 case YV16:
203 case VideoFrame::HOLE: 198 case ARGB:
204 #endif // defined(VIDEO_HOLE) 199 case XRGB:
205 return true; 200 #if defined(OS_MACOSX) || defined(OS_CHROMEOS)
206 201 case NV12:
207 case VideoFrame::YV24: 202 #endif
208 case VideoFrame::YV12:
209 case VideoFrame::I420:
210 case VideoFrame::YV12A:
211 case VideoFrame::NV12:
212 case VideoFrame::YV16:
213 case VideoFrame::ARGB:
214 // Check that software-allocated buffer formats are aligned correctly and 203 // Check that software-allocated buffer formats are aligned correctly and
215 // not empty. 204 // not empty.
216 const gfx::Size alignment = CommonAlignment(format); 205 const gfx::Size alignment = CommonAlignment(format);
217 return RoundUp(visible_rect.right(), alignment.width()) <= 206 return RoundUp(visible_rect.right(), alignment.width()) <=
218 static_cast<size_t>(coded_size.width()) && 207 static_cast<size_t>(coded_size.width()) &&
219 RoundUp(visible_rect.bottom(), alignment.height()) <= 208 RoundUp(visible_rect.bottom(), alignment.height()) <=
220 static_cast<size_t>(coded_size.height()) && 209 static_cast<size_t>(coded_size.height()) &&
221 !coded_size.IsEmpty() && !visible_rect.IsEmpty() && 210 !coded_size.IsEmpty() && !visible_rect.IsEmpty() &&
222 !natural_size.IsEmpty(); 211 !natural_size.IsEmpty();
223 } 212 }
224 213
214 // TODO(mcasas): Check that storage type and underlying mailboxes/dataptr are
215 // matching.
225 NOTREACHED(); 216 NOTREACHED();
226 return false; 217 return false;
227 } 218 }
228 219
229 // static 220 // static
221 scoped_refptr<VideoFrame> VideoFrame::CreateFrame(
222 Format format,
223 const gfx::Size& coded_size,
224 const gfx::Rect& visible_rect,
225 const gfx::Size& natural_size,
226 base::TimeDelta timestamp) {
227 if (!IsYuvPlanar(format)) {
228 NOTIMPLEMENTED();
229 return nullptr;
230 }
231
232 // Since we're creating a new YUV frame (and allocating memory for it
233 // ourselves), we can pad the requested |coded_size| if necessary if the
234 // request does not line up on sample boundaries.
235 const gfx::Size new_coded_size = AdjustCodedSize(format, coded_size);
236 DCHECK(IsValidConfig(format, STORAGE_OWNED_MEMORY, new_coded_size,
237 visible_rect, natural_size));
238
239 scoped_refptr<VideoFrame> frame(
240 new VideoFrame(format, STORAGE_OWNED_MEMORY, new_coded_size, visible_rect,
241 natural_size, timestamp, false));
242 frame->AllocateYUV();
243 return frame;
244 }
245
246 // static
230 scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture( 247 scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture(
231 const gpu::MailboxHolder& mailbox_holder, 248 const gpu::MailboxHolder& mailbox_holder,
232 const ReleaseMailboxCB& mailbox_holder_release_cb, 249 const ReleaseMailboxCB& mailbox_holder_release_cb,
233 const gfx::Size& coded_size, 250 const gfx::Size& coded_size,
234 const gfx::Rect& visible_rect, 251 const gfx::Rect& visible_rect,
235 const gfx::Size& natural_size, 252 const gfx::Size& natural_size,
236 base::TimeDelta timestamp, 253 base::TimeDelta timestamp,
237 bool allow_overlay, 254 bool allow_overlay,
238 bool has_alpha) { 255 bool has_alpha) {
239 gpu::MailboxHolder mailbox_holders[kMaxPlanes]; 256 gpu::MailboxHolder mailbox_holders[kMaxPlanes];
240 mailbox_holders[kARGBPlane] = mailbox_holder; 257 mailbox_holders[kARGBPlane] = mailbox_holder;
241 TextureFormat texture_format = has_alpha ? TEXTURE_RGBA : TEXTURE_RGB; 258 Format texture_format = has_alpha ? ARGB : XRGB;
242 scoped_refptr<VideoFrame> frame( 259 scoped_refptr<VideoFrame> frame(
243 new VideoFrame(NATIVE_TEXTURE, coded_size, visible_rect, natural_size, 260 new VideoFrame(texture_format, STORAGE_TEXTURE, coded_size, visible_rect,
244 mailbox_holders, texture_format, timestamp, false)); 261 natural_size, mailbox_holders, timestamp, false));
245 frame->mailbox_holders_release_cb_ = mailbox_holder_release_cb; 262 frame->mailbox_holders_release_cb_ = mailbox_holder_release_cb;
246 frame->allow_overlay_ = allow_overlay; 263 frame->allow_overlay_ = allow_overlay;
247 return frame; 264 return frame;
248 } 265 }
249 266
250 // static 267 // static
251 scoped_refptr<VideoFrame> VideoFrame::WrapYUV420NativeTextures( 268 scoped_refptr<VideoFrame> VideoFrame::WrapYUV420NativeTextures(
252 const gpu::MailboxHolder& y_mailbox_holder, 269 const gpu::MailboxHolder& y_mailbox_holder,
253 const gpu::MailboxHolder& u_mailbox_holder, 270 const gpu::MailboxHolder& u_mailbox_holder,
254 const gpu::MailboxHolder& v_mailbox_holder, 271 const gpu::MailboxHolder& v_mailbox_holder,
255 const ReleaseMailboxCB& mailbox_holder_release_cb, 272 const ReleaseMailboxCB& mailbox_holder_release_cb,
256 const gfx::Size& coded_size, 273 const gfx::Size& coded_size,
257 const gfx::Rect& visible_rect, 274 const gfx::Rect& visible_rect,
258 const gfx::Size& natural_size, 275 const gfx::Size& natural_size,
259 base::TimeDelta timestamp, 276 base::TimeDelta timestamp,
260 bool allow_overlay) { 277 bool allow_overlay) {
261 gpu::MailboxHolder mailbox_holders[kMaxPlanes]; 278 gpu::MailboxHolder mailbox_holders[kMaxPlanes];
262 mailbox_holders[kYPlane] = y_mailbox_holder; 279 mailbox_holders[kYPlane] = y_mailbox_holder;
263 mailbox_holders[kUPlane] = u_mailbox_holder; 280 mailbox_holders[kUPlane] = u_mailbox_holder;
264 mailbox_holders[kVPlane] = v_mailbox_holder; 281 mailbox_holders[kVPlane] = v_mailbox_holder;
265 scoped_refptr<VideoFrame> frame( 282 scoped_refptr<VideoFrame> frame(
266 new VideoFrame(NATIVE_TEXTURE, coded_size, visible_rect, natural_size, 283 new VideoFrame(I420, STORAGE_TEXTURE, coded_size, visible_rect,
267 mailbox_holders, TEXTURE_YUV_420, timestamp, false)); 284 natural_size, mailbox_holders, timestamp, false));
268 frame->mailbox_holders_release_cb_ = mailbox_holder_release_cb; 285 frame->mailbox_holders_release_cb_ = mailbox_holder_release_cb;
269 frame->allow_overlay_ = allow_overlay; 286 frame->allow_overlay_ = allow_overlay;
270 return frame; 287 return frame;
271 } 288 }
272 289
273 // static 290 // static
274 scoped_refptr<VideoFrame> VideoFrame::WrapExternalPackedMemory( 291 scoped_refptr<VideoFrame> VideoFrame::WrapExternalData(
275 Format format, 292 Format format,
276 const gfx::Size& coded_size, 293 const gfx::Size& coded_size,
277 const gfx::Rect& visible_rect, 294 const gfx::Rect& visible_rect,
295 const gfx::Size& natural_size,
296 uint8* data,
297 size_t data_size,
298 base::TimeDelta timestamp) {
299 return WrapExternalStorage(format, STORAGE_UNOWNED_MEMORY, coded_size,
300 visible_rect, natural_size, data, data_size,
301 timestamp, base::SharedMemory::NULLHandle(), 0);
302 }
303
304 // static
305 scoped_refptr<VideoFrame> VideoFrame::WrapExternalSharedMemory(
306 Format format,
307 const gfx::Size& coded_size,
308 const gfx::Rect& visible_rect,
278 const gfx::Size& natural_size, 309 const gfx::Size& natural_size,
279 uint8* data, 310 uint8* data,
280 size_t data_size, 311 size_t data_size,
281 base::SharedMemoryHandle handle, 312 base::SharedMemoryHandle handle,
282 size_t data_offset, 313 size_t data_offset,
283 base::TimeDelta timestamp) { 314 base::TimeDelta timestamp) {
284 const gfx::Size new_coded_size = AdjustCodedSize(format, coded_size); 315 return WrapExternalStorage(format, STORAGE_SHMEM, coded_size, visible_rect,
285 316 natural_size, data, data_size, timestamp, handle,
286 if (!IsValidConfig(format, new_coded_size, visible_rect, natural_size)) 317 data_offset);
287 return NULL;
288 if (data_size < AllocationSize(format, new_coded_size))
289 return NULL;
290
291 switch (format) {
292 case VideoFrame::I420: {
293 gpu::MailboxHolder mailbox_holders[kMaxPlanes];
294 scoped_refptr<VideoFrame> frame(
295 new VideoFrame(format, new_coded_size, visible_rect, natural_size,
296 mailbox_holders, TEXTURE_RGBA, timestamp, false));
297 frame->shared_memory_handle_ = handle;
298 frame->shared_memory_offset_ = data_offset;
299 frame->strides_[kYPlane] = new_coded_size.width();
300 frame->strides_[kUPlane] = new_coded_size.width() / 2;
301 frame->strides_[kVPlane] = new_coded_size.width() / 2;
302 frame->data_[kYPlane] = data;
303 frame->data_[kUPlane] = data + new_coded_size.GetArea();
304 frame->data_[kVPlane] = data + (new_coded_size.GetArea() * 5 / 4);
305 return frame;
306 }
307 default:
308 NOTIMPLEMENTED();
309 return NULL;
310 }
311 } 318 }
312 319
313 // static 320 // static
314 scoped_refptr<VideoFrame> VideoFrame::WrapExternalYuvData( 321 scoped_refptr<VideoFrame> VideoFrame::WrapExternalYuvData(
315 Format format, 322 Format format,
316 const gfx::Size& coded_size, 323 const gfx::Size& coded_size,
317 const gfx::Rect& visible_rect, 324 const gfx::Rect& visible_rect,
318 const gfx::Size& natural_size, 325 const gfx::Size& natural_size,
319 int32 y_stride, 326 int32 y_stride,
320 int32 u_stride, 327 int32 u_stride,
321 int32 v_stride, 328 int32 v_stride,
322 uint8* y_data, 329 uint8* y_data,
323 uint8* u_data, 330 uint8* u_data,
324 uint8* v_data, 331 uint8* v_data,
325 base::TimeDelta timestamp) { 332 base::TimeDelta timestamp) {
326 const gfx::Size new_coded_size = AdjustCodedSize(format, coded_size); 333 const gfx::Size new_coded_size = AdjustCodedSize(format, coded_size);
327 CHECK(IsValidConfig(format, new_coded_size, visible_rect, natural_size)); 334 CHECK(IsValidConfig(format, STORAGE_UNOWNED_MEMORY, new_coded_size,
335 visible_rect, natural_size));
328 336
329 gpu::MailboxHolder mailbox_holders[kMaxPlanes];
330 scoped_refptr<VideoFrame> frame( 337 scoped_refptr<VideoFrame> frame(
331 new VideoFrame(format, new_coded_size, visible_rect, natural_size, 338 new VideoFrame(format, STORAGE_UNOWNED_MEMORY, new_coded_size,
332 mailbox_holders, TEXTURE_RGBA, timestamp, false)); 339 visible_rect, natural_size, timestamp, false));
333 frame->strides_[kYPlane] = y_stride; 340 frame->strides_[kYPlane] = y_stride;
334 frame->strides_[kUPlane] = u_stride; 341 frame->strides_[kUPlane] = u_stride;
335 frame->strides_[kVPlane] = v_stride; 342 frame->strides_[kVPlane] = v_stride;
336 frame->data_[kYPlane] = y_data; 343 frame->data_[kYPlane] = y_data;
337 frame->data_[kUPlane] = u_data; 344 frame->data_[kUPlane] = u_data;
338 frame->data_[kVPlane] = v_data; 345 frame->data_[kVPlane] = v_data;
339 return frame; 346 return frame;
340 } 347 }
341 348
342 #if defined(OS_POSIX) 349 #if defined(OS_LINUX)
343 // static 350 // static
344 scoped_refptr<VideoFrame> VideoFrame::WrapExternalDmabufs( 351 scoped_refptr<VideoFrame> VideoFrame::WrapExternalDmabufs(
345 Format format, 352 Format format,
346 const gfx::Size& coded_size, 353 const gfx::Size& coded_size,
347 const gfx::Rect& visible_rect, 354 const gfx::Rect& visible_rect,
348 const gfx::Size& natural_size, 355 const gfx::Size& natural_size,
349 const std::vector<int> dmabuf_fds, 356 const std::vector<int> dmabuf_fds,
350 base::TimeDelta timestamp) { 357 base::TimeDelta timestamp) {
351 if (!IsValidConfig(format, coded_size, visible_rect, natural_size)) 358 if (!IsValidConfig(format, STORAGE_DMABUFS, coded_size, visible_rect,
359 natural_size)) {
352 return NULL; 360 return NULL;
361 }
353 362
354 // TODO(posciak): This is not exactly correct, it's possible for one 363 // TODO(posciak): This is not exactly correct, it's possible for one
355 // buffer to contain more than one plane. 364 // buffer to contain more than one plane.
356 if (dmabuf_fds.size() != NumPlanes(format)) { 365 if (dmabuf_fds.size() != NumPlanes(format)) {
357 LOG(FATAL) << "Not enough dmabuf fds provided!"; 366 LOG(FATAL) << "Not enough dmabuf fds provided!";
358 return NULL; 367 return NULL;
359 } 368 }
360 369
361 gpu::MailboxHolder mailbox_holders[kMaxPlanes]; 370 DCHECK_EQ(format, ARGB);
362 scoped_refptr<VideoFrame> frame( 371 scoped_refptr<VideoFrame> frame(
363 new VideoFrame(format, coded_size, visible_rect, natural_size, 372 new VideoFrame(format, STORAGE_DMABUFS, coded_size, visible_rect,
364 mailbox_holders, TEXTURE_RGBA, timestamp, false)); 373 natural_size, timestamp, false));
365 374
366 for (size_t i = 0; i < dmabuf_fds.size(); ++i) { 375 for (size_t i = 0; i < dmabuf_fds.size(); ++i) {
367 int duped_fd = HANDLE_EINTR(dup(dmabuf_fds[i])); 376 int duped_fd = HANDLE_EINTR(dup(dmabuf_fds[i]));
368 if (duped_fd == -1) { 377 if (duped_fd == -1) {
369 // The already-duped in previous iterations fds will be closed when 378 // The already-duped in previous iterations fds will be closed when
370 // the partially-created frame drops out of scope here. 379 // the partially-created frame drops out of scope here.
371 DLOG(ERROR) << "Failed duplicating a dmabuf fd"; 380 DLOG(ERROR) << "Failed duplicating a dmabuf fd";
372 return NULL; 381 return NULL;
373 } 382 }
374 383
(...skipping 12 matching lines...) Expand all
387 scoped_refptr<VideoFrame> VideoFrame::WrapCVPixelBuffer( 396 scoped_refptr<VideoFrame> VideoFrame::WrapCVPixelBuffer(
388 CVPixelBufferRef cv_pixel_buffer, 397 CVPixelBufferRef cv_pixel_buffer,
389 base::TimeDelta timestamp) { 398 base::TimeDelta timestamp) {
390 DCHECK(cv_pixel_buffer); 399 DCHECK(cv_pixel_buffer);
391 DCHECK(CFGetTypeID(cv_pixel_buffer) == CVPixelBufferGetTypeID()); 400 DCHECK(CFGetTypeID(cv_pixel_buffer) == CVPixelBufferGetTypeID());
392 401
393 const OSType cv_format = CVPixelBufferGetPixelFormatType(cv_pixel_buffer); 402 const OSType cv_format = CVPixelBufferGetPixelFormatType(cv_pixel_buffer);
394 Format format; 403 Format format;
395 // There are very few compatible CV pixel formats, so just check each. 404 // There are very few compatible CV pixel formats, so just check each.
396 if (cv_format == kCVPixelFormatType_420YpCbCr8Planar) { 405 if (cv_format == kCVPixelFormatType_420YpCbCr8Planar) {
397 format = Format::I420; 406 format = I420;
398 } else if (cv_format == kCVPixelFormatType_444YpCbCr8) { 407 } else if (cv_format == kCVPixelFormatType_444YpCbCr8) {
399 format = Format::YV24; 408 format = YV24;
400 } else if (cv_format == '420v') { 409 } else if (cv_format == '420v') {
401 // TODO(jfroy): Use kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange when the 410 // TODO(jfroy): Use kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange when the
402 // minimum OS X and iOS SDKs permits it. 411 // minimum OS X and iOS SDKs permits it.
403 format = Format::NV12; 412 format = NV12;
404 } else { 413 } else {
405 DLOG(ERROR) << "CVPixelBuffer format not supported: " << cv_format; 414 DLOG(ERROR) << "CVPixelBuffer format not supported: " << cv_format;
406 return NULL; 415 return NULL;
407 } 416 }
408 417
409 const gfx::Size coded_size(CVImageBufferGetEncodedSize(cv_pixel_buffer)); 418 const gfx::Size coded_size(CVImageBufferGetEncodedSize(cv_pixel_buffer));
410 const gfx::Rect visible_rect(CVImageBufferGetCleanRect(cv_pixel_buffer)); 419 const gfx::Rect visible_rect(CVImageBufferGetCleanRect(cv_pixel_buffer));
411 const gfx::Size natural_size(CVImageBufferGetDisplaySize(cv_pixel_buffer)); 420 const gfx::Size natural_size(CVImageBufferGetDisplaySize(cv_pixel_buffer));
412 421
413 if (!IsValidConfig(format, coded_size, visible_rect, natural_size)) 422 if (!IsValidConfig(format, STORAGE_UNOWNED_MEMORY, coded_size, visible_rect,
423 natural_size)) {
414 return NULL; 424 return NULL;
425 }
415 426
416 gpu::MailboxHolder mailbox_holders[kMaxPlanes];
417 scoped_refptr<VideoFrame> frame( 427 scoped_refptr<VideoFrame> frame(
418 new VideoFrame(format, coded_size, visible_rect, natural_size, 428 new VideoFrame(format, STORAGE_UNOWNED_MEMORY, coded_size, visible_rect,
419 mailbox_holders, TEXTURE_RGBA, timestamp, false)); 429 natural_size, timestamp, false));
420 430
421 frame->cv_pixel_buffer_.reset(cv_pixel_buffer, base::scoped_policy::RETAIN); 431 frame->cv_pixel_buffer_.reset(cv_pixel_buffer, base::scoped_policy::RETAIN);
422 return frame; 432 return frame;
423 } 433 }
424 #endif 434 #endif
425 435
426 // static 436 // static
427 scoped_refptr<VideoFrame> VideoFrame::WrapVideoFrame( 437 scoped_refptr<VideoFrame> VideoFrame::WrapVideoFrame(
428 const scoped_refptr<VideoFrame>& frame, 438 const scoped_refptr<VideoFrame>& frame,
429 const gfx::Rect& visible_rect, 439 const gfx::Rect& visible_rect,
430 const gfx::Size& natural_size) { 440 const gfx::Size& natural_size) {
431 // NATIVE_TEXTURE frames need mailbox info propagated, and there's no support 441 // STORAGE_TEXTURE frames need mailbox info propagated, and there's no support
432 // for that here yet, see http://crbug/362521. 442 // for that here yet, see http://crbug/362521.
433 CHECK_NE(frame->format(), NATIVE_TEXTURE); 443 CHECK_NE(frame->storage_type(), STORAGE_TEXTURE);
434 444
435 DCHECK(frame->visible_rect().Contains(visible_rect)); 445 DCHECK(frame->visible_rect().Contains(visible_rect));
436 gpu::MailboxHolder mailbox_holders[kMaxPlanes];
437 scoped_refptr<VideoFrame> wrapped_frame( 446 scoped_refptr<VideoFrame> wrapped_frame(
438 new VideoFrame(frame->format(), frame->coded_size(), visible_rect, 447 new VideoFrame(frame->format(), frame->storage_type(),
439 natural_size, mailbox_holders, TEXTURE_RGBA, 448 frame->coded_size(), visible_rect, natural_size,
440 frame->timestamp(), frame->end_of_stream())); 449 frame->timestamp(), frame->end_of_stream()));
441 450
442 for (size_t i = 0; i < NumPlanes(frame->format()); ++i) { 451 for (size_t i = 0; i < NumPlanes(frame->format()); ++i) {
443 wrapped_frame->strides_[i] = frame->stride(i); 452 wrapped_frame->strides_[i] = frame->stride(i);
444 wrapped_frame->data_[i] = frame->data(i); 453 wrapped_frame->data_[i] = frame->data(i);
445 } 454 }
446 455
447 return wrapped_frame; 456 return wrapped_frame;
448 } 457 }
449 458
450 // static 459 // static
451 scoped_refptr<VideoFrame> VideoFrame::CreateEOSFrame() { 460 scoped_refptr<VideoFrame> VideoFrame::CreateEOSFrame() {
452 gpu::MailboxHolder mailbox_holders[kMaxPlanes]; 461 return new VideoFrame(UNKNOWN, STORAGE_UNKNOWN, gfx::Size(), gfx::Rect(),
453 return new VideoFrame(VideoFrame::UNKNOWN, gfx::Size(), gfx::Rect(), 462 gfx::Size(), kNoTimestamp(), true);
454 gfx::Size(), mailbox_holders, TEXTURE_RGBA,
455 kNoTimestamp(), true);
456 } 463 }
457 464
458 // static 465 // static
459 scoped_refptr<VideoFrame> VideoFrame::CreateColorFrame( 466 scoped_refptr<VideoFrame> VideoFrame::CreateColorFrame(
460 const gfx::Size& size, 467 const gfx::Size& size,
461 uint8 y, uint8 u, uint8 v, 468 uint8 y, uint8 u, uint8 v,
462 base::TimeDelta timestamp) { 469 base::TimeDelta timestamp) {
463 scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame( 470 scoped_refptr<VideoFrame> frame =
464 VideoFrame::YV12, size, gfx::Rect(size), size, timestamp); 471 CreateFrame(YV12, size, gfx::Rect(size), size, timestamp);
465 FillYUV(frame.get(), y, u, v); 472 FillYUV(frame.get(), y, u, v);
466 return frame; 473 return frame;
467 } 474 }
468 475
469 // static 476 // static
470 scoped_refptr<VideoFrame> VideoFrame::CreateBlackFrame(const gfx::Size& size) { 477 scoped_refptr<VideoFrame> VideoFrame::CreateBlackFrame(const gfx::Size& size) {
471 const uint8 kBlackY = 0x00; 478 const uint8 kBlackY = 0x00;
472 const uint8 kBlackUV = 0x80; 479 const uint8 kBlackUV = 0x80;
473 const base::TimeDelta kZero; 480 const base::TimeDelta kZero;
474 return CreateColorFrame(size, kBlackY, kBlackUV, kBlackUV, kZero); 481 return CreateColorFrame(size, kBlackY, kBlackUV, kBlackUV, kZero);
475 } 482 }
476 483
477 // static 484 // static
478 scoped_refptr<VideoFrame> VideoFrame::CreateTransparentFrame( 485 scoped_refptr<VideoFrame> VideoFrame::CreateTransparentFrame(
479 const gfx::Size& size) { 486 const gfx::Size& size) {
480 const uint8 kBlackY = 0x00; 487 const uint8 kBlackY = 0x00;
481 const uint8 kBlackUV = 0x00; 488 const uint8 kBlackUV = 0x00;
482 const uint8 kTransparentA = 0x00; 489 const uint8 kTransparentA = 0x00;
483 const base::TimeDelta kZero; 490 const base::TimeDelta kZero;
484 scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame( 491 scoped_refptr<VideoFrame> frame =
485 VideoFrame::YV12A, size, gfx::Rect(size), size, kZero); 492 CreateFrame(YV12A, size, gfx::Rect(size), size, kZero);
486 FillYUVA(frame.get(), kBlackY, kBlackUV, kBlackUV, kTransparentA); 493 FillYUVA(frame.get(), kBlackY, kBlackUV, kBlackUV, kTransparentA);
487 return frame; 494 return frame;
488 } 495 }
489 496
490 #if defined(VIDEO_HOLE) 497 #if defined(VIDEO_HOLE)
491 // This block and other blocks wrapped around #if defined(VIDEO_HOLE) is not 498 // This block and other blocks wrapped around #if defined(VIDEO_HOLE) is not
492 // maintained by the general compositor team. Please contact the following 499 // maintained by the general compositor team. Please contact
493 // people instead: 500 // wonsik@chromium.org .
494 //
495 // wonsik@chromium.org
496 // ycheo@chromium.org
497 501
498 // static 502 // static
499 scoped_refptr<VideoFrame> VideoFrame::CreateHoleFrame( 503 scoped_refptr<VideoFrame> VideoFrame::CreateHoleFrame(
500 const gfx::Size& size) { 504 const gfx::Size& size) {
501 DCHECK(IsValidConfig(VideoFrame::HOLE, size, gfx::Rect(size), size)); 505 DCHECK(IsValidConfig(UNKNOWN, STORAGE_HOLE, size, gfx::Rect(size), size));
502 gpu::MailboxHolder mailboxes[kMaxPlanes];
503 scoped_refptr<VideoFrame> frame( 506 scoped_refptr<VideoFrame> frame(
504 new VideoFrame(VideoFrame::HOLE, size, gfx::Rect(size), size, mailboxes, 507 new VideoFrame(UNKNOWN, STORAGE_HOLE, size, gfx::Rect(size), size,
505 TEXTURE_RGBA, base::TimeDelta(), false)); 508 base::TimeDelta(), false));
506 return frame; 509 return frame;
507 } 510 }
508 #endif // defined(VIDEO_HOLE) 511 #endif // defined(VIDEO_HOLE)
509 512
510 // static 513 // static
511 size_t VideoFrame::NumPlanes(Format format) { 514 size_t VideoFrame::NumPlanes(Format format) {
512 switch (format) { 515 switch (format) {
513 case VideoFrame::NATIVE_TEXTURE: 516 case ARGB:
514 #if defined(VIDEO_HOLE) 517 case XRGB:
515 case VideoFrame::HOLE:
516 #endif // defined(VIDEO_HOLE)
517 return 0;
518 case VideoFrame::ARGB:
519 return 1; 518 return 1;
520 case VideoFrame::NV12: 519 #if defined(OS_MACOSX) || defined(OS_CHROMEOS)
520 case NV12:
521 return 2; 521 return 2;
522 case VideoFrame::YV12: 522 #endif
523 case VideoFrame::YV16: 523 case YV12:
524 case VideoFrame::I420: 524 case YV16:
525 case VideoFrame::YV24: 525 case I420:
526 case YV24:
526 return 3; 527 return 3;
527 case VideoFrame::YV12A: 528 case YV12A:
528 return 4; 529 return 4;
529 case VideoFrame::UNKNOWN: 530 case UNKNOWN:
530 break; 531 break;
531 } 532 }
532 NOTREACHED() << "Unsupported video frame format: " << format; 533 NOTREACHED() << "Unsupported video frame format: " << format;
533 return 0; 534 return 0;
534 } 535 }
535 536
536 // static 537 // static
537 size_t VideoFrame::NumTextures(TextureFormat texture_format) {
538 switch (texture_format) {
539 case TEXTURE_RGBA:
540 case TEXTURE_RGB:
541 return 1;
542 case TEXTURE_YUV_420:
543 return 3;
544 }
545
546 NOTREACHED();
547 return 0;
548 }
549
550 // static
551 size_t VideoFrame::AllocationSize(Format format, const gfx::Size& coded_size) { 538 size_t VideoFrame::AllocationSize(Format format, const gfx::Size& coded_size) {
552 size_t total = 0; 539 size_t total = 0;
553 for (size_t i = 0; i < NumPlanes(format); ++i) 540 for (size_t i = 0; i < NumPlanes(format); ++i)
554 total += PlaneAllocationSize(format, i, coded_size); 541 total += PlaneAllocationSize(format, i, coded_size);
555 return total; 542 return total;
556 } 543 }
557 544
558 // static 545 // static
559 gfx::Size VideoFrame::PlaneSize(Format format, 546 gfx::Size VideoFrame::PlaneSize(Format format,
560 size_t plane, 547 size_t plane,
561 const gfx::Size& coded_size) { 548 const gfx::Size& coded_size) {
562 DCHECK(IsValidPlane(plane, format)); 549 DCHECK(IsValidPlane(plane, format));
563 550
564 int width = coded_size.width(); 551 int width = coded_size.width();
565 int height = coded_size.height(); 552 int height = coded_size.height();
566 if (format != VideoFrame::ARGB) { 553 if (format != ARGB) {
567 // Align to multiple-of-two size overall. This ensures that non-subsampled 554 // Align to multiple-of-two size overall. This ensures that non-subsampled
568 // planes can be addressed by pixel with the same scaling as the subsampled 555 // planes can be addressed by pixel with the same scaling as the subsampled
569 // planes. 556 // planes.
570 width = RoundUp(width, 2); 557 width = RoundUp(width, 2);
571 height = RoundUp(height, 2); 558 height = RoundUp(height, 2);
572 } 559 }
573 560
574 const gfx::Size subsample = SampleSize(format, plane); 561 const gfx::Size subsample = SampleSize(format, plane);
575 DCHECK(width % subsample.width() == 0); 562 DCHECK(width % subsample.width() == 0);
576 DCHECK(height % subsample.height() == 0); 563 DCHECK(height % subsample.height() == 0);
(...skipping 16 matching lines...) Expand all
593 return bits_per_element / horiz_pixels_per_element; 580 return bits_per_element / horiz_pixels_per_element;
594 } 581 }
595 582
596 // static 583 // static
597 int VideoFrame::PlaneBitsPerPixel(Format format, size_t plane) { 584 int VideoFrame::PlaneBitsPerPixel(Format format, size_t plane) {
598 DCHECK(IsValidPlane(plane, format)); 585 DCHECK(IsValidPlane(plane, format));
599 return PlaneHorizontalBitsPerPixel(format, plane) / 586 return PlaneHorizontalBitsPerPixel(format, plane) /
600 SampleSize(format, plane).height(); 587 SampleSize(format, plane).height();
601 } 588 }
602 589
603 // Release data allocated by AllocateYUV().
604 static void ReleaseData(uint8* data) {
605 DCHECK(data);
606 base::AlignedFree(data);
607 }
608
609 void VideoFrame::AllocateYUV() { 590 void VideoFrame::AllocateYUV() {
610 DCHECK(format_ == YV12 || format_ == YV16 || format_ == YV12A || 591 DCHECK_EQ(storage_type_, STORAGE_OWNED_MEMORY);
611 format_ == I420 || format_ == YV24);
612 static_assert(0 == kYPlane, "y plane data must be index 0"); 592 static_assert(0 == kYPlane, "y plane data must be index 0");
613 593
614 size_t data_size = 0; 594 size_t data_size = 0;
615 size_t offset[kMaxPlanes]; 595 size_t offset[kMaxPlanes];
616 for (size_t plane = 0; plane < VideoFrame::NumPlanes(format_); ++plane) { 596 for (size_t plane = 0; plane < NumPlanes(format_); ++plane) {
617 // The *2 in alignment for height is because some formats (e.g. h264) allow 597 // The *2 in alignment for height is because some formats (e.g. h264) allow
618 // interlaced coding, and then the size needs to be a multiple of two 598 // interlaced coding, and then the size needs to be a multiple of two
619 // macroblocks (vertically). See 599 // macroblocks (vertically). See
620 // libavcodec/utils.c:avcodec_align_dimensions2(). 600 // libavcodec/utils.c:avcodec_align_dimensions2().
621 const size_t height = RoundUp(rows(plane), kFrameSizeAlignment * 2); 601 const size_t height = RoundUp(rows(plane), kFrameSizeAlignment * 2);
622 strides_[plane] = RoundUp(row_bytes(plane), kFrameSizeAlignment); 602 strides_[plane] = RoundUp(row_bytes(plane), kFrameSizeAlignment);
623 offset[plane] = data_size; 603 offset[plane] = data_size;
624 data_size += height * strides_[plane]; 604 data_size += height * strides_[plane];
625 } 605 }
626 606
627 // The extra line of UV being allocated is because h264 chroma MC 607 // The extra line of UV being allocated is because h264 chroma MC
628 // overreads by one line in some cases, see libavcodec/utils.c: 608 // overreads by one line in some cases, see libavcodec/utils.c:
629 // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm: 609 // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm:
630 // put_h264_chroma_mc4_ssse3(). 610 // put_h264_chroma_mc4_ssse3().
631 DCHECK(IsValidPlane(kUPlane, format_)); 611 DCHECK(IsValidPlane(kUPlane, format_));
632 data_size += strides_[kUPlane] + kFrameSizePadding; 612 data_size += strides_[kUPlane] + kFrameSizePadding;
633 613
634 // FFmpeg expects the initialize allocation to be zero-initialized. Failure 614 // FFmpeg expects the initialize allocation to be zero-initialized. Failure
635 // to do so can lead to unitialized value usage. See http://crbug.com/390941 615 // to do so can lead to unitialized value usage. See http://crbug.com/390941
636 uint8* data = reinterpret_cast<uint8*>( 616 uint8* data = reinterpret_cast<uint8*>(
637 base::AlignedAlloc(data_size, kFrameAddressAlignment)); 617 base::AlignedAlloc(data_size, kFrameAddressAlignment));
638 memset(data, 0, data_size); 618 memset(data, 0, data_size);
639 619
640 for (size_t plane = 0; plane < VideoFrame::NumPlanes(format_); ++plane) 620 for (size_t plane = 0; plane < NumPlanes(format_); ++plane)
641 data_[plane] = data + offset[plane]; 621 data_[plane] = data + offset[plane];
642 622
643 AddDestructionObserver(base::Bind(&ReleaseData, data)); 623 AddDestructionObserver(base::Bind(&ReleaseData, data));
644 } 624 }
645 625
646 VideoFrame::VideoFrame(VideoFrame::Format format, 626 VideoFrame::VideoFrame(Format format,
627 StorageType storage_type,
647 const gfx::Size& coded_size, 628 const gfx::Size& coded_size,
648 const gfx::Rect& visible_rect, 629 const gfx::Rect& visible_rect,
649 const gfx::Size& natural_size, 630 const gfx::Size& natural_size,
650 const gpu::MailboxHolder(&mailbox_holders)[kMaxPlanes],
651 VideoFrame::TextureFormat texture_format,
652 base::TimeDelta timestamp, 631 base::TimeDelta timestamp,
653 bool end_of_stream) 632 bool end_of_stream)
654 : format_(format), 633 : format_(format),
655 texture_format_(texture_format), 634 storage_type_(storage_type),
656 coded_size_(coded_size), 635 coded_size_(coded_size),
657 visible_rect_(visible_rect), 636 visible_rect_(visible_rect),
658 natural_size_(natural_size), 637 natural_size_(natural_size),
659 shared_memory_handle_(base::SharedMemory::NULLHandle()), 638 shared_memory_handle_(base::SharedMemory::NULLHandle()),
660 shared_memory_offset_(0), 639 shared_memory_offset_(0),
661 timestamp_(timestamp), 640 timestamp_(timestamp),
662 release_sync_point_(0), 641 release_sync_point_(0),
663 end_of_stream_(end_of_stream), 642 end_of_stream_(end_of_stream),
664 allow_overlay_(false) { 643 allow_overlay_(false) {
665 DCHECK(IsValidConfig(format_, coded_size_, visible_rect_, natural_size_)); 644 DCHECK(IsValidConfig(format_, storage_type, coded_size_, visible_rect_,
666 memcpy(&mailbox_holders_, mailbox_holders, sizeof(mailbox_holders_)); 645 natural_size_));
646 memset(&mailbox_holders_, 0, sizeof(mailbox_holders_));
667 memset(&strides_, 0, sizeof(strides_)); 647 memset(&strides_, 0, sizeof(strides_));
668 memset(&data_, 0, sizeof(data_)); 648 memset(&data_, 0, sizeof(data_));
669 } 649 }
670 650
651 VideoFrame::VideoFrame(Format format,
652 StorageType storage_type,
653 const gfx::Size& coded_size,
654 const gfx::Rect& visible_rect,
655 const gfx::Size& natural_size,
656 base::TimeDelta timestamp,
657 bool end_of_stream,
658 base::SharedMemoryHandle handle,
659 size_t shared_memory_offset)
660 : VideoFrame(format, storage_type, coded_size, visible_rect, natural_size,
661 timestamp, end_of_stream) {
662 shared_memory_handle_ = handle;
663 shared_memory_offset_ = shared_memory_offset;
664 }
665
666 VideoFrame::VideoFrame(Format format,
667 StorageType storage_type,
668 const gfx::Size& coded_size,
669 const gfx::Rect& visible_rect,
670 const gfx::Size& natural_size,
671 const gpu::MailboxHolder(&mailbox_holders)[kMaxPlanes],
672 base::TimeDelta timestamp,
673 bool end_of_stream)
674 : VideoFrame(format, storage_type, coded_size, visible_rect, natural_size,
675 timestamp, end_of_stream) {
676 memcpy(&mailbox_holders_, mailbox_holders, sizeof(mailbox_holders_));
677 }
678
671 VideoFrame::~VideoFrame() { 679 VideoFrame::~VideoFrame() {
672 if (!mailbox_holders_release_cb_.is_null()) { 680 if (!mailbox_holders_release_cb_.is_null()) {
673 uint32 release_sync_point; 681 uint32 release_sync_point;
674 { 682 {
675 // To ensure that changes to |release_sync_point_| are visible on this 683 // To ensure that changes to |release_sync_point_| are visible on this
676 // thread (imply a memory barrier). 684 // thread (imply a memory barrier).
677 base::AutoLock locker(release_sync_point_lock_); 685 base::AutoLock locker(release_sync_point_lock_);
678 release_sync_point = release_sync_point_; 686 release_sync_point = release_sync_point_;
679 } 687 }
680 base::ResetAndReturn(&mailbox_holders_release_cb_).Run(release_sync_point); 688 base::ResetAndReturn(&mailbox_holders_release_cb_).Run(release_sync_point);
681 } 689 }
682 690
683 for (auto& callback : done_callbacks_) 691 for (auto& callback : done_callbacks_)
684 base::ResetAndReturn(&callback).Run(); 692 base::ResetAndReturn(&callback).Run();
685 } 693 }
686 694
687 // static 695 // static
688 bool VideoFrame::IsValidPlane(size_t plane, VideoFrame::Format format) { 696 scoped_refptr<VideoFrame> VideoFrame::WrapExternalStorage(
697 Format format,
698 StorageType storage_type,
699 const gfx::Size& coded_size,
700 const gfx::Rect& visible_rect,
701 const gfx::Size& natural_size,
702 uint8* data,
703 size_t data_size,
704 base::TimeDelta timestamp,
705 base::SharedMemoryHandle handle,
706 size_t data_offset) {
707 const gfx::Size new_coded_size = AdjustCodedSize(format, coded_size);
708
709 if (!IsValidConfig(format, storage_type, new_coded_size, visible_rect,
710 natural_size) ||
711 data_size < AllocationSize(format, new_coded_size)) {
712 return NULL;
713 }
714 DLOG_IF(ERROR, format != I420) << "Only I420 format supported: "
715 << FormatToString(format);
716 if (format != I420)
717 return NULL;
718
719 scoped_refptr<VideoFrame> frame;
720 if (storage_type == STORAGE_SHMEM) {
721 frame = new VideoFrame(format, storage_type, new_coded_size, visible_rect,
722 natural_size, timestamp, false, handle, data_offset);
723 } else {
724 frame = new VideoFrame(format, storage_type, new_coded_size, visible_rect,
725 natural_size, timestamp, false);
726 }
727 frame->strides_[kYPlane] = new_coded_size.width();
728 frame->strides_[kUPlane] = new_coded_size.width() / 2;
729 frame->strides_[kVPlane] = new_coded_size.width() / 2;
730 frame->data_[kYPlane] = data;
731 frame->data_[kUPlane] = data + new_coded_size.GetArea();
732 frame->data_[kVPlane] = data + (new_coded_size.GetArea() * 5 / 4);
733 return frame;
734 }
735
736 // static
737 bool VideoFrame::IsValidPlane(size_t plane, Format format) {
689 return (plane < NumPlanes(format)); 738 return (plane < NumPlanes(format));
690 } 739 }
691 740
692 int VideoFrame::stride(size_t plane) const { 741 int VideoFrame::stride(size_t plane) const {
693 DCHECK(IsValidPlane(plane, format_)); 742 DCHECK(IsValidPlane(plane, format_));
694 return strides_[plane]; 743 return strides_[plane];
695 } 744 }
696 745
697 // static 746 // static
698 size_t VideoFrame::RowBytes(size_t plane, 747 size_t VideoFrame::RowBytes(size_t plane, Format format, int width) {
699 VideoFrame::Format format,
700 int width) {
701 DCHECK(IsValidPlane(plane, format)); 748 DCHECK(IsValidPlane(plane, format));
702 return BytesPerElement(format, plane) * Columns(plane, format, width); 749 return BytesPerElement(format, plane) * Columns(plane, format, width);
703 } 750 }
704 751
705 int VideoFrame::row_bytes(size_t plane) const { 752 int VideoFrame::row_bytes(size_t plane) const {
706 return RowBytes(plane, format_, coded_size_.width()); 753 return RowBytes(plane, format_, coded_size_.width());
707 } 754 }
708 755
709 // static 756 // static
710 size_t VideoFrame::Rows(size_t plane, VideoFrame::Format format, int height) { 757 size_t VideoFrame::Rows(size_t plane, Format format, int height) {
711 DCHECK(IsValidPlane(plane, format)); 758 DCHECK(IsValidPlane(plane, format));
712 const int sample_height = SampleSize(format, plane).height(); 759 const int sample_height = SampleSize(format, plane).height();
713 return RoundUp(height, sample_height) / sample_height; 760 return RoundUp(height, sample_height) / sample_height;
714 } 761 }
715 762
716 // static 763 // static
717 size_t VideoFrame::Columns(size_t plane, Format format, int width) { 764 size_t VideoFrame::Columns(size_t plane, Format format, int width) {
718 DCHECK(IsValidPlane(plane, format)); 765 DCHECK(IsValidPlane(plane, format));
719 const int sample_width = SampleSize(format, plane).width(); 766 const int sample_width = SampleSize(format, plane).width();
720 return RoundUp(width, sample_width) / sample_width; 767 return RoundUp(width, sample_width) / sample_width;
721 } 768 }
722 769
723 int VideoFrame::rows(size_t plane) const { 770 int VideoFrame::rows(size_t plane) const {
724 return Rows(plane, format_, coded_size_.height()); 771 return Rows(plane, format_, coded_size_.height());
725 } 772 }
726 773
727 const uint8* VideoFrame::data(size_t plane) const { 774 const uint8* VideoFrame::data(size_t plane) const {
728 DCHECK(IsValidPlane(plane, format_)); 775 DCHECK(IsValidPlane(plane, format_));
776 DCHECK(IsMappable(storage_type_));
729 return data_[plane]; 777 return data_[plane];
730 } 778 }
731 779
732 uint8* VideoFrame::data(size_t plane) { 780 uint8* VideoFrame::data(size_t plane) {
733 DCHECK(IsValidPlane(plane, format_)); 781 DCHECK(IsValidPlane(plane, format_));
782 DCHECK(IsMappable(storage_type_));
734 return data_[plane]; 783 return data_[plane];
735 } 784 }
736 785
737 const uint8* VideoFrame::visible_data(size_t plane) const { 786 const uint8* VideoFrame::visible_data(size_t plane) const {
738 DCHECK(IsValidPlane(plane, format_)); 787 DCHECK(IsValidPlane(plane, format_));
788 DCHECK(IsMappable(storage_type_));
739 789
740 // Calculate an offset that is properly aligned for all planes. 790 // Calculate an offset that is properly aligned for all planes.
741 const gfx::Size alignment = CommonAlignment(format_); 791 const gfx::Size alignment = CommonAlignment(format_);
742 const gfx::Point offset(RoundDown(visible_rect_.x(), alignment.width()), 792 const gfx::Point offset(RoundDown(visible_rect_.x(), alignment.width()),
743 RoundDown(visible_rect_.y(), alignment.height())); 793 RoundDown(visible_rect_.y(), alignment.height()));
744 794
745 const gfx::Size subsample = SampleSize(format_, plane); 795 const gfx::Size subsample = SampleSize(format_, plane);
746 DCHECK(offset.x() % subsample.width() == 0); 796 DCHECK(offset.x() % subsample.width() == 0);
747 DCHECK(offset.y() % subsample.height() == 0); 797 DCHECK(offset.y() % subsample.height() == 0);
748 return data(plane) + 798 return data(plane) +
749 stride(plane) * (offset.y() / subsample.height()) + // Row offset. 799 stride(plane) * (offset.y() / subsample.height()) + // Row offset.
750 BytesPerElement(format_, plane) * // Column offset. 800 BytesPerElement(format_, plane) * // Column offset.
751 (offset.x() / subsample.width()); 801 (offset.x() / subsample.width());
752 } 802 }
753 803
754 uint8* VideoFrame::visible_data(size_t plane) { 804 uint8* VideoFrame::visible_data(size_t plane) {
755 return const_cast<uint8*>( 805 return const_cast<uint8*>(
756 static_cast<const VideoFrame*>(this)->visible_data(plane)); 806 static_cast<const VideoFrame*>(this)->visible_data(plane));
757 } 807 }
758 808
759 const gpu::MailboxHolder& VideoFrame::mailbox_holder(size_t texture) const { 809 const gpu::MailboxHolder&
760 DCHECK_EQ(format_, NATIVE_TEXTURE); 810 VideoFrame::mailbox_holder(size_t texture_index) const {
761 DCHECK_LT(texture, NumTextures(texture_format_)); 811 #if defined(OS_LINUX)
762 return mailbox_holders_[texture]; 812 DCHECK(storage_type_ == STORAGE_TEXTURE || storage_type_ == STORAGE_DMABUFS);
813 #else
814 DCHECK(storage_type_ == STORAGE_TEXTURE);
815 #endif
816 DCHECK_LT(texture_index, NumPlanes(format_));
817 return mailbox_holders_[texture_index];
763 } 818 }
764 819
765 base::SharedMemoryHandle VideoFrame::shared_memory_handle() const { 820 base::SharedMemoryHandle VideoFrame::shared_memory_handle() const {
821 DCHECK_EQ(storage_type_, STORAGE_SHMEM);
822 DCHECK(shared_memory_handle_ != base::SharedMemory::NULLHandle());
766 return shared_memory_handle_; 823 return shared_memory_handle_;
767 } 824 }
768 825
769 size_t VideoFrame::shared_memory_offset() const { 826 size_t VideoFrame::shared_memory_offset() const {
827 DCHECK_EQ(storage_type_, STORAGE_SHMEM);
828 DCHECK(shared_memory_handle_ != base::SharedMemory::NULLHandle());
770 return shared_memory_offset_; 829 return shared_memory_offset_;
771 } 830 }
772 831
773 void VideoFrame::AddDestructionObserver(const base::Closure& callback) { 832 void VideoFrame::AddDestructionObserver(const base::Closure& callback) {
774 DCHECK(!callback.is_null()); 833 DCHECK(!callback.is_null());
775 done_callbacks_.push_back(callback); 834 done_callbacks_.push_back(callback);
776 } 835 }
777 836
778 void VideoFrame::UpdateReleaseSyncPoint(SyncPointClient* client) { 837 void VideoFrame::UpdateReleaseSyncPoint(SyncPointClient* client) {
779 DCHECK_EQ(format_, NATIVE_TEXTURE); 838 #if defined(OS_LINUX)
839 DCHECK(storage_type_ == STORAGE_TEXTURE || storage_type_ == STORAGE_DMABUFS);
840 #else
841 DCHECK(storage_type_ == STORAGE_TEXTURE);
842 #endif
780 base::AutoLock locker(release_sync_point_lock_); 843 base::AutoLock locker(release_sync_point_lock_);
781 // Must wait on the previous sync point before inserting a new sync point so 844 // Must wait on the previous sync point before inserting a new sync point so
782 // that |mailbox_holders_release_cb_| guarantees the previous sync point 845 // that |mailbox_holders_release_cb_| guarantees the previous sync point
783 // occurred when it waits on |release_sync_point_|. 846 // occurred when it waits on |release_sync_point_|.
784 if (release_sync_point_) 847 if (release_sync_point_)
785 client->WaitSyncPoint(release_sync_point_); 848 client->WaitSyncPoint(release_sync_point_);
786 release_sync_point_ = client->InsertSyncPoint(); 849 release_sync_point_ = client->InsertSyncPoint();
787 } 850 }
788 851
789 #if defined(OS_POSIX) 852 #if defined(OS_LINUX)
790 int VideoFrame::dmabuf_fd(size_t plane) const { 853 int VideoFrame::dmabuf_fd(size_t plane) const {
854 DCHECK_EQ(storage_type_, STORAGE_DMABUFS);
791 return dmabuf_fds_[plane].get(); 855 return dmabuf_fds_[plane].get();
792 } 856 }
793 #endif 857 #endif
794 858
795 #if defined(OS_MACOSX) 859 #if defined(OS_MACOSX)
796 CVPixelBufferRef VideoFrame::cv_pixel_buffer() const { 860 CVPixelBufferRef VideoFrame::cv_pixel_buffer() const {
797 return cv_pixel_buffer_.get(); 861 return cv_pixel_buffer_.get();
798 } 862 }
799 #endif 863 #endif
800 864
801 void VideoFrame::HashFrameForTesting(base::MD5Context* context) { 865 void VideoFrame::HashFrameForTesting(base::MD5Context* context) {
802 for (size_t plane = 0; plane < NumPlanes(format_); ++plane) { 866 for (size_t plane = 0; plane < NumPlanes(format_); ++plane) {
803 for (int row = 0; row < rows(plane); ++row) { 867 for (int row = 0; row < rows(plane); ++row) {
804 base::MD5Update(context, base::StringPiece( 868 base::MD5Update(context, base::StringPiece(
805 reinterpret_cast<char*>(data(plane) + stride(plane) * row), 869 reinterpret_cast<char*>(data(plane) + stride(plane) * row),
806 row_bytes(plane))); 870 row_bytes(plane)));
807 } 871 }
808 } 872 }
809 } 873 }
810 874
811 } // namespace media 875 } // 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