OLD | NEW |
1 /* | 1 /* |
2 * libjingle | 2 * libjingle |
3 * Copyright 2015 Google Inc. | 3 * Copyright 2015 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 captured_frame_.data_size = cricket::CapturedFrame::kUnknownDataSize; | 64 captured_frame_.data_size = cricket::CapturedFrame::kUnknownDataSize; |
65 captured_frame_.fourcc = static_cast<uint32>(cricket::FOURCC_ANY); | 65 captured_frame_.fourcc = static_cast<uint32>(cricket::FOURCC_ANY); |
66 } | 66 } |
67 | 67 |
68 void UpdateCapturedFrame(void* frame_data, | 68 void UpdateCapturedFrame(void* frame_data, |
69 int length, | 69 int length, |
70 int width, | 70 int width, |
71 int height, | 71 int height, |
72 int rotation, | 72 int rotation, |
73 int64 time_stamp_in_ns) { | 73 int64 time_stamp_in_ns) { |
| 74 // Make sure we don't overwrite the previous frame. |
| 75 CHECK(captured_frame_.data == nullptr); |
74 captured_frame_.fourcc = static_cast<uint32>(cricket::FOURCC_YV12); | 76 captured_frame_.fourcc = static_cast<uint32>(cricket::FOURCC_YV12); |
75 captured_frame_.data = frame_data; | 77 captured_frame_.data = frame_data; |
76 captured_frame_.width = width; | 78 captured_frame_.width = width; |
77 captured_frame_.height = height; | 79 captured_frame_.height = height; |
78 captured_frame_.elapsed_time = rtc::TimeNanos() - start_time_; | 80 captured_frame_.elapsed_time = rtc::TimeNanos() - start_time_; |
79 captured_frame_.time_stamp = time_stamp_in_ns; | 81 captured_frame_.time_stamp = time_stamp_in_ns; |
80 captured_frame_.rotation = rotation; | 82 captured_frame_.rotation = rotation; |
81 captured_frame_.data_size = length; | 83 captured_frame_.data_size = length; |
82 } | 84 } |
83 | 85 |
| 86 void ClearCapturedFrame() const { |
| 87 captured_frame_.data = nullptr; |
| 88 captured_frame_.width = 0; |
| 89 captured_frame_.height = 0; |
| 90 captured_frame_.elapsed_time = 0; |
| 91 captured_frame_.time_stamp = 0; |
| 92 captured_frame_.data_size = 0; |
| 93 } |
| 94 |
84 const cricket::CapturedFrame* GetCapturedFrame() const { | 95 const cricket::CapturedFrame* GetCapturedFrame() const { |
85 return &captured_frame_; | 96 return &captured_frame_; |
86 } | 97 } |
87 | 98 |
88 cricket::VideoFrame* CreateAliasedFrame( | 99 cricket::VideoFrame* CreateAliasedFrame( |
89 const cricket::CapturedFrame* captured_frame, | 100 const cricket::CapturedFrame* captured_frame, |
90 int dst_width, | 101 int dst_width, |
91 int dst_height) const override { | 102 int dst_height) const override { |
92 // This override of CreateAliasedFrame creates a copy of the frame since | 103 // This override of CreateAliasedFrame creates a copy of the frame since |
93 // |captured_frame_.data| is only guaranteed to be valid during the scope | 104 // |captured_frame_.data| is only guaranteed to be valid during the scope |
94 // of |AndroidVideoCapturer::OnIncomingFrame_w|. | 105 // of |AndroidVideoCapturer::OnIncomingFrame_w|. |
95 // Check that captured_frame is actually our frame. | 106 // Check that captured_frame is actually our frame. |
96 CHECK(captured_frame == &captured_frame_); | 107 CHECK(captured_frame == &captured_frame_); |
| 108 CHECK(captured_frame->data != nullptr); |
97 | 109 |
98 if (!apply_rotation_ || captured_frame->rotation == kVideoRotation_0) { | 110 if (!apply_rotation_ || captured_frame->rotation == kVideoRotation_0) { |
99 CHECK(captured_frame->fourcc == cricket::FOURCC_YV12); | 111 CHECK(captured_frame->fourcc == cricket::FOURCC_YV12); |
100 const uint8_t* y_plane = static_cast<uint8_t*>(captured_frame_.data); | 112 const uint8_t* y_plane = static_cast<uint8_t*>(captured_frame_.data); |
101 | 113 |
102 // Android guarantees that the stride is a multiple of 16. | 114 // Android guarantees that the stride is a multiple of 16. |
103 // http://developer.android.com/reference/android/hardware/Camera.Paramete
rs.html#setPreviewFormat%28int%29 | 115 // http://developer.android.com/reference/android/hardware/Camera.Paramete
rs.html#setPreviewFormat%28int%29 |
104 int y_stride; | 116 int y_stride; |
105 int uv_stride; | 117 int uv_stride; |
106 webrtc::Calc16ByteAlignedStride(captured_frame->width, &y_stride, | 118 webrtc::Calc16ByteAlignedStride(captured_frame->width, &y_stride, |
107 &uv_stride); | 119 &uv_stride); |
108 const uint8_t* v_plane = y_plane + y_stride * captured_frame->height; | 120 const uint8_t* v_plane = y_plane + y_stride * captured_frame->height; |
109 const uint8_t* u_plane = | 121 const uint8_t* u_plane = |
110 v_plane + uv_stride * webrtc::AlignInt(captured_frame->height, 2) / 2; | 122 v_plane + uv_stride * webrtc::AlignInt(captured_frame->height, 2) / 2; |
111 | 123 |
112 // Create a WrappedI420Buffer and bind the |no_longer_used| callback | 124 // Create a WrappedI420Buffer and bind the |no_longer_used| callback |
113 // to the static method ReturnFrame. The |delegate_| is bound as an | 125 // to the static method ReturnFrame. The |delegate_| is bound as an |
114 // argument which means that the callback will hold a reference to | 126 // argument which means that the callback will hold a reference to |
115 // |delegate_|. | 127 // |delegate_|. |
116 rtc::scoped_refptr<WrappedI420Buffer> buffer( | 128 rtc::scoped_refptr<WrappedI420Buffer> buffer( |
117 new rtc::RefCountedObject<webrtc::WrappedI420Buffer>( | 129 new rtc::RefCountedObject<webrtc::WrappedI420Buffer>( |
118 dst_width, dst_height, captured_frame->width, | 130 dst_width, dst_height, captured_frame->width, |
119 captured_frame->height, y_plane, y_stride, u_plane, uv_stride, | 131 captured_frame->height, y_plane, y_stride, u_plane, uv_stride, |
120 v_plane, uv_stride, | 132 v_plane, uv_stride, |
121 rtc::Bind(&AndroidVideoCapturer::FrameFactory::ReturnFrame, | 133 rtc::Bind(&AndroidVideoCapturer::FrameFactory::ReturnFrame, |
122 delegate_, | 134 delegate_, |
123 captured_frame->time_stamp))); | 135 captured_frame->time_stamp))); |
124 return new WebRtcVideoFrame( | 136 cricket::VideoFrame* cricket_frame = new WebRtcVideoFrame( |
125 buffer, captured_frame->elapsed_time, | 137 buffer, captured_frame->elapsed_time, |
126 captured_frame->time_stamp, captured_frame->GetRotation()); | 138 captured_frame->time_stamp, captured_frame->GetRotation()); |
| 139 // |cricket_frame| is now responsible for returning the frame. Clear |
| 140 // |captured_frame_| so the frame isn't returned twice. |
| 141 ClearCapturedFrame(); |
| 142 return cricket_frame; |
127 } | 143 } |
128 | 144 |
129 scoped_ptr<WebRtcVideoFrame> frame(new WebRtcVideoFrame()); | 145 scoped_ptr<WebRtcVideoFrame> frame(new WebRtcVideoFrame()); |
130 frame->Init(captured_frame, dst_width, dst_height, apply_rotation_); | 146 frame->Init(captured_frame, dst_width, dst_height, apply_rotation_); |
131 // frame->Init copies the data in |captured_frame| so it is safe to return | |
132 // the buffer immediately. | |
133 delegate_->ReturnBuffer(captured_frame->time_stamp); | |
134 return frame.release(); | 147 return frame.release(); |
135 } | 148 } |
136 | 149 |
137 static void ReturnFrame(scoped_refptr<AndroidVideoCapturerDelegate> delegate, | 150 static void ReturnFrame(scoped_refptr<AndroidVideoCapturerDelegate> delegate, |
138 int64 time_stamp) { | 151 int64 time_stamp) { |
139 delegate->ReturnBuffer(time_stamp); | 152 delegate->ReturnBuffer(time_stamp); |
140 } | 153 } |
141 | 154 |
142 private: | 155 private: |
143 uint64 start_time_; | 156 uint64 start_time_; |
144 cricket::CapturedFrame captured_frame_; | 157 // |captured_frame_| is mutable as a hacky way to modify it inside |
| 158 // CreateAliasedframe(). |
| 159 mutable cricket::CapturedFrame captured_frame_; |
145 scoped_refptr<AndroidVideoCapturerDelegate> delegate_; | 160 scoped_refptr<AndroidVideoCapturerDelegate> delegate_; |
146 }; | 161 }; |
147 | 162 |
148 AndroidVideoCapturer::AndroidVideoCapturer( | 163 AndroidVideoCapturer::AndroidVideoCapturer( |
149 const rtc::scoped_refptr<AndroidVideoCapturerDelegate>& delegate) | 164 const rtc::scoped_refptr<AndroidVideoCapturerDelegate>& delegate) |
150 : running_(false), | 165 : running_(false), |
151 delegate_(delegate), | 166 delegate_(delegate), |
152 frame_factory_(NULL), | 167 frame_factory_(NULL), |
153 current_state_(cricket::CS_STOPPED) { | 168 current_state_(cricket::CS_STOPPED) { |
154 thread_checker_.DetachFromThread(); | 169 thread_checker_.DetachFromThread(); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 void AndroidVideoCapturer::OnIncomingFrame(void* frame_data, | 255 void AndroidVideoCapturer::OnIncomingFrame(void* frame_data, |
241 int length, | 256 int length, |
242 int width, | 257 int width, |
243 int height, | 258 int height, |
244 int rotation, | 259 int rotation, |
245 int64 time_stamp) { | 260 int64 time_stamp) { |
246 CHECK(thread_checker_.CalledOnValidThread()); | 261 CHECK(thread_checker_.CalledOnValidThread()); |
247 frame_factory_->UpdateCapturedFrame(frame_data, length, width, height, | 262 frame_factory_->UpdateCapturedFrame(frame_data, length, width, height, |
248 rotation, time_stamp); | 263 rotation, time_stamp); |
249 SignalFrameCaptured(this, frame_factory_->GetCapturedFrame()); | 264 SignalFrameCaptured(this, frame_factory_->GetCapturedFrame()); |
| 265 if (frame_factory_->GetCapturedFrame()->data == nullptr) { |
| 266 // Ownership has been passed to a WrappedI420Buffer. Do nothing. |
| 267 } else { |
| 268 // |captured_frame_| has either been copied or dropped, return it |
| 269 // immediately. |
| 270 delegate_->ReturnBuffer(time_stamp); |
| 271 frame_factory_->ClearCapturedFrame(); |
| 272 } |
250 } | 273 } |
251 | 274 |
252 void AndroidVideoCapturer::OnOutputFormatRequest( | 275 void AndroidVideoCapturer::OnOutputFormatRequest( |
253 int width, int height, int fps) { | 276 int width, int height, int fps) { |
254 CHECK(thread_checker_.CalledOnValidThread()); | 277 CHECK(thread_checker_.CalledOnValidThread()); |
255 const cricket::VideoFormat& current = video_adapter()->output_format(); | 278 const cricket::VideoFormat& current = video_adapter()->output_format(); |
256 cricket::VideoFormat format( | 279 cricket::VideoFormat format( |
257 width, height, cricket::VideoFormat::FpsToInterval(fps), current.fourcc); | 280 width, height, cricket::VideoFormat::FpsToInterval(fps), current.fourcc); |
258 video_adapter()->OnOutputFormatRequest(format); | 281 video_adapter()->OnOutputFormatRequest(format); |
259 } | 282 } |
260 | 283 |
261 } // namespace webrtc | 284 } // namespace webrtc |
OLD | NEW |