[Mac] Add helper methods to convert CMTime <--> MediaTime
[WebKit-https.git] / Source / WebCore / platform / mac / PlatformClockCM.mm
1 /*
2  * Copyright (C) 2012 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27
28 #if USE(COREMEDIA)
29
30 #import "PlatformClockCM.h"
31
32 #import "MediaTimeMac.h"
33 #import "SoftLinking.h"
34 #import <CoreMedia/CMAudioDeviceClock.h>
35
36 SOFT_LINK_FRAMEWORK_OPTIONAL(CoreMedia)
37
38 SOFT_LINK(CoreMedia, CMAudioDeviceClockCreate, OSStatus, (CFAllocatorRef allocator, CFStringRef deviceUID, CMClockRef *clockOut), (allocator, deviceUID, clockOut))
39 SOFT_LINK(CoreMedia, CMTimebaseCreateWithMasterClock, OSStatus, (CFAllocatorRef allocator, CMClockRef masterClock, CMTimebaseRef *timebaseOut), (allocator, masterClock, timebaseOut))
40 SOFT_LINK(CoreMedia, CMTimebaseSetTime, OSStatus, (CMTimebaseRef timebase, CMTime time), (timebase, time))
41 SOFT_LINK(CoreMedia, CMTimebaseGetTime, CMTime, (CMTimebaseRef timebase), (timebase))
42 SOFT_LINK(CoreMedia, CMTimebaseSetRate, OSStatus, (CMTimebaseRef timebase, Float64 rate), (timebase, rate))
43 SOFT_LINK(CoreMedia, CMTimeMakeWithSeconds, CMTime, (Float64 seconds, int32_t preferredTimeScale), (seconds, preferredTimeScale))
44 SOFT_LINK(CoreMedia, CMTimeGetSeconds, Float64, (CMTime time), (time))
45
46 using namespace WebCore;
47
48 // A default time scale of 1000 allows milli-second CMTime precision without scaling the timebase.
49 static const int32_t DefaultTimeScale = 1000;
50
51 PlatformClockCM::PlatformClockCM()
52     : m_timebase(0)
53     , m_rate(1)
54     , m_running(false)
55 {
56     CMClockRef rawClockPtr = 0;
57     CMAudioDeviceClockCreate(kCFAllocatorDefault, NULL, &rawClockPtr);
58     RetainPtr<CMClockRef> clock = adoptCF(rawClockPtr);
59     initializeWithTimingSource(clock.get());
60 }
61
62 PlatformClockCM::PlatformClockCM(CMClockRef clock)
63     : m_timebase(0)
64     , m_running(false)
65 {
66     initializeWithTimingSource(clock);
67 }
68
69 void PlatformClockCM::initializeWithTimingSource(CMClockRef clock)
70 {
71     CMTimebaseRef rawTimebasePtr = 0;
72     CMTimebaseCreateWithMasterClock(kCFAllocatorDefault, clock, &rawTimebasePtr);
73     m_timebase = adoptCF(rawTimebasePtr);
74 }
75
76 void PlatformClockCM::setCurrentTime(double time)
77 {
78     CMTime cmTime = CMTimeMakeWithSeconds(time, DefaultTimeScale);
79     CMTimebaseSetTime(m_timebase.get(), cmTime);
80 }
81
82 double PlatformClockCM::currentTime() const
83 {
84     CMTime cmTime = CMTimebaseGetTime(m_timebase.get());
85     return CMTimeGetSeconds(cmTime);
86 }
87
88 void PlatformClockCM::setCurrentMediaTime(const MediaTime& time)
89 {
90     CMTimebaseSetTime(m_timebase.get(), toCMTime(time));
91 }
92
93 MediaTime PlatformClockCM::currentMediaTime() const
94 {
95     return toMediaTime(CMTimebaseGetTime(m_timebase.get()));
96 }
97
98 void PlatformClockCM::setPlayRate(double rate)
99 {
100     if (m_rate == rate)
101         return;
102
103     m_rate = rate;
104     if (m_running)
105         CMTimebaseSetRate(m_timebase.get(), rate);
106 }
107
108 void PlatformClockCM::start()
109 {
110     if (m_running)
111         return;
112     m_running = true;
113     CMTimebaseSetRate(m_timebase.get(), m_rate);
114 }
115
116 void PlatformClockCM::stop()
117 {
118     if (!m_running)
119         return;
120     m_running = false;
121     CMTimebaseSetRate(m_timebase.get(), 0);
122 }
123
124 #endif