blob: dd38d5d0bdfb7f89857361fb15f397bcb0529464 [file] [log] [blame]
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "VideoFrameScheduler"
19#include <utils/Log.h>
20#define ATRACE_TAG ATRACE_TAG_VIDEO
21#include <utils/Trace.h>
22
23#include <sys/time.h>
24
25#include <binder/IServiceManager.h>
26#include <gui/ISurfaceComposer.h>
27#include <ui/DisplayStatInfo.h>
28
29#include <media/stagefright/foundation/ADebug.h>
30
31#include "VideoFrameScheduler.h"
32
33namespace android {
34
35static const nsecs_t kNanosIn1s = 1000000000;
36
37/* ======================================================================= */
38/* Frame Scheduler */
39/* ======================================================================= */
40
41static const nsecs_t kDefaultVsyncPeriod = kNanosIn1s / 60; // 60Hz
42static const nsecs_t kVsyncRefreshPeriod = kNanosIn1s; // 1 sec
43
44VideoFrameScheduler::VideoFrameScheduler()
45 : mVsyncTime(0),
46 mVsyncPeriod(0),
47 mVsyncRefreshAt(0) {
48}
49
50void VideoFrameScheduler::updateVsync() {
51 mVsyncRefreshAt = systemTime(SYSTEM_TIME_MONOTONIC) + kVsyncRefreshPeriod;
52 mVsyncPeriod = 0;
53 mVsyncTime = 0;
54
55 // TODO: schedule frames for the destination surface
56 // For now, surface flinger only schedules frames on the primary display
57 if (mComposer == NULL) {
58 String16 name("SurfaceFlinger");
59 sp<IServiceManager> sm = defaultServiceManager();
60 mComposer = interface_cast<ISurfaceComposer>(sm->checkService(name));
61 }
62 if (mComposer != NULL) {
63 DisplayStatInfo stats;
64 status_t res = mComposer->getDisplayStats(NULL /* display */, &stats);
65 if (res == OK) {
66 ALOGV("vsync time:%lld period:%lld",
67 (long long)stats.vsyncTime, (long long)stats.vsyncPeriod);
68 mVsyncTime = stats.vsyncTime;
69 mVsyncPeriod = stats.vsyncPeriod;
70 } else {
71 ALOGW("getDisplayStats returned %d", res);
72 }
73 } else {
74 ALOGW("could not get surface mComposer service");
75 }
76}
77
78void VideoFrameScheduler::init() {
79 updateVsync();
80}
81
82nsecs_t VideoFrameScheduler::getVsyncPeriod() {
83 if (mVsyncPeriod > 0) {
84 return mVsyncPeriod;
85 }
86 return kDefaultVsyncPeriod;
87}
88
89nsecs_t VideoFrameScheduler::schedule(nsecs_t renderTime) {
90 nsecs_t origRenderTime = renderTime;
91
92 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
93 if (now >= mVsyncRefreshAt) {
94 updateVsync();
95 }
96
97 // without VSYNC info, there is nothing to do
98 if (mVsyncPeriod == 0) {
99 ALOGV("no vsync: render=%lld", (long long)renderTime);
100 return renderTime;
101 }
102
103 // ensure vsync time is well before (corrected) render time
104 if (mVsyncTime > renderTime - 4 * mVsyncPeriod) {
105 mVsyncTime -=
106 ((mVsyncTime - renderTime) / mVsyncPeriod + 5) * mVsyncPeriod;
107 }
108
109 // Video presentation takes place at the VSYNC _after_ renderTime. Adjust renderTime
110 // so this effectively becomes a rounding operation (to the _closest_ VSYNC.)
111 renderTime -= mVsyncPeriod / 2;
112
113 // align rendertime to the center between VSYNC edges
114 renderTime -= (renderTime - mVsyncTime) % mVsyncPeriod;
115 renderTime += mVsyncPeriod / 2;
116 ALOGV("adjusting render: %lld => %lld", (long long)origRenderTime, (long long)renderTime);
117 ATRACE_INT("FRAME_FLIP_IN(ms)", (renderTime - now) / 1000000);
118 return renderTime;
119}
120
121void VideoFrameScheduler::release() {
122 mComposer.clear();
123}
124
125VideoFrameScheduler::~VideoFrameScheduler() {
126 release();
127}
128
129} // namespace android
130