Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include "webrtc/media/engine/webrtcvideoframe.h" | 11 #include "webrtc/media/engine/webrtcvideoframe.h" |
| 12 | 12 |
| 13 #include "libyuv/convert.h" | 13 #include "libyuv/convert.h" |
| 14 #include "webrtc/base/logging.h" | 14 #include "webrtc/base/logging.h" |
| 15 #include "webrtc/media/base/videocapturer.h" | 15 #include "webrtc/media/base/videocapturer.h" |
| 16 #include "webrtc/media/base/videocommon.h" | 16 #include "webrtc/media/base/videocommon.h" |
| 17 #include "webrtc/video_frame.h" | 17 #include "webrtc/video_frame.h" |
| 18 | 18 |
| 19 using webrtc::kYPlane; | 19 using webrtc::kYPlane; |
| 20 using webrtc::kUPlane; | 20 using webrtc::kUPlane; |
| 21 using webrtc::kVPlane; | 21 using webrtc::kVPlane; |
| 22 | 22 |
| 23 namespace cricket { | 23 namespace cricket { |
| 24 | 24 |
| 25 WebRtcVideoFrame::WebRtcVideoFrame(): | 25 WebRtcVideoFrame::WebRtcVideoFrame() |
| 26 time_stamp_ns_(0), | 26 : timestamp_us_(0), rotation_(webrtc::kVideoRotation_0) {} |
| 27 rotation_(webrtc::kVideoRotation_0) {} | |
| 28 | 27 |
| 29 WebRtcVideoFrame::WebRtcVideoFrame( | 28 WebRtcVideoFrame::WebRtcVideoFrame( |
| 30 const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& buffer, | 29 const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& buffer, |
| 31 int64_t time_stamp_ns, | 30 int64_t time_stamp_ns, |
| 32 webrtc::VideoRotation rotation) | 31 webrtc::VideoRotation rotation) |
| 33 : video_frame_buffer_(buffer), | 32 : video_frame_buffer_(buffer), |
| 34 time_stamp_ns_(time_stamp_ns), | |
| 35 rotation_(rotation) { | 33 rotation_(rotation) { |
| 34 // Convert to usecs. | |
| 35 SetTimeStamp(time_stamp_ns); | |
| 36 } | 36 } |
| 37 | 37 |
| 38 WebRtcVideoFrame::~WebRtcVideoFrame() {} | 38 WebRtcVideoFrame::~WebRtcVideoFrame() {} |
| 39 | 39 |
| 40 bool WebRtcVideoFrame::Init(uint32_t format, | 40 bool WebRtcVideoFrame::Init(uint32_t format, |
| 41 int w, | 41 int w, |
| 42 int h, | 42 int h, |
| 43 int dw, | 43 int dw, |
| 44 int dh, | 44 int dh, |
| 45 uint8_t* sample, | 45 uint8_t* sample, |
| 46 size_t sample_size, | 46 size_t sample_size, |
| 47 int64_t time_stamp_ns, | 47 int64_t time_stamp_ns, |
| 48 webrtc::VideoRotation rotation) { | 48 webrtc::VideoRotation rotation) { |
| 49 return Reset(format, w, h, dw, dh, sample, sample_size, | 49 if (!Reset(format, w, h, dw, dh, sample, sample_size, rotation, |
| 50 time_stamp_ns, rotation, | 50 true /*apply_rotation*/)) |
| 51 true /*apply_rotation*/); | 51 return false; |
| 52 | |
| 53 SetTimeStamp(time_stamp_ns); | |
| 54 return true; | |
| 52 } | 55 } |
| 53 | 56 |
| 54 bool WebRtcVideoFrame::Init(const CapturedFrame* frame, int dw, int dh, | 57 bool WebRtcVideoFrame::Init(const CapturedFrame* frame, int dw, int dh, |
| 55 bool apply_rotation) { | 58 bool apply_rotation) { |
| 56 return Reset(frame->fourcc, frame->width, frame->height, dw, dh, | 59 if (!Reset(frame->fourcc, frame->width, frame->height, dw, dh, |
| 57 static_cast<uint8_t*>(frame->data), frame->data_size, | 60 static_cast<uint8_t*>(frame->data), frame->data_size, |
| 58 frame->time_stamp, | 61 frame->rotation, apply_rotation)) { |
| 59 frame->rotation, apply_rotation); | 62 return false; |
| 63 } | |
| 64 SetTimeStamp(frame->time_stamp); | |
| 65 | |
| 66 return true; | |
| 60 } | 67 } |
| 61 | 68 |
| 62 bool WebRtcVideoFrame::InitToBlack(int w, int h, | 69 bool WebRtcVideoFrame::InitToBlack(int w, int h, |
| 63 int64_t time_stamp_ns) { | 70 int64_t time_stamp_ns) { |
| 64 InitToEmptyBuffer(w, h, time_stamp_ns); | 71 InitToEmptyBuffer(w, h, time_stamp_ns); |
| 65 return SetToBlack(); | 72 return SetToBlack(); |
| 66 } | 73 } |
| 67 | 74 |
| 68 int WebRtcVideoFrame::width() const { | 75 int WebRtcVideoFrame::width() const { |
| 69 return video_frame_buffer_ ? video_frame_buffer_->width() : 0; | 76 return video_frame_buffer_ ? video_frame_buffer_->width() : 0; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 120 return video_frame_buffer_ ? video_frame_buffer_->native_handle() : nullptr; | 127 return video_frame_buffer_ ? video_frame_buffer_->native_handle() : nullptr; |
| 121 } | 128 } |
| 122 | 129 |
| 123 rtc::scoped_refptr<webrtc::VideoFrameBuffer> | 130 rtc::scoped_refptr<webrtc::VideoFrameBuffer> |
| 124 WebRtcVideoFrame::GetVideoFrameBuffer() const { | 131 WebRtcVideoFrame::GetVideoFrameBuffer() const { |
| 125 return video_frame_buffer_; | 132 return video_frame_buffer_; |
| 126 } | 133 } |
| 127 | 134 |
| 128 VideoFrame* WebRtcVideoFrame::Copy() const { | 135 VideoFrame* WebRtcVideoFrame::Copy() const { |
| 129 WebRtcVideoFrame* new_frame = new WebRtcVideoFrame( | 136 WebRtcVideoFrame* new_frame = new WebRtcVideoFrame( |
| 130 video_frame_buffer_, time_stamp_ns_, rotation_); | 137 video_frame_buffer_, 0 /* Dummy timestamp, overwridden below */, |
|
pbos-webrtc
2016/04/13 12:04:04
That seems weird? rtc::kNumNanosecsPerMicrosec * t
nisse-webrtc
2016/04/13 13:02:12
I added a constructor with us timestamp (and argum
| |
| 138 rotation_); | |
| 139 new_frame->set_timestamp_us(timestamp_us_); | |
| 131 return new_frame; | 140 return new_frame; |
| 132 } | 141 } |
| 133 | 142 |
| 134 size_t WebRtcVideoFrame::ConvertToRgbBuffer(uint32_t to_fourcc, | 143 size_t WebRtcVideoFrame::ConvertToRgbBuffer(uint32_t to_fourcc, |
| 135 uint8_t* buffer, | 144 uint8_t* buffer, |
| 136 size_t size, | 145 size_t size, |
| 137 int stride_rgb) const { | 146 int stride_rgb) const { |
| 138 RTC_CHECK(video_frame_buffer_); | 147 RTC_CHECK(video_frame_buffer_); |
| 139 RTC_CHECK(video_frame_buffer_->native_handle() == nullptr); | 148 RTC_CHECK(video_frame_buffer_->native_handle() == nullptr); |
| 140 return VideoFrame::ConvertToRgbBuffer(to_fourcc, buffer, size, stride_rgb); | 149 return VideoFrame::ConvertToRgbBuffer(to_fourcc, buffer, size, stride_rgb); |
| 141 } | 150 } |
| 142 | 151 |
| 143 bool WebRtcVideoFrame::Reset(uint32_t format, | 152 bool WebRtcVideoFrame::Reset(uint32_t format, |
| 144 int w, | 153 int w, |
| 145 int h, | 154 int h, |
| 146 int dw, | 155 int dw, |
| 147 int dh, | 156 int dh, |
| 148 uint8_t* sample, | 157 uint8_t* sample, |
| 149 size_t sample_size, | 158 size_t sample_size, |
| 150 int64_t time_stamp_ns, | |
| 151 webrtc::VideoRotation rotation, | 159 webrtc::VideoRotation rotation, |
| 152 bool apply_rotation) { | 160 bool apply_rotation) { |
| 153 if (!Validate(format, w, h, sample, sample_size)) { | 161 if (!Validate(format, w, h, sample, sample_size)) { |
| 154 return false; | 162 return false; |
| 155 } | 163 } |
| 156 // Translate aliases to standard enums (e.g., IYUV -> I420). | 164 // Translate aliases to standard enums (e.g., IYUV -> I420). |
| 157 format = CanonicalFourCC(format); | 165 format = CanonicalFourCC(format); |
| 158 | 166 |
| 159 // Set up a new buffer. | 167 // Set up a new buffer. |
| 160 // TODO(fbarchard): Support lazy allocation. | 168 // TODO(fbarchard): Support lazy allocation. |
| 161 int new_width = dw; | 169 int new_width = dw; |
| 162 int new_height = dh; | 170 int new_height = dh; |
| 163 // If rotated swap width, height. | 171 // If rotated swap width, height. |
| 164 if (apply_rotation && (rotation == 90 || rotation == 270)) { | 172 if (apply_rotation && (rotation == 90 || rotation == 270)) { |
| 165 new_width = dh; | 173 new_width = dh; |
| 166 new_height = dw; | 174 new_height = dw; |
| 167 } | 175 } |
| 168 | 176 |
| 169 InitToEmptyBuffer(new_width, new_height, | 177 InitToEmptyBuffer(new_width, new_height); |
| 170 time_stamp_ns); | |
| 171 rotation_ = apply_rotation ? webrtc::kVideoRotation_0 : rotation; | 178 rotation_ = apply_rotation ? webrtc::kVideoRotation_0 : rotation; |
| 172 | 179 |
| 173 int horiz_crop = ((w - dw) / 2) & ~1; | 180 int horiz_crop = ((w - dw) / 2) & ~1; |
| 174 // ARGB on Windows has negative height. | 181 // ARGB on Windows has negative height. |
| 175 // The sample's layout in memory is normal, so just correct crop. | 182 // The sample's layout in memory is normal, so just correct crop. |
| 176 int vert_crop = ((abs(h) - dh) / 2) & ~1; | 183 int vert_crop = ((abs(h) - dh) / 2) & ~1; |
| 177 // Conversion functions expect negative height to flip the image. | 184 // Conversion functions expect negative height to flip the image. |
| 178 int idh = (h < 0) ? -dh : dh; | 185 int idh = (h < 0) ? -dh : dh; |
| 179 int r = libyuv::ConvertToI420( | 186 int r = libyuv::ConvertToI420( |
| 180 sample, sample_size, | 187 sample, sample_size, |
| 181 GetYPlane(), GetYPitch(), | 188 GetYPlane(), GetYPitch(), |
| 182 GetUPlane(), GetUPitch(), | 189 GetUPlane(), GetUPitch(), |
| 183 GetVPlane(), GetVPitch(), | 190 GetVPlane(), GetVPitch(), |
| 184 horiz_crop, vert_crop, | 191 horiz_crop, vert_crop, |
| 185 w, h, | 192 w, h, |
| 186 dw, idh, | 193 dw, idh, |
| 187 static_cast<libyuv::RotationMode>( | 194 static_cast<libyuv::RotationMode>( |
| 188 apply_rotation ? rotation : webrtc::kVideoRotation_0), | 195 apply_rotation ? rotation : webrtc::kVideoRotation_0), |
| 189 format); | 196 format); |
| 190 if (r) { | 197 if (r) { |
| 191 LOG(LS_ERROR) << "Error parsing format: " << GetFourccName(format) | 198 LOG(LS_ERROR) << "Error parsing format: " << GetFourccName(format) |
| 192 << " return code : " << r; | 199 << " return code : " << r; |
| 193 return false; | 200 return false; |
| 194 } | 201 } |
| 195 return true; | 202 return true; |
| 196 } | 203 } |
| 197 | 204 |
| 198 VideoFrame* WebRtcVideoFrame::CreateEmptyFrame( | 205 VideoFrame* WebRtcVideoFrame::CreateEmptyFrame( |
| 199 int w, int h, | 206 int w, int h, |
|
pbos-webrtc
2016/04/13 12:04:04
git cl format here
nisse-webrtc
2016/04/13 13:02:12
Done.
| |
| 200 int64_t time_stamp_ns) const { | 207 int64_t timestamp_us) const { |
| 201 WebRtcVideoFrame* frame = new WebRtcVideoFrame(); | 208 WebRtcVideoFrame* frame = new WebRtcVideoFrame(); |
| 202 frame->InitToEmptyBuffer(w, h, time_stamp_ns); | 209 frame->InitToEmptyBuffer(w, h, rtc::kNumNanosecsPerMicrosec * timestamp_us); |
| 203 return frame; | 210 return frame; |
| 204 } | 211 } |
| 205 | 212 |
| 213 void WebRtcVideoFrame::InitToEmptyBuffer(int w, int h) { | |
| 214 video_frame_buffer_ = new rtc::RefCountedObject<webrtc::I420Buffer>(w, h); | |
| 215 rotation_ = webrtc::kVideoRotation_0; | |
| 216 } | |
| 217 | |
| 206 void WebRtcVideoFrame::InitToEmptyBuffer(int w, int h, | 218 void WebRtcVideoFrame::InitToEmptyBuffer(int w, int h, |
| 207 int64_t time_stamp_ns) { | 219 int64_t time_stamp_ns) { |
| 208 video_frame_buffer_ = new rtc::RefCountedObject<webrtc::I420Buffer>(w, h); | 220 video_frame_buffer_ = new rtc::RefCountedObject<webrtc::I420Buffer>(w, h); |
| 209 time_stamp_ns_ = time_stamp_ns; | 221 SetTimeStamp(time_stamp_ns); |
| 210 rotation_ = webrtc::kVideoRotation_0; | 222 rotation_ = webrtc::kVideoRotation_0; |
| 211 } | 223 } |
| 212 | 224 |
| 213 const VideoFrame* WebRtcVideoFrame::GetCopyWithRotationApplied() const { | 225 const VideoFrame* WebRtcVideoFrame::GetCopyWithRotationApplied() const { |
| 214 // If the frame is not rotated, the caller should reuse this frame instead of | 226 // If the frame is not rotated, the caller should reuse this frame instead of |
| 215 // making a redundant copy. | 227 // making a redundant copy. |
| 216 if (GetVideoRotation() == webrtc::kVideoRotation_0) { | 228 if (GetVideoRotation() == webrtc::kVideoRotation_0) { |
| 217 return this; | 229 return this; |
| 218 } | 230 } |
| 219 | 231 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 230 int orig_height = height(); | 242 int orig_height = height(); |
| 231 | 243 |
| 232 int rotated_width = orig_width; | 244 int rotated_width = orig_width; |
| 233 int rotated_height = orig_height; | 245 int rotated_height = orig_height; |
| 234 if (GetVideoRotation() == webrtc::kVideoRotation_90 || | 246 if (GetVideoRotation() == webrtc::kVideoRotation_90 || |
| 235 GetVideoRotation() == webrtc::kVideoRotation_270) { | 247 GetVideoRotation() == webrtc::kVideoRotation_270) { |
| 236 rotated_width = orig_height; | 248 rotated_width = orig_height; |
| 237 rotated_height = orig_width; | 249 rotated_height = orig_width; |
| 238 } | 250 } |
| 239 | 251 |
| 240 rotated_frame_.reset(CreateEmptyFrame(rotated_width, rotated_height, | 252 rotated_frame_.reset( |
| 241 GetTimeStamp())); | 253 CreateEmptyFrame(rotated_width, rotated_height, timestamp_us_)); |
| 242 | 254 |
| 243 // TODO(guoweis): Add a function in webrtc_libyuv.cc to convert from | 255 // TODO(guoweis): Add a function in webrtc_libyuv.cc to convert from |
| 244 // VideoRotation to libyuv::RotationMode. | 256 // VideoRotation to libyuv::RotationMode. |
| 245 int ret = libyuv::I420Rotate( | 257 int ret = libyuv::I420Rotate( |
| 246 GetYPlane(), GetYPitch(), GetUPlane(), GetUPitch(), GetVPlane(), | 258 GetYPlane(), GetYPitch(), GetUPlane(), GetUPitch(), GetVPlane(), |
| 247 GetVPitch(), rotated_frame_->GetYPlane(), rotated_frame_->GetYPitch(), | 259 GetVPitch(), rotated_frame_->GetYPlane(), rotated_frame_->GetYPitch(), |
| 248 rotated_frame_->GetUPlane(), rotated_frame_->GetUPitch(), | 260 rotated_frame_->GetUPlane(), rotated_frame_->GetUPitch(), |
| 249 rotated_frame_->GetVPlane(), rotated_frame_->GetVPitch(), | 261 rotated_frame_->GetVPlane(), rotated_frame_->GetVPitch(), |
| 250 orig_width, orig_height, | 262 orig_width, orig_height, |
| 251 static_cast<libyuv::RotationMode>(GetVideoRotation())); | 263 static_cast<libyuv::RotationMode>(GetVideoRotation())); |
| 252 if (ret == 0) { | 264 if (ret == 0) { |
| 253 return rotated_frame_.get(); | 265 return rotated_frame_.get(); |
| 254 } | 266 } |
| 255 return nullptr; | 267 return nullptr; |
| 256 } | 268 } |
| 257 | 269 |
| 258 } // namespace cricket | 270 } // namespace cricket |
| OLD | NEW |