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 |