OLD | NEW |
1 /* | 1 /* |
2 * libjingle | 2 * libjingle |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
(...skipping 22 matching lines...) Expand all Loading... |
33 #include "webrtc/base/logging.h" | 33 #include "webrtc/base/logging.h" |
34 #include "webrtc/video_frame.h" | 34 #include "webrtc/video_frame.h" |
35 | 35 |
36 using webrtc::kYPlane; | 36 using webrtc::kYPlane; |
37 using webrtc::kUPlane; | 37 using webrtc::kUPlane; |
38 using webrtc::kVPlane; | 38 using webrtc::kVPlane; |
39 | 39 |
40 namespace cricket { | 40 namespace cricket { |
41 | 41 |
42 WebRtcVideoFrame::WebRtcVideoFrame(): | 42 WebRtcVideoFrame::WebRtcVideoFrame(): |
43 pixel_width_(0), | |
44 pixel_height_(0), | |
45 time_stamp_ns_(0), | 43 time_stamp_ns_(0), |
46 rotation_(webrtc::kVideoRotation_0) {} | 44 rotation_(webrtc::kVideoRotation_0) {} |
47 | 45 |
48 WebRtcVideoFrame::WebRtcVideoFrame( | 46 WebRtcVideoFrame::WebRtcVideoFrame( |
49 const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& buffer, | 47 const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& buffer, |
50 int64_t time_stamp_ns, | 48 int64_t time_stamp_ns, |
51 webrtc::VideoRotation rotation) | 49 webrtc::VideoRotation rotation) |
52 : video_frame_buffer_(buffer), | 50 : video_frame_buffer_(buffer), |
53 pixel_width_(1), | |
54 pixel_height_(1), | |
55 time_stamp_ns_(time_stamp_ns), | 51 time_stamp_ns_(time_stamp_ns), |
56 rotation_(rotation) { | 52 rotation_(rotation) { |
57 } | 53 } |
58 | 54 |
59 WebRtcVideoFrame::~WebRtcVideoFrame() {} | 55 WebRtcVideoFrame::~WebRtcVideoFrame() {} |
60 | 56 |
61 bool WebRtcVideoFrame::Init(uint32_t format, | 57 bool WebRtcVideoFrame::Init(uint32_t format, |
62 int w, | 58 int w, |
63 int h, | 59 int h, |
64 int dw, | 60 int dw, |
65 int dh, | 61 int dh, |
66 uint8_t* sample, | 62 uint8_t* sample, |
67 size_t sample_size, | 63 size_t sample_size, |
68 size_t pixel_width, | |
69 size_t pixel_height, | |
70 int64_t time_stamp_ns, | 64 int64_t time_stamp_ns, |
71 webrtc::VideoRotation rotation) { | 65 webrtc::VideoRotation rotation) { |
72 return Reset(format, w, h, dw, dh, sample, sample_size, pixel_width, | 66 return Reset(format, w, h, dw, dh, sample, sample_size, |
73 pixel_height, time_stamp_ns, rotation, | 67 time_stamp_ns, rotation, |
74 true /*apply_rotation*/); | 68 true /*apply_rotation*/); |
75 } | 69 } |
76 | 70 |
77 bool WebRtcVideoFrame::Init(const CapturedFrame* frame, int dw, int dh, | 71 bool WebRtcVideoFrame::Init(const CapturedFrame* frame, int dw, int dh, |
78 bool apply_rotation) { | 72 bool apply_rotation) { |
79 return Reset(frame->fourcc, frame->width, frame->height, dw, dh, | 73 return Reset(frame->fourcc, frame->width, frame->height, dw, dh, |
80 static_cast<uint8_t*>(frame->data), frame->data_size, | 74 static_cast<uint8_t*>(frame->data), frame->data_size, |
81 frame->pixel_width, frame->pixel_height, frame->time_stamp, | 75 frame->time_stamp, |
82 frame->rotation, apply_rotation); | 76 frame->rotation, apply_rotation); |
83 } | 77 } |
84 | 78 |
85 bool WebRtcVideoFrame::InitToBlack(int w, int h, size_t pixel_width, | 79 bool WebRtcVideoFrame::InitToBlack(int w, int h, |
86 size_t pixel_height, int64_t time_stamp_ns) { | 80 int64_t time_stamp_ns) { |
87 InitToEmptyBuffer(w, h, pixel_width, pixel_height, time_stamp_ns); | 81 InitToEmptyBuffer(w, h, time_stamp_ns); |
88 return SetToBlack(); | 82 return SetToBlack(); |
89 } | 83 } |
90 | 84 |
91 size_t WebRtcVideoFrame::GetWidth() const { | 85 size_t WebRtcVideoFrame::GetWidth() const { |
92 return video_frame_buffer_ ? video_frame_buffer_->width() : 0; | 86 return video_frame_buffer_ ? video_frame_buffer_->width() : 0; |
93 } | 87 } |
94 | 88 |
95 size_t WebRtcVideoFrame::GetHeight() const { | 89 size_t WebRtcVideoFrame::GetHeight() const { |
96 return video_frame_buffer_ ? video_frame_buffer_->height() : 0; | 90 return video_frame_buffer_ ? video_frame_buffer_->height() : 0; |
97 } | 91 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 } | 138 } |
145 | 139 |
146 rtc::scoped_refptr<webrtc::VideoFrameBuffer> | 140 rtc::scoped_refptr<webrtc::VideoFrameBuffer> |
147 WebRtcVideoFrame::GetVideoFrameBuffer() const { | 141 WebRtcVideoFrame::GetVideoFrameBuffer() const { |
148 return video_frame_buffer_; | 142 return video_frame_buffer_; |
149 } | 143 } |
150 | 144 |
151 VideoFrame* WebRtcVideoFrame::Copy() const { | 145 VideoFrame* WebRtcVideoFrame::Copy() const { |
152 WebRtcVideoFrame* new_frame = new WebRtcVideoFrame( | 146 WebRtcVideoFrame* new_frame = new WebRtcVideoFrame( |
153 video_frame_buffer_, time_stamp_ns_, rotation_); | 147 video_frame_buffer_, time_stamp_ns_, rotation_); |
154 new_frame->pixel_width_ = pixel_width_; | |
155 new_frame->pixel_height_ = pixel_height_; | |
156 return new_frame; | 148 return new_frame; |
157 } | 149 } |
158 | 150 |
159 bool WebRtcVideoFrame::MakeExclusive() { | 151 bool WebRtcVideoFrame::MakeExclusive() { |
160 RTC_DCHECK(video_frame_buffer_->native_handle() == nullptr); | 152 RTC_DCHECK(video_frame_buffer_->native_handle() == nullptr); |
161 if (IsExclusive()) | 153 if (IsExclusive()) |
162 return true; | 154 return true; |
163 | 155 |
164 // Not exclusive already, need to copy buffer. | 156 // Not exclusive already, need to copy buffer. |
165 rtc::scoped_refptr<webrtc::VideoFrameBuffer> new_buffer = | 157 rtc::scoped_refptr<webrtc::VideoFrameBuffer> new_buffer = |
(...skipping 23 matching lines...) Expand all Loading... |
189 return VideoFrame::ConvertToRgbBuffer(to_fourcc, buffer, size, stride_rgb); | 181 return VideoFrame::ConvertToRgbBuffer(to_fourcc, buffer, size, stride_rgb); |
190 } | 182 } |
191 | 183 |
192 bool WebRtcVideoFrame::Reset(uint32_t format, | 184 bool WebRtcVideoFrame::Reset(uint32_t format, |
193 int w, | 185 int w, |
194 int h, | 186 int h, |
195 int dw, | 187 int dw, |
196 int dh, | 188 int dh, |
197 uint8_t* sample, | 189 uint8_t* sample, |
198 size_t sample_size, | 190 size_t sample_size, |
199 size_t pixel_width, | |
200 size_t pixel_height, | |
201 int64_t time_stamp_ns, | 191 int64_t time_stamp_ns, |
202 webrtc::VideoRotation rotation, | 192 webrtc::VideoRotation rotation, |
203 bool apply_rotation) { | 193 bool apply_rotation) { |
204 if (!Validate(format, w, h, sample, sample_size)) { | 194 if (!Validate(format, w, h, sample, sample_size)) { |
205 return false; | 195 return false; |
206 } | 196 } |
207 // Translate aliases to standard enums (e.g., IYUV -> I420). | 197 // Translate aliases to standard enums (e.g., IYUV -> I420). |
208 format = CanonicalFourCC(format); | 198 format = CanonicalFourCC(format); |
209 | 199 |
210 // Set up a new buffer. | 200 // Set up a new buffer. |
211 // TODO(fbarchard): Support lazy allocation. | 201 // TODO(fbarchard): Support lazy allocation. |
212 int new_width = dw; | 202 int new_width = dw; |
213 int new_height = dh; | 203 int new_height = dh; |
214 // If rotated swap width, height. | 204 // If rotated swap width, height. |
215 if (apply_rotation && (rotation == 90 || rotation == 270)) { | 205 if (apply_rotation && (rotation == 90 || rotation == 270)) { |
216 new_width = dh; | 206 new_width = dh; |
217 new_height = dw; | 207 new_height = dw; |
218 } | 208 } |
219 | 209 |
220 InitToEmptyBuffer(new_width, new_height, pixel_width, pixel_height, | 210 InitToEmptyBuffer(new_width, new_height, |
221 time_stamp_ns); | 211 time_stamp_ns); |
222 rotation_ = apply_rotation ? webrtc::kVideoRotation_0 : rotation; | 212 rotation_ = apply_rotation ? webrtc::kVideoRotation_0 : rotation; |
223 | 213 |
224 int horiz_crop = ((w - dw) / 2) & ~1; | 214 int horiz_crop = ((w - dw) / 2) & ~1; |
225 // ARGB on Windows has negative height. | 215 // ARGB on Windows has negative height. |
226 // The sample's layout in memory is normal, so just correct crop. | 216 // The sample's layout in memory is normal, so just correct crop. |
227 int vert_crop = ((abs(h) - dh) / 2) & ~1; | 217 int vert_crop = ((abs(h) - dh) / 2) & ~1; |
228 // Conversion functions expect negative height to flip the image. | 218 // Conversion functions expect negative height to flip the image. |
229 int idh = (h < 0) ? -dh : dh; | 219 int idh = (h < 0) ? -dh : dh; |
230 int r = libyuv::ConvertToI420( | 220 int r = libyuv::ConvertToI420( |
231 sample, sample_size, | 221 sample, sample_size, |
232 GetYPlane(), GetYPitch(), | 222 GetYPlane(), GetYPitch(), |
233 GetUPlane(), GetUPitch(), | 223 GetUPlane(), GetUPitch(), |
234 GetVPlane(), GetVPitch(), | 224 GetVPlane(), GetVPitch(), |
235 horiz_crop, vert_crop, | 225 horiz_crop, vert_crop, |
236 w, h, | 226 w, h, |
237 dw, idh, | 227 dw, idh, |
238 static_cast<libyuv::RotationMode>( | 228 static_cast<libyuv::RotationMode>( |
239 apply_rotation ? rotation : webrtc::kVideoRotation_0), | 229 apply_rotation ? rotation : webrtc::kVideoRotation_0), |
240 format); | 230 format); |
241 if (r) { | 231 if (r) { |
242 LOG(LS_ERROR) << "Error parsing format: " << GetFourccName(format) | 232 LOG(LS_ERROR) << "Error parsing format: " << GetFourccName(format) |
243 << " return code : " << r; | 233 << " return code : " << r; |
244 return false; | 234 return false; |
245 } | 235 } |
246 return true; | 236 return true; |
247 } | 237 } |
248 | 238 |
249 VideoFrame* WebRtcVideoFrame::CreateEmptyFrame( | 239 VideoFrame* WebRtcVideoFrame::CreateEmptyFrame( |
250 int w, int h, size_t pixel_width, size_t pixel_height, | 240 int w, int h, |
251 int64_t time_stamp_ns) const { | 241 int64_t time_stamp_ns) const { |
252 WebRtcVideoFrame* frame = new WebRtcVideoFrame(); | 242 WebRtcVideoFrame* frame = new WebRtcVideoFrame(); |
253 frame->InitToEmptyBuffer(w, h, pixel_width, pixel_height, time_stamp_ns); | 243 frame->InitToEmptyBuffer(w, h, time_stamp_ns); |
254 return frame; | 244 return frame; |
255 } | 245 } |
256 | 246 |
257 void WebRtcVideoFrame::InitToEmptyBuffer(int w, int h, size_t pixel_width, | 247 void WebRtcVideoFrame::InitToEmptyBuffer(int w, int h, |
258 size_t pixel_height, | |
259 int64_t time_stamp_ns) { | 248 int64_t time_stamp_ns) { |
260 video_frame_buffer_ = new rtc::RefCountedObject<webrtc::I420Buffer>(w, h); | 249 video_frame_buffer_ = new rtc::RefCountedObject<webrtc::I420Buffer>(w, h); |
261 pixel_width_ = pixel_width; | |
262 pixel_height_ = pixel_height; | |
263 time_stamp_ns_ = time_stamp_ns; | 250 time_stamp_ns_ = time_stamp_ns; |
264 rotation_ = webrtc::kVideoRotation_0; | 251 rotation_ = webrtc::kVideoRotation_0; |
265 } | 252 } |
266 | 253 |
267 const VideoFrame* WebRtcVideoFrame::GetCopyWithRotationApplied() const { | 254 const VideoFrame* WebRtcVideoFrame::GetCopyWithRotationApplied() const { |
268 // If the frame is not rotated, the caller should reuse this frame instead of | 255 // If the frame is not rotated, the caller should reuse this frame instead of |
269 // making a redundant copy. | 256 // making a redundant copy. |
270 if (GetVideoRotation() == webrtc::kVideoRotation_0) { | 257 if (GetVideoRotation() == webrtc::kVideoRotation_0) { |
271 return this; | 258 return this; |
272 } | 259 } |
(...skipping 12 matching lines...) Expand all Loading... |
285 | 272 |
286 int rotated_width = width; | 273 int rotated_width = width; |
287 int rotated_height = height; | 274 int rotated_height = height; |
288 if (GetVideoRotation() == webrtc::kVideoRotation_90 || | 275 if (GetVideoRotation() == webrtc::kVideoRotation_90 || |
289 GetVideoRotation() == webrtc::kVideoRotation_270) { | 276 GetVideoRotation() == webrtc::kVideoRotation_270) { |
290 rotated_width = height; | 277 rotated_width = height; |
291 rotated_height = width; | 278 rotated_height = width; |
292 } | 279 } |
293 | 280 |
294 rotated_frame_.reset(CreateEmptyFrame(rotated_width, rotated_height, | 281 rotated_frame_.reset(CreateEmptyFrame(rotated_width, rotated_height, |
295 GetPixelWidth(), GetPixelHeight(), | |
296 GetTimeStamp())); | 282 GetTimeStamp())); |
297 | 283 |
298 // TODO(guoweis): Add a function in webrtc_libyuv.cc to convert from | 284 // TODO(guoweis): Add a function in webrtc_libyuv.cc to convert from |
299 // VideoRotation to libyuv::RotationMode. | 285 // VideoRotation to libyuv::RotationMode. |
300 int ret = libyuv::I420Rotate( | 286 int ret = libyuv::I420Rotate( |
301 GetYPlane(), GetYPitch(), GetUPlane(), GetUPitch(), GetVPlane(), | 287 GetYPlane(), GetYPitch(), GetUPlane(), GetUPitch(), GetVPlane(), |
302 GetVPitch(), rotated_frame_->GetYPlane(), rotated_frame_->GetYPitch(), | 288 GetVPitch(), rotated_frame_->GetYPlane(), rotated_frame_->GetYPitch(), |
303 rotated_frame_->GetUPlane(), rotated_frame_->GetUPitch(), | 289 rotated_frame_->GetUPlane(), rotated_frame_->GetUPitch(), |
304 rotated_frame_->GetVPlane(), rotated_frame_->GetVPitch(), width, height, | 290 rotated_frame_->GetVPlane(), rotated_frame_->GetVPitch(), width, height, |
305 static_cast<libyuv::RotationMode>(GetVideoRotation())); | 291 static_cast<libyuv::RotationMode>(GetVideoRotation())); |
306 if (ret == 0) { | 292 if (ret == 0) { |
307 return rotated_frame_.get(); | 293 return rotated_frame_.get(); |
308 } | 294 } |
309 return nullptr; | 295 return nullptr; |
310 } | 296 } |
311 | 297 |
312 } // namespace cricket | 298 } // namespace cricket |
OLD | NEW |