blob: 6a38c768f57461163a79388cf7ccd1be36aad3d6 [file] [log] [blame]
Ajit Khare73cfaf42013-01-07 23:28:47 -08001/*
2 * Copyright (c) 2013, The Linux Foundation. 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 are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
Ajit Khare73cfaf42013-01-07 23:28:47 -080030#include <utils/Log.h>
Ajit Khare73cfaf42013-01-07 23:28:47 -080031#include "DashPlayerStats.h"
Ajit Khare73cfaf42013-01-07 23:28:47 -080032
33#define NO_MIMETYPE_AVAILABLE "N/A"
34
35namespace android {
36
37DashPlayerStats::DashPlayerStats() {
Surajit Podder852ebd52013-02-21 15:05:18 +053038 Mutex::Autolock autoLock(mStatsLock);
39 mMIME = new char[strlen(NO_MIMETYPE_AVAILABLE)+1];
40 strcpy(mMIME,NO_MIMETYPE_AVAILABLE);
41 mNumVideoFramesDecoded = 0;
42 mNumVideoFramesDropped = 0;
43 mConsecutiveFramesDropped = 0;
44 mCatchupTimeStart = 0;
45 mNumTimesSyncLoss = 0;
46 mMaxEarlyDelta = 0;
47 mMaxLateDelta = 0;
48 mMaxTimeSyncLoss = 0;
49 mTotalFrames = 0;
50 mFirstFrameLatencyStartUs = getTimeOfDayUs();
51 mLastFrame = 0;
52 mLastFrameUs = 0;
53 mStatisticsFrames = 0;
54 mFPSSumUs = 0;
55 mVeryFirstFrame = true;
56 mSeekPerformed = false;
57 mTotalTime = 0;
58 mFirstFrameTime = 0;
59 mTotalRenderingFrames = 0;
60 mBufferingEvent = false;
61 mFd = -1;
62 mFileOut = NULL;
Ajit Khare73cfaf42013-01-07 23:28:47 -080063}
64
65DashPlayerStats::~DashPlayerStats() {
Surajit Podder852ebd52013-02-21 15:05:18 +053066 Mutex::Autolock autoLock(mStatsLock);
67 if(mFileOut){
68 fclose(mFileOut);
69 mFileOut = NULL;
70 }
Ajit Khare73cfaf42013-01-07 23:28:47 -080071 if(mMIME) {
Naupada Dharmendra Patnaik84a8aa12013-02-01 14:34:07 +053072 delete[] mMIME;
Ajit Khare73cfaf42013-01-07 23:28:47 -080073 }
74}
75
Surajit Podder852ebd52013-02-21 15:05:18 +053076void DashPlayerStats::setFileDescAndOutputStream(int fd) {
77 Mutex::Autolock autoLock(mStatsLock);
78 mFd = fd;
79 if(mFileOut){
80 fclose(mFileOut);
81 mFileOut = NULL;
82 }
83 mFileOut = fdopen(dup(fd), "w");
84}
85
Ajit Khare73cfaf42013-01-07 23:28:47 -080086void DashPlayerStats::setMime(const char* mime) {
87 Mutex::Autolock autoLock(mStatsLock);
88 if(mime != NULL) {
89 int mimeLen = strlen(mime);
Naupada Dharmendra Patnaik84a8aa12013-02-01 14:34:07 +053090 if(mMIME) {
91 delete[] mMIME;
Ajit Khare73cfaf42013-01-07 23:28:47 -080092 }
93
94 mMIME = new char[mimeLen+1];
95 strcpy(mMIME,mime);
96 }
97}
98
99void DashPlayerStats::setVeryFirstFrame(bool vff) {
100 Mutex::Autolock autoLock(mStatsLock);
101 mVeryFirstFrame = true;
102}
103
104void DashPlayerStats::notifySeek() {
105 Mutex::Autolock autoLock(mStatsLock);
106 mFirstFrameLatencyStartUs = getTimeOfDayUs();
107 mSeekPerformed = true;
108}
109
Naupada Dharmendra Patnaik84a8aa12013-02-01 14:34:07 +0530110void DashPlayerStats::notifyBufferingEvent() {
111 Mutex::Autolock autoLock(mStatsLock);
112 mBufferingEvent = true;
113}
114
Ajit Khare73cfaf42013-01-07 23:28:47 -0800115void DashPlayerStats::incrementTotalFrames() {
116 Mutex::Autolock autoLock(mStatsLock);
117 mTotalFrames++;
118}
119
120void DashPlayerStats::incrementTotalRenderingFrames() {
121 Mutex::Autolock autoLock(mStatsLock);
122 mTotalRenderingFrames++;
123}
124
125void DashPlayerStats::incrementDroppedFrames() {
126 Mutex::Autolock autoLock(mStatsLock);
127 mNumVideoFramesDropped++;
128}
129
130void DashPlayerStats::logStatistics() {
Surajit Podder852ebd52013-02-21 15:05:18 +0530131 if(mFileOut) {
Ajit Khare73cfaf42013-01-07 23:28:47 -0800132 Mutex::Autolock autoLock(mStatsLock);
Surajit Podder852ebd52013-02-21 15:05:18 +0530133 fprintf(mFileOut, "=====================================================\n");
134 fprintf(mFileOut, "Mime Type: %s\n",mMIME);
135 fprintf(mFileOut, "Number of total frames: %llu\n",mTotalFrames);
136 fprintf(mFileOut, "Number of frames dropped: %lld\n",mNumVideoFramesDropped);
137 fprintf(mFileOut, "Number of frames rendered: %llu\n",mTotalRenderingFrames);
138 fprintf(mFileOut, "Percentage dropped: %.2f\n",
139 mTotalFrames == 0 ? 0.0 : (double)mNumVideoFramesDropped / mTotalFrames);
140 fprintf(mFileOut, "=====================================================\n");
Ajit Khare73cfaf42013-01-07 23:28:47 -0800141 }
142}
143
144void DashPlayerStats::logPause(int64_t positionUs) {
Surajit Podder852ebd52013-02-21 15:05:18 +0530145 if(mFileOut) {
146 fprintf(mFileOut, "=====================================================\n");
147 fprintf(mFileOut, "Pause position: %lld ms\n",positionUs/1000);
148 fprintf(mFileOut, "=====================================================\n");
Ajit Khare73cfaf42013-01-07 23:28:47 -0800149 }
150}
151
152void DashPlayerStats::logSeek(int64_t seekTimeUs) {
Surajit Podder852ebd52013-02-21 15:05:18 +0530153 if(mFileOut) {
Ajit Khare73cfaf42013-01-07 23:28:47 -0800154 Mutex::Autolock autoLock(mStatsLock);
Surajit Podder852ebd52013-02-21 15:05:18 +0530155 fprintf(mFileOut, "=====================================================\n");
156 fprintf(mFileOut, "Seek position: %lld ms\n",seekTimeUs/1000);
157 fprintf(mFileOut, "Seek latency: %lld ms\n",(getTimeOfDayUs() - mFirstFrameLatencyStartUs)/1000);
158 fprintf(mFileOut, "=====================================================\n");
Ajit Khare73cfaf42013-01-07 23:28:47 -0800159 }
160}
161
162void DashPlayerStats::recordLate(int64_t ts, int64_t clock, int64_t delta, int64_t anchorTime) {
Surajit Podder852ebd52013-02-21 15:05:18 +0530163 Mutex::Autolock autoLock(mStatsLock);
164 mNumVideoFramesDropped++;
165 mConsecutiveFramesDropped++;
166 if (mConsecutiveFramesDropped == 1){
Ajit Khare73cfaf42013-01-07 23:28:47 -0800167 mCatchupTimeStart = anchorTime;
Ajit Khare73cfaf42013-01-07 23:28:47 -0800168 }
Surajit Podder852ebd52013-02-21 15:05:18 +0530169
170 logLate(ts,clock,delta);
Ajit Khare73cfaf42013-01-07 23:28:47 -0800171}
172
173void DashPlayerStats::recordOnTime(int64_t ts, int64_t clock, int64_t delta) {
Surajit Podder852ebd52013-02-21 15:05:18 +0530174 Mutex::Autolock autoLock(mStatsLock);
175 mNumVideoFramesDecoded++;
176 mConsecutiveFramesDropped = 0;
177 logOnTime(ts,clock,delta);
Ajit Khare73cfaf42013-01-07 23:28:47 -0800178}
179
180void DashPlayerStats::logSyncLoss() {
Surajit Podder852ebd52013-02-21 15:05:18 +0530181 if(mFileOut) {
Ajit Khare73cfaf42013-01-07 23:28:47 -0800182 Mutex::Autolock autoLock(mStatsLock);
Surajit Podder852ebd52013-02-21 15:05:18 +0530183 fprintf(mFileOut, "=====================================================\n");
184 fprintf(mFileOut, "Number of times AV Sync Losses = %u\n", mNumTimesSyncLoss);
185 fprintf(mFileOut, "Max Video Ahead time delta = %u\n", -mMaxEarlyDelta/1000);
186 fprintf(mFileOut, "Max Video Behind time delta = %u\n", mMaxLateDelta/1000);
187 fprintf(mFileOut, "Max Time sync loss = %u\n",mMaxTimeSyncLoss/1000);
188 fprintf(mFileOut, "=====================================================\n");
Ajit Khare73cfaf42013-01-07 23:28:47 -0800189 }
190}
191
192void DashPlayerStats::logFps() {
Surajit Podder852ebd52013-02-21 15:05:18 +0530193 if (mFileOut) {
Ajit Khare73cfaf42013-01-07 23:28:47 -0800194 Mutex::Autolock autoLock(mStatsLock);
Naupada Dharmendra Patnaik84a8aa12013-02-01 14:34:07 +0530195 int64_t now = getTimeOfDayUs();
196
Ajit Khare73cfaf42013-01-07 23:28:47 -0800197 if(mTotalRenderingFrames < 2){
Naupada Dharmendra Patnaik84a8aa12013-02-01 14:34:07 +0530198 mLastFrameUs = now;
199 mFirstFrameTime = now;
Ajit Khare73cfaf42013-01-07 23:28:47 -0800200 }
201
Naupada Dharmendra Patnaik84a8aa12013-02-01 14:34:07 +0530202 mTotalTime = now - mFirstFrameTime;
Ajit Khare73cfaf42013-01-07 23:28:47 -0800203 int64_t diff = now - mLastFrameUs;
Naupada Dharmendra Patnaik84a8aa12013-02-01 14:34:07 +0530204 if (diff > 250000 && !mVeryFirstFrame && !mBufferingEvent) {
Ajit Khare73cfaf42013-01-07 23:28:47 -0800205 double fps =((mTotalRenderingFrames - mLastFrame) * 1E6)/diff;
206 if (mStatisticsFrames == 0) {
207 fps =((mTotalRenderingFrames - mLastFrame - 1) * 1E6)/diff;
208 }
Surajit Podder852ebd52013-02-21 15:05:18 +0530209 fprintf(mFileOut, "Frames per second: %.4f, Duration of measurement: %lld\n", fps,diff);
Ajit Khare73cfaf42013-01-07 23:28:47 -0800210 mFPSSumUs += fps;
211 ++mStatisticsFrames;
212 mLastFrameUs = now;
213 mLastFrame = mTotalRenderingFrames;
214 }
215
216 if(mSeekPerformed) {
217 mVeryFirstFrame = false;
218 mSeekPerformed = false;
219 } else if(mVeryFirstFrame) {
220 logFirstFrame();
Surajit Podder852ebd52013-02-21 15:05:18 +0530221 fprintf(mFileOut, "setting first frame time\n");
Naupada Dharmendra Patnaik84a8aa12013-02-01 14:34:07 +0530222 mLastFrameUs = now;
223 } else if(mBufferingEvent) {
224 mLastFrameUs = now;
225 mLastFrame = mTotalRenderingFrames;
Ajit Khare73cfaf42013-01-07 23:28:47 -0800226 }
Naupada Dharmendra Patnaik84a8aa12013-02-01 14:34:07 +0530227 mBufferingEvent = false;
Ajit Khare73cfaf42013-01-07 23:28:47 -0800228 }
229}
230
231void DashPlayerStats::logFpsSummary() {
Surajit Podder852ebd52013-02-21 15:05:18 +0530232 if (mFileOut) {
Ajit Khare73cfaf42013-01-07 23:28:47 -0800233 logStatistics();
234 logSyncLoss();
235 {
236 Mutex::Autolock autoLock(mStatsLock);
Surajit Podder852ebd52013-02-21 15:05:18 +0530237 fprintf(mFileOut, "=========================================================\n");
238 fprintf(mFileOut, "Average Frames Per Second: %.4f\n", mFPSSumUs/((double)mStatisticsFrames));
239 fprintf(mFileOut, "Total Frames (rendered) / Total Time: %.4f\n", ((double)(mTotalRenderingFrames-1)*1E6)/((double)mTotalTime));
240 fprintf(mFileOut, "========================================================\n");
Ajit Khare73cfaf42013-01-07 23:28:47 -0800241 }
242 }
243}
244
245int64_t DashPlayerStats::getTimeOfDayUs() {
246 struct timeval tv;
247 gettimeofday(&tv, NULL);
248 return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
249}
250
251// WARNING: Most private functions are only thread-safe within mStatsLock
252inline void DashPlayerStats::logFirstFrame() {
Surajit Podder852ebd52013-02-21 15:05:18 +0530253 fprintf(mFileOut, "=====================================================\n");
254 fprintf(mFileOut, "First frame latency: %lld ms\n",(getTimeOfDayUs()-mFirstFrameLatencyStartUs)/1000);
255 fprintf(mFileOut, "=====================================================\n");
Ajit Khare73cfaf42013-01-07 23:28:47 -0800256 mVeryFirstFrame = false;
257}
258
259inline void DashPlayerStats::logCatchUp(int64_t ts, int64_t clock, int64_t delta) {
Surajit Podder852ebd52013-02-21 15:05:18 +0530260 if (mConsecutiveFramesDropped > 0) {
261 mNumTimesSyncLoss++;
262 if (mMaxTimeSyncLoss < (clock - mCatchupTimeStart) && clock > 0 && ts > 0) {
263 mMaxTimeSyncLoss = clock - mCatchupTimeStart;
Ajit Khare73cfaf42013-01-07 23:28:47 -0800264 }
265 }
266}
267
268inline void DashPlayerStats::logLate(int64_t ts, int64_t clock, int64_t delta) {
Surajit Podder852ebd52013-02-21 15:05:18 +0530269 if (mMaxLateDelta < delta && clock > 0 && ts > 0) {
270 mMaxLateDelta = delta;
Ajit Khare73cfaf42013-01-07 23:28:47 -0800271 }
272}
273
274inline void DashPlayerStats::logOnTime(int64_t ts, int64_t clock, int64_t delta) {
Surajit Podder852ebd52013-02-21 15:05:18 +0530275 bool needLogLate = false;
276 logCatchUp(ts, clock, delta);
277 if (delta <= 0) {
278 if ((-delta) > (-mMaxEarlyDelta) && clock > 0 && ts > 0) {
279 mMaxEarlyDelta = delta;
Ajit Khare73cfaf42013-01-07 23:28:47 -0800280 }
Ajit Khare73cfaf42013-01-07 23:28:47 -0800281 }
Surajit Podder852ebd52013-02-21 15:05:18 +0530282 else {
283 needLogLate = true;
284 }
285
286 if(needLogLate) logLate(ts, clock, delta);
Ajit Khare73cfaf42013-01-07 23:28:47 -0800287}
288
289} // namespace android