1/*
2 * Copyright (C) 2015 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#ifndef MEDIA_CLOCK_H_
18
19#define MEDIA_CLOCK_H_
20
21#include <list>
22#include <media/stagefright/foundation/AHandler.h>
23#include <utils/Mutex.h>
24#include <utils/RefBase.h>
25
26namespace android {
27
28struct AMessage;
29
30struct MediaClock : public AHandler {
31    enum {
32        TIMER_REASON_REACHED = 0,
33        TIMER_REASON_RESET = 1,
34    };
35
36    MediaClock();
37    void init();
38
39    void setStartingTimeMedia(int64_t startingTimeMediaUs);
40
41    void clearAnchor();
42    // It's required to use timestamp of just rendered frame as
43    // anchor time in paused state.
44    void updateAnchor(
45            int64_t anchorTimeMediaUs,
46            int64_t anchorTimeRealUs,
47            int64_t maxTimeMediaUs = INT64_MAX);
48
49    void updateMaxTimeMedia(int64_t maxTimeMediaUs);
50
51    void setPlaybackRate(float rate);
52    float getPlaybackRate() const;
53
54    // query media time corresponding to real time |realUs|, and save the
55    // result in |outMediaUs|.
56    status_t getMediaTime(
57            int64_t realUs,
58            int64_t *outMediaUs,
59            bool allowPastMaxTime = false) const;
60    // query real time corresponding to media time |targetMediaUs|.
61    // The result is saved in |outRealUs|.
62    status_t getRealTimeFor(int64_t targetMediaUs, int64_t *outRealUs) const;
63
64    // request to set up a timer. The target time is |mediaTimeUs|, adjusted by
65    // system time of |adjustRealUs|. In other words, the wake up time is
66    // mediaTimeUs + (adjustRealUs / playbackRate)
67    void addTimer(const sp<AMessage> &notify, int64_t mediaTimeUs, int64_t adjustRealUs = 0);
68
69    void setNotificationMessage(const sp<AMessage> &msg);
70
71    void reset();
72
73protected:
74    virtual ~MediaClock();
75
76    virtual void onMessageReceived(const sp<AMessage> &msg);
77
78private:
79    enum {
80        kWhatTimeIsUp = 'tIsU',
81    };
82
83    struct Timer {
84        Timer(const sp<AMessage> &notify, int64_t mediaTimeUs, int64_t adjustRealUs);
85        const sp<AMessage> mNotify;
86        int64_t mMediaTimeUs;
87        int64_t mAdjustRealUs;
88    };
89
90    status_t getMediaTime_l(
91            int64_t realUs,
92            int64_t *outMediaUs,
93            bool allowPastMaxTime) const;
94
95    void processTimers_l();
96
97    void updateAnchorTimesAndPlaybackRate_l(
98            int64_t anchorTimeMediaUs, int64_t anchorTimeRealUs , float playbackRate);
99
100    void notifyDiscontinuity_l();
101
102    sp<ALooper> mLooper;
103    mutable Mutex mLock;
104
105    int64_t mAnchorTimeMediaUs;
106    int64_t mAnchorTimeRealUs;
107    int64_t mMaxTimeMediaUs;
108    int64_t mStartingTimeMediaUs;
109
110    float mPlaybackRate;
111
112    int32_t mGeneration;
113    std::list<Timer> mTimers;
114    sp<AMessage> mNotify;
115
116    DISALLOW_EVIL_CONSTRUCTORS(MediaClock);
117};
118
119}  // namespace android
120
121#endif  // MEDIA_CLOCK_H_
122