| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 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/common_video/video_render_frames.h" | 11 #include "webrtc/common_video/video_render_frames.h" |
| 12 | 12 |
| 13 #include <utility> |
| 14 |
| 13 #include "webrtc/base/logging.h" | 15 #include "webrtc/base/logging.h" |
| 14 #include "webrtc/base/timeutils.h" | 16 #include "webrtc/base/timeutils.h" |
| 15 #include "webrtc/modules/include/module_common_types.h" | 17 #include "webrtc/modules/include/module_common_types.h" |
| 16 #include "webrtc/system_wrappers/include/trace.h" | 18 #include "webrtc/system_wrappers/include/trace.h" |
| 17 | 19 |
| 18 namespace webrtc { | 20 namespace webrtc { |
| 19 namespace { | 21 namespace { |
| 22 // Don't render frames with timestamp older than 500ms from now. |
| 23 const int kOldRenderTimestampMS = 500; |
| 24 // Don't render frames with timestamp more than 10s into the future. |
| 25 const int kFutureRenderTimestampMS = 10000; |
| 20 | 26 |
| 21 const uint32_t kEventMaxWaitTimeMs = 200; | 27 const uint32_t kEventMaxWaitTimeMs = 200; |
| 22 const uint32_t kMinRenderDelayMs = 10; | 28 const uint32_t kMinRenderDelayMs = 10; |
| 23 const uint32_t kMaxRenderDelayMs = 500; | 29 const uint32_t kMaxRenderDelayMs = 500; |
| 24 const size_t kMaxIncomingFramesBeforeLogged = 100; | 30 const size_t kMaxIncomingFramesBeforeLogged = 100; |
| 25 | 31 |
| 26 uint32_t EnsureValidRenderDelay(uint32_t render_delay) { | 32 uint32_t EnsureValidRenderDelay(uint32_t render_delay) { |
| 27 return (render_delay < kMinRenderDelayMs || render_delay > kMaxRenderDelayMs) | 33 return (render_delay < kMinRenderDelayMs || render_delay > kMaxRenderDelayMs) |
| 28 ? kMinRenderDelayMs | 34 ? kMinRenderDelayMs |
| 29 : render_delay; | 35 : render_delay; |
| 30 } | 36 } |
| 31 } // namespace | 37 } // namespace |
| 32 | 38 |
| 33 VideoRenderFrames::VideoRenderFrames(uint32_t render_delay_ms) | 39 VideoRenderFrames::VideoRenderFrames(uint32_t render_delay_ms) |
| 34 : render_delay_ms_(EnsureValidRenderDelay(render_delay_ms)) {} | 40 : render_delay_ms_(EnsureValidRenderDelay(render_delay_ms)) {} |
| 35 | 41 |
| 36 int32_t VideoRenderFrames::AddFrame(const VideoFrame& new_frame) { | 42 int32_t VideoRenderFrames::AddFrame(VideoFrame&& new_frame) { |
| 37 const int64_t time_now = rtc::TimeMillis(); | 43 const int64_t time_now = rtc::TimeMillis(); |
| 38 | 44 |
| 39 // Drop old frames only when there are other frames in the queue, otherwise, a | 45 // Drop old frames only when there are other frames in the queue, otherwise, a |
| 40 // really slow system never renders any frames. | 46 // really slow system never renders any frames. |
| 41 if (!incoming_frames_.empty() && | 47 if (!incoming_frames_.empty() && |
| 42 new_frame.render_time_ms() + KOldRenderTimestampMS < time_now) { | 48 new_frame.render_time_ms() + kOldRenderTimestampMS < time_now) { |
| 43 WEBRTC_TRACE(kTraceWarning, | 49 WEBRTC_TRACE(kTraceWarning, |
| 44 kTraceVideoRenderer, | 50 kTraceVideoRenderer, |
| 45 -1, | 51 -1, |
| 46 "%s: too old frame, timestamp=%u.", | 52 "%s: too old frame, timestamp=%u.", |
| 47 __FUNCTION__, | 53 __FUNCTION__, |
| 48 new_frame.timestamp()); | 54 new_frame.timestamp()); |
| 49 return -1; | 55 return -1; |
| 50 } | 56 } |
| 51 | 57 |
| 52 if (new_frame.render_time_ms() > time_now + KFutureRenderTimestampMS) { | 58 if (new_frame.render_time_ms() > time_now + kFutureRenderTimestampMS) { |
| 53 WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, -1, | 59 WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, -1, |
| 54 "%s: frame too long into the future, timestamp=%u.", | 60 "%s: frame too long into the future, timestamp=%u.", |
| 55 __FUNCTION__, new_frame.timestamp()); | 61 __FUNCTION__, new_frame.timestamp()); |
| 56 return -1; | 62 return -1; |
| 57 } | 63 } |
| 58 | 64 |
| 59 incoming_frames_.push_back(new_frame); | 65 if (new_frame.render_time_ms() < last_render_time_ms_) { |
| 66 WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, -1, |
| 67 "%s: frame scheduled out of order, render_time=%u, latest=%u.", |
| 68 __FUNCTION__, new_frame.render_time_ms(), |
| 69 last_render_time_ms_); |
| 70 // TODO(mflodman): Decide what to do when this happens. |
| 71 // See bug: https://bugs.chromium.org/p/webrtc/issues/detail?id=7253 |
| 72 } |
| 73 |
| 74 last_render_time_ms_ = new_frame.render_time_ms(); |
| 75 incoming_frames_.emplace_back(std::move(new_frame)); |
| 76 |
| 60 if (incoming_frames_.size() > kMaxIncomingFramesBeforeLogged) | 77 if (incoming_frames_.size() > kMaxIncomingFramesBeforeLogged) |
| 61 LOG(LS_WARNING) << "Stored incoming frames: " << incoming_frames_.size(); | 78 LOG(LS_WARNING) << "Stored incoming frames: " << incoming_frames_.size(); |
| 62 return static_cast<int32_t>(incoming_frames_.size()); | 79 return static_cast<int32_t>(incoming_frames_.size()); |
| 63 } | 80 } |
| 64 | 81 |
| 65 rtc::Optional<VideoFrame> VideoRenderFrames::FrameToRender() { | 82 rtc::Optional<VideoFrame> VideoRenderFrames::FrameToRender() { |
| 66 rtc::Optional<VideoFrame> render_frame; | 83 rtc::Optional<VideoFrame> render_frame; |
| 67 // Get the newest frame that can be released for rendering. | 84 // Get the newest frame that can be released for rendering. |
| 68 while (!incoming_frames_.empty() && TimeToNextFrameRelease() <= 0) { | 85 while (!incoming_frames_.empty() && TimeToNextFrameRelease() <= 0) { |
| 69 render_frame = rtc::Optional<VideoFrame>(incoming_frames_.front()); | 86 render_frame = |
| 87 rtc::Optional<VideoFrame>(std::move(incoming_frames_.front())); |
| 70 incoming_frames_.pop_front(); | 88 incoming_frames_.pop_front(); |
| 71 } | 89 } |
| 72 return render_frame; | 90 return render_frame; |
| 73 } | 91 } |
| 74 | 92 |
| 75 uint32_t VideoRenderFrames::TimeToNextFrameRelease() { | 93 uint32_t VideoRenderFrames::TimeToNextFrameRelease() { |
| 76 if (incoming_frames_.empty()) { | 94 if (incoming_frames_.empty()) { |
| 77 return kEventMaxWaitTimeMs; | 95 return kEventMaxWaitTimeMs; |
| 78 } | 96 } |
| 79 const int64_t time_to_release = incoming_frames_.front().render_time_ms() - | 97 const int64_t time_to_release = incoming_frames_.front().render_time_ms() - |
| 80 render_delay_ms_ - | 98 render_delay_ms_ - |
| 81 rtc::TimeMillis(); | 99 rtc::TimeMillis(); |
| 82 return time_to_release < 0 ? 0u : static_cast<uint32_t>(time_to_release); | 100 return time_to_release < 0 ? 0u : static_cast<uint32_t>(time_to_release); |
| 83 } | 101 } |
| 84 | 102 |
| 103 bool VideoRenderFrames::HasPendingFrames() const { |
| 104 return !incoming_frames_.empty(); |
| 105 } |
| 106 |
| 85 } // namespace webrtc | 107 } // namespace webrtc |
| OLD | NEW |