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