| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/capture/video/video_capture_buffer_pool_impl.h" | 5 #include "media/capture/video/video_capture_buffer_pool_impl.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 } | 50 } |
| 51 | 51 |
| 52 DCHECK(tracker->held_by_producer()); | 52 DCHECK(tracker->held_by_producer()); |
| 53 return tracker->GetBufferHandle(); | 53 return tracker->GetBufferHandle(); |
| 54 } | 54 } |
| 55 | 55 |
| 56 int VideoCaptureBufferPoolImpl::ReserveForProducer( | 56 int VideoCaptureBufferPoolImpl::ReserveForProducer( |
| 57 const gfx::Size& dimensions, | 57 const gfx::Size& dimensions, |
| 58 media::VideoPixelFormat format, | 58 media::VideoPixelFormat format, |
| 59 media::VideoPixelStorage storage, | 59 media::VideoPixelStorage storage, |
| 60 int frame_feedback_id, |
| 60 int* buffer_id_to_drop) { | 61 int* buffer_id_to_drop) { |
| 61 base::AutoLock lock(lock_); | 62 base::AutoLock lock(lock_); |
| 62 return ReserveForProducerInternal(dimensions, format, storage, | 63 return ReserveForProducerInternal(dimensions, format, storage, |
| 63 buffer_id_to_drop); | 64 frame_feedback_id, buffer_id_to_drop); |
| 64 } | 65 } |
| 65 | 66 |
| 66 void VideoCaptureBufferPoolImpl::RelinquishProducerReservation(int buffer_id) { | 67 void VideoCaptureBufferPoolImpl::RelinquishProducerReservation(int buffer_id) { |
| 67 base::AutoLock lock(lock_); | 68 base::AutoLock lock(lock_); |
| 68 VideoCaptureBufferTracker* tracker = GetTracker(buffer_id); | 69 VideoCaptureBufferTracker* tracker = GetTracker(buffer_id); |
| 69 if (!tracker) { | 70 if (!tracker) { |
| 70 NOTREACHED() << "Invalid buffer_id."; | 71 NOTREACHED() << "Invalid buffer_id."; |
| 71 return; | 72 return; |
| 72 } | 73 } |
| 73 DCHECK(tracker->held_by_producer()); | 74 DCHECK(tracker->held_by_producer()); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 if (tracker->held_by_producer() || tracker->consumer_hold_count() > 0) | 145 if (tracker->held_by_producer() || tracker->consumer_hold_count() > 0) |
| 145 ++num_buffers_held; | 146 ++num_buffers_held; |
| 146 } | 147 } |
| 147 return static_cast<double>(num_buffers_held) / count_; | 148 return static_cast<double>(num_buffers_held) / count_; |
| 148 } | 149 } |
| 149 | 150 |
| 150 int VideoCaptureBufferPoolImpl::ReserveForProducerInternal( | 151 int VideoCaptureBufferPoolImpl::ReserveForProducerInternal( |
| 151 const gfx::Size& dimensions, | 152 const gfx::Size& dimensions, |
| 152 media::VideoPixelFormat pixel_format, | 153 media::VideoPixelFormat pixel_format, |
| 153 media::VideoPixelStorage storage_type, | 154 media::VideoPixelStorage storage_type, |
| 155 int frame_feedback_id, |
| 154 int* buffer_id_to_drop) { | 156 int* buffer_id_to_drop) { |
| 155 lock_.AssertAcquired(); | 157 lock_.AssertAcquired(); |
| 156 | 158 |
| 157 const size_t size_in_pixels = dimensions.GetArea(); | 159 const size_t size_in_pixels = dimensions.GetArea(); |
| 158 // Look for a tracker that's allocated, big enough, and not in use. Track the | 160 // Look for a tracker that's allocated, big enough, and not in use. Track the |
| 159 // largest one that's not big enough, in case we have to reallocate a tracker. | 161 // largest one that's not big enough, in case we have to reallocate a tracker. |
| 160 *buffer_id_to_drop = kInvalidId; | 162 *buffer_id_to_drop = kInvalidId; |
| 161 size_t largest_size_in_pixels = 0; | 163 size_t largest_size_in_pixels = 0; |
| 162 auto tracker_of_last_resort = trackers_.end(); | 164 auto tracker_of_last_resort = trackers_.end(); |
| 163 auto tracker_to_drop = trackers_.end(); | 165 auto tracker_to_drop = trackers_.end(); |
| 164 for (auto it = trackers_.begin(); it != trackers_.end(); ++it) { | 166 for (auto it = trackers_.begin(); it != trackers_.end(); ++it) { |
| 165 VideoCaptureBufferTracker* const tracker = it->second.get(); | 167 VideoCaptureBufferTracker* const tracker = it->second.get(); |
| 166 if (!tracker->consumer_hold_count() && !tracker->held_by_producer()) { | 168 if (!tracker->consumer_hold_count() && !tracker->held_by_producer()) { |
| 167 if (tracker->max_pixel_count() >= size_in_pixels && | 169 if (tracker->max_pixel_count() >= size_in_pixels && |
| 168 (tracker->pixel_format() == pixel_format) && | 170 (tracker->pixel_format() == pixel_format) && |
| 169 (tracker->storage_type() == storage_type)) { | 171 (tracker->storage_type() == storage_type)) { |
| 170 if (it->first == last_relinquished_buffer_id_) { | 172 if (it->first == last_relinquished_buffer_id_) { |
| 171 // This buffer would do just fine, but avoid returning it because the | 173 // This buffer would do just fine, but avoid returning it because the |
| 172 // client may want to resurrect it. It will be returned perforce if | 174 // client may want to resurrect it. It will be returned perforce if |
| 173 // the pool has reached it's maximum limit (see code below). | 175 // the pool has reached it's maximum limit (see code below). |
| 174 tracker_of_last_resort = it; | 176 tracker_of_last_resort = it; |
| 175 continue; | 177 continue; |
| 176 } | 178 } |
| 177 // Existing tracker is big enough and has correct format. Reuse it. | 179 // Existing tracker is big enough and has correct format. Reuse it. |
| 178 tracker->set_dimensions(dimensions); | 180 tracker->set_dimensions(dimensions); |
| 179 tracker->set_held_by_producer(true); | 181 tracker->set_held_by_producer(true); |
| 182 tracker->set_frame_feedback_id(frame_feedback_id); |
| 180 return it->first; | 183 return it->first; |
| 181 } | 184 } |
| 182 if (tracker->max_pixel_count() > largest_size_in_pixels) { | 185 if (tracker->max_pixel_count() > largest_size_in_pixels) { |
| 183 largest_size_in_pixels = tracker->max_pixel_count(); | 186 largest_size_in_pixels = tracker->max_pixel_count(); |
| 184 tracker_to_drop = it; | 187 tracker_to_drop = it; |
| 185 } | 188 } |
| 186 } | 189 } |
| 187 } | 190 } |
| 188 | 191 |
| 189 // Preferably grow the pool by creating a new tracker. If we're at maximum | 192 // Preferably grow the pool by creating a new tracker. If we're at maximum |
| 190 // size, then try using |tracker_of_last_resort| or reallocate by deleting an | 193 // size, then try using |tracker_of_last_resort| or reallocate by deleting an |
| 191 // existing one instead. | 194 // existing one instead. |
| 192 if (trackers_.size() == static_cast<size_t>(count_)) { | 195 if (trackers_.size() == static_cast<size_t>(count_)) { |
| 193 if (tracker_of_last_resort != trackers_.end()) { | 196 if (tracker_of_last_resort != trackers_.end()) { |
| 194 last_relinquished_buffer_id_ = kInvalidId; | 197 last_relinquished_buffer_id_ = kInvalidId; |
| 195 tracker_of_last_resort->second->set_dimensions(dimensions); | 198 tracker_of_last_resort->second->set_dimensions(dimensions); |
| 196 tracker_of_last_resort->second->set_held_by_producer(true); | 199 tracker_of_last_resort->second->set_held_by_producer(true); |
| 200 tracker_of_last_resort->second->set_frame_feedback_id(frame_feedback_id); |
| 197 return tracker_of_last_resort->first; | 201 return tracker_of_last_resort->first; |
| 198 } | 202 } |
| 199 if (tracker_to_drop == trackers_.end()) { | 203 if (tracker_to_drop == trackers_.end()) { |
| 200 // We're out of space, and can't find an unused tracker to reallocate. | 204 // We're out of space, and can't find an unused tracker to reallocate. |
| 201 return kInvalidId; | 205 return kInvalidId; |
| 202 } | 206 } |
| 203 if (tracker_to_drop->first == last_relinquished_buffer_id_) | 207 if (tracker_to_drop->first == last_relinquished_buffer_id_) |
| 204 last_relinquished_buffer_id_ = kInvalidId; | 208 last_relinquished_buffer_id_ = kInvalidId; |
| 205 *buffer_id_to_drop = tracker_to_drop->first; | 209 *buffer_id_to_drop = tracker_to_drop->first; |
| 206 trackers_.erase(tracker_to_drop); | 210 trackers_.erase(tracker_to_drop); |
| 207 } | 211 } |
| 208 | 212 |
| 209 // Create the new tracker. | 213 // Create the new tracker. |
| 210 const int buffer_id = next_buffer_id_++; | 214 const int buffer_id = next_buffer_id_++; |
| 211 | 215 |
| 212 std::unique_ptr<VideoCaptureBufferTracker> tracker = | 216 std::unique_ptr<VideoCaptureBufferTracker> tracker = |
| 213 buffer_tracker_factory_->CreateTracker(storage_type); | 217 buffer_tracker_factory_->CreateTracker(storage_type); |
| 214 // TODO(emircan): We pass the lock here to solve GMB allocation issue, see | 218 // TODO(emircan): We pass the lock here to solve GMB allocation issue, see |
| 215 // crbug.com/545238. | 219 // crbug.com/545238. |
| 216 if (!tracker->Init(dimensions, pixel_format, storage_type, &lock_)) { | 220 if (!tracker->Init(dimensions, pixel_format, storage_type, &lock_)) { |
| 217 DLOG(ERROR) << "Error initializing VideoCaptureBufferTracker"; | 221 DLOG(ERROR) << "Error initializing VideoCaptureBufferTracker"; |
| 218 return kInvalidId; | 222 return kInvalidId; |
| 219 } | 223 } |
| 220 | 224 |
| 221 tracker->set_held_by_producer(true); | 225 tracker->set_held_by_producer(true); |
| 226 tracker->set_frame_feedback_id(frame_feedback_id); |
| 222 trackers_[buffer_id] = std::move(tracker); | 227 trackers_[buffer_id] = std::move(tracker); |
| 223 | 228 |
| 224 return buffer_id; | 229 return buffer_id; |
| 225 } | 230 } |
| 226 | 231 |
| 227 VideoCaptureBufferTracker* VideoCaptureBufferPoolImpl::GetTracker( | 232 VideoCaptureBufferTracker* VideoCaptureBufferPoolImpl::GetTracker( |
| 228 int buffer_id) { | 233 int buffer_id) { |
| 229 auto it = trackers_.find(buffer_id); | 234 auto it = trackers_.find(buffer_id); |
| 230 return (it == trackers_.end()) ? nullptr : it->second.get(); | 235 return (it == trackers_.end()) ? nullptr : it->second.get(); |
| 231 } | 236 } |
| 232 | 237 |
| 233 } // namespace media | 238 } // namespace media |
| OLD | NEW |