Line data Source code
1 : /*
2 : * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 : *
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
6 : * tree. An additional intellectual property rights grant can be found
7 : * in the file PATENTS. All contributing project authors may
8 : * be found in the AUTHORS file in the root of the source tree.
9 : */
10 :
11 : #include "webrtc/common_video/video_render_frames.h"
12 :
13 : #include "webrtc/base/logging.h"
14 : #include "webrtc/base/timeutils.h"
15 : #include "webrtc/modules/include/module_common_types.h"
16 : #include "webrtc/system_wrappers/include/trace.h"
17 :
18 : namespace webrtc {
19 : namespace {
20 :
21 : const uint32_t kEventMaxWaitTimeMs = 200;
22 : const uint32_t kMinRenderDelayMs = 10;
23 : const uint32_t kMaxRenderDelayMs = 500;
24 : const size_t kMaxIncomingFramesBeforeLogged = 100;
25 :
26 0 : uint32_t EnsureValidRenderDelay(uint32_t render_delay) {
27 0 : return (render_delay < kMinRenderDelayMs || render_delay > kMaxRenderDelayMs)
28 0 : ? kMinRenderDelayMs
29 0 : : render_delay;
30 : }
31 : } // namespace
32 :
33 0 : VideoRenderFrames::VideoRenderFrames(uint32_t render_delay_ms)
34 0 : : render_delay_ms_(EnsureValidRenderDelay(render_delay_ms)) {}
35 :
36 0 : int32_t VideoRenderFrames::AddFrame(const VideoFrame& new_frame) {
37 0 : const int64_t time_now = rtc::TimeMillis();
38 :
39 : // Drop old frames only when there are other frames in the queue, otherwise, a
40 : // really slow system never renders any frames.
41 0 : if (!incoming_frames_.empty() &&
42 0 : new_frame.render_time_ms() + KOldRenderTimestampMS < time_now) {
43 : WEBRTC_TRACE(kTraceWarning,
44 : kTraceVideoRenderer,
45 : -1,
46 : "%s: too old frame, timestamp=%u.",
47 : __FUNCTION__,
48 : new_frame.timestamp());
49 0 : return -1;
50 : }
51 :
52 0 : if (new_frame.render_time_ms() > time_now + KFutureRenderTimestampMS) {
53 : WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, -1,
54 : "%s: frame too long into the future, timestamp=%u.",
55 : __FUNCTION__, new_frame.timestamp());
56 0 : return -1;
57 : }
58 :
59 0 : incoming_frames_.push_back(new_frame);
60 0 : if (incoming_frames_.size() > kMaxIncomingFramesBeforeLogged)
61 0 : LOG(LS_WARNING) << "Stored incoming frames: " << incoming_frames_.size();
62 0 : return static_cast<int32_t>(incoming_frames_.size());
63 : }
64 :
65 0 : rtc::Optional<VideoFrame> VideoRenderFrames::FrameToRender() {
66 0 : rtc::Optional<VideoFrame> render_frame;
67 : // Get the newest frame that can be released for rendering.
68 0 : while (!incoming_frames_.empty() && TimeToNextFrameRelease() <= 0) {
69 0 : render_frame = rtc::Optional<VideoFrame>(incoming_frames_.front());
70 0 : incoming_frames_.pop_front();
71 : }
72 0 : return render_frame;
73 : }
74 :
75 0 : uint32_t VideoRenderFrames::TimeToNextFrameRelease() {
76 0 : if (incoming_frames_.empty()) {
77 0 : return kEventMaxWaitTimeMs;
78 : }
79 0 : const int64_t time_to_release = incoming_frames_.front().render_time_ms() -
80 0 : render_delay_ms_ -
81 0 : rtc::TimeMillis();
82 0 : return time_to_release < 0 ? 0u : static_cast<uint32_t>(time_to_release);
83 : }
84 :
85 : } // namespace webrtc
|