blob: f520ff7a04a14b26679c7f605c4d6d1f6721b217 [file] [log] [blame]
Andreas Huberf9334412010-12-15 15:17:42 -08001/*
2 * Copyright (C) 2010 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 "NuPlayerRenderer"
19#include <utils/Log.h>
20
21#include "NuPlayerRenderer.h"
22
23#include <media/stagefright/foundation/ABuffer.h>
24#include <media/stagefright/foundation/ADebug.h>
Andreas Huber5bc087c2010-12-23 10:27:40 -080025#include <media/stagefright/foundation/AMessage.h>
Wei Jiabc2fb722014-07-08 16:37:57 -070026#include <media/stagefright/MediaErrors.h>
27#include <media/stagefright/MetaData.h>
Andreas Huberf9334412010-12-15 15:17:42 -080028
29namespace android {
30
Andreas Huber714aa7b2011-09-13 08:28:38 -070031// static
32const int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll;
33
Andreas Huberf9334412010-12-15 15:17:42 -080034NuPlayer::Renderer::Renderer(
35 const sp<MediaPlayerBase::AudioSink> &sink,
Andreas Huberd5e56232013-03-12 11:01:43 -070036 const sp<AMessage> &notify,
37 uint32_t flags)
Andreas Huberf9334412010-12-15 15:17:42 -080038 : mAudioSink(sink),
39 mNotify(notify),
Andreas Huberd5e56232013-03-12 11:01:43 -070040 mFlags(flags),
Andreas Huberf9334412010-12-15 15:17:42 -080041 mNumFramesWritten(0),
42 mDrainAudioQueuePending(false),
43 mDrainVideoQueuePending(false),
44 mAudioQueueGeneration(0),
45 mVideoQueueGeneration(0),
Wei Jiabc2fb722014-07-08 16:37:57 -070046 mFirstAudioTimeUs(-1),
Andreas Huberf9334412010-12-15 15:17:42 -080047 mAnchorTimeMediaUs(-1),
48 mAnchorTimeRealUs(-1),
49 mFlushingAudio(false),
50 mFlushingVideo(false),
Andreas Huberbc7f5b22011-01-21 10:15:23 -080051 mHasAudio(false),
52 mHasVideo(false),
53 mSyncQueues(false),
Andreas Huber714aa7b2011-09-13 08:28:38 -070054 mPaused(false),
James Dongf57b4ea2012-07-20 13:38:36 -070055 mVideoRenderingStarted(false),
Lajos Molnarcbaffcf2013-08-14 18:30:38 -070056 mVideoRenderingStartGeneration(0),
57 mAudioRenderingStartGeneration(0),
Andreas Huber3fe62152011-09-16 15:09:22 -070058 mLastPositionUpdateUs(-1ll),
59 mVideoLateByUs(0ll) {
Andreas Huberf9334412010-12-15 15:17:42 -080060}
61
62NuPlayer::Renderer::~Renderer() {
Wei Jiabc2fb722014-07-08 16:37:57 -070063 if (offloadingAudio()) {
64 mAudioSink->stop();
65 mAudioSink->flush();
66 mAudioSink->close();
67 }
Andreas Huberf9334412010-12-15 15:17:42 -080068}
69
70void NuPlayer::Renderer::queueBuffer(
71 bool audio,
72 const sp<ABuffer> &buffer,
73 const sp<AMessage> &notifyConsumed) {
74 sp<AMessage> msg = new AMessage(kWhatQueueBuffer, id());
75 msg->setInt32("audio", static_cast<int32_t>(audio));
Andreas Huber2d8bedd2012-02-21 14:38:23 -080076 msg->setBuffer("buffer", buffer);
Andreas Huberf9334412010-12-15 15:17:42 -080077 msg->setMessage("notifyConsumed", notifyConsumed);
78 msg->post();
79}
80
81void NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
82 CHECK_NE(finalResult, (status_t)OK);
83
84 sp<AMessage> msg = new AMessage(kWhatQueueEOS, id());
85 msg->setInt32("audio", static_cast<int32_t>(audio));
86 msg->setInt32("finalResult", finalResult);
87 msg->post();
88}
89
90void NuPlayer::Renderer::flush(bool audio) {
91 {
92 Mutex::Autolock autoLock(mFlushLock);
93 if (audio) {
94 CHECK(!mFlushingAudio);
95 mFlushingAudio = true;
96 } else {
97 CHECK(!mFlushingVideo);
98 mFlushingVideo = true;
99 }
100 }
101
102 sp<AMessage> msg = new AMessage(kWhatFlush, id());
103 msg->setInt32("audio", static_cast<int32_t>(audio));
104 msg->post();
105}
106
107void NuPlayer::Renderer::signalTimeDiscontinuity() {
Wei Jiabc2fb722014-07-08 16:37:57 -0700108 Mutex::Autolock autoLock(mLock);
Andreas Huber14f76722013-01-15 09:04:18 -0800109 // CHECK(mAudioQueue.empty());
110 // CHECK(mVideoQueue.empty());
Andreas Huberf9334412010-12-15 15:17:42 -0800111 mAnchorTimeMediaUs = -1;
112 mAnchorTimeRealUs = -1;
Andreas Huber14f76722013-01-15 09:04:18 -0800113 mSyncQueues = false;
Andreas Huberf9334412010-12-15 15:17:42 -0800114}
115
Andreas Huberb4082222011-01-20 15:23:04 -0800116void NuPlayer::Renderer::pause() {
117 (new AMessage(kWhatPause, id()))->post();
118}
119
120void NuPlayer::Renderer::resume() {
121 (new AMessage(kWhatResume, id()))->post();
122}
123
Andreas Huberf9334412010-12-15 15:17:42 -0800124void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
125 switch (msg->what()) {
Wei Jiabc2fb722014-07-08 16:37:57 -0700126 case kWhatStopAudioSink:
127 {
128 mAudioSink->stop();
129 break;
130 }
131
Andreas Huberf9334412010-12-15 15:17:42 -0800132 case kWhatDrainAudioQueue:
133 {
134 int32_t generation;
135 CHECK(msg->findInt32("generation", &generation));
136 if (generation != mAudioQueueGeneration) {
137 break;
138 }
139
140 mDrainAudioQueuePending = false;
141
Andreas Huber078cfcf2011-09-15 12:25:04 -0700142 if (onDrainAudioQueue()) {
143 uint32_t numFramesPlayed;
144 CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
145 (status_t)OK);
Andreas Huberf9334412010-12-15 15:17:42 -0800146
Andreas Huber078cfcf2011-09-15 12:25:04 -0700147 uint32_t numFramesPendingPlayout =
148 mNumFramesWritten - numFramesPlayed;
149
150 // This is how long the audio sink will have data to
151 // play back.
152 int64_t delayUs =
153 mAudioSink->msecsPerFrame()
154 * numFramesPendingPlayout * 1000ll;
155
156 // Let's give it more data after about half that time
157 // has elapsed.
Wei Jiabc2fb722014-07-08 16:37:57 -0700158 // kWhatDrainAudioQueue is used for non-offloading mode,
159 // and mLock is used only for offloading mode. Therefore,
160 // no need to acquire mLock here.
161 postDrainAudioQueue_l(delayUs / 2);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700162 }
Andreas Huberf9334412010-12-15 15:17:42 -0800163 break;
164 }
165
166 case kWhatDrainVideoQueue:
167 {
168 int32_t generation;
169 CHECK(msg->findInt32("generation", &generation));
170 if (generation != mVideoQueueGeneration) {
171 break;
172 }
173
174 mDrainVideoQueuePending = false;
175
176 onDrainVideoQueue();
177
178 postDrainVideoQueue();
179 break;
180 }
181
182 case kWhatQueueBuffer:
183 {
184 onQueueBuffer(msg);
185 break;
186 }
187
188 case kWhatQueueEOS:
189 {
190 onQueueEOS(msg);
191 break;
192 }
193
194 case kWhatFlush:
195 {
196 onFlush(msg);
197 break;
198 }
199
Andreas Huber3831a062010-12-21 10:22:33 -0800200 case kWhatAudioSinkChanged:
201 {
202 onAudioSinkChanged();
203 break;
204 }
205
Wei Jiabc2fb722014-07-08 16:37:57 -0700206 case kWhatDisableOffloadAudio:
207 {
208 onDisableOffloadAudio();
209 break;
210 }
211
Andreas Huberb4082222011-01-20 15:23:04 -0800212 case kWhatPause:
213 {
214 onPause();
215 break;
216 }
217
218 case kWhatResume:
219 {
220 onResume();
221 break;
222 }
223
Andreas Huberf9334412010-12-15 15:17:42 -0800224 default:
225 TRESPASS();
226 break;
227 }
228}
229
Wei Jiabc2fb722014-07-08 16:37:57 -0700230void NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) {
231 if (mDrainAudioQueuePending || mSyncQueues || mPaused
232 || offloadingAudio()) {
Andreas Huberf9334412010-12-15 15:17:42 -0800233 return;
234 }
235
236 if (mAudioQueue.empty()) {
237 return;
238 }
239
240 mDrainAudioQueuePending = true;
241 sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, id());
242 msg->setInt32("generation", mAudioQueueGeneration);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700243 msg->post(delayUs);
Andreas Huberf9334412010-12-15 15:17:42 -0800244}
245
Andreas Huber3831a062010-12-21 10:22:33 -0800246void NuPlayer::Renderer::signalAudioSinkChanged() {
247 (new AMessage(kWhatAudioSinkChanged, id()))->post();
248}
249
Wei Jiabc2fb722014-07-08 16:37:57 -0700250void NuPlayer::Renderer::signalDisableOffloadAudio() {
251 (new AMessage(kWhatDisableOffloadAudio, id()))->post();
252}
253
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700254void NuPlayer::Renderer::prepareForMediaRenderingStart() {
255 mAudioRenderingStartGeneration = mAudioQueueGeneration;
256 mVideoRenderingStartGeneration = mVideoQueueGeneration;
257}
258
259void NuPlayer::Renderer::notifyIfMediaRenderingStarted() {
260 if (mVideoRenderingStartGeneration == mVideoQueueGeneration &&
261 mAudioRenderingStartGeneration == mAudioQueueGeneration) {
262 mVideoRenderingStartGeneration = -1;
263 mAudioRenderingStartGeneration = -1;
264
265 sp<AMessage> notify = mNotify->dup();
266 notify->setInt32("what", kWhatMediaRenderingStart);
267 notify->post();
268 }
269}
270
Wei Jiabc2fb722014-07-08 16:37:57 -0700271// static
272size_t NuPlayer::Renderer::AudioSinkCallback(
273 MediaPlayerBase::AudioSink * /* audioSink */,
274 void *buffer,
275 size_t size,
276 void *cookie,
277 MediaPlayerBase::AudioSink::cb_event_t event) {
278 NuPlayer::Renderer *me = (NuPlayer::Renderer *)cookie;
279
280 switch (event) {
281 case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
282 {
283 return me->fillAudioBuffer(buffer, size);
284 break;
285 }
286
287 case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
288 {
289 me->notifyEOS(true /* audio */, ERROR_END_OF_STREAM);
290 break;
291 }
292
293 case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
294 {
295 // TODO: send this to player.
296 break;
297 }
298 }
299
300 return 0;
301}
302
303size_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
304 Mutex::Autolock autoLock(mLock);
305
306 if (!offloadingAudio()) {
307 return 0;
308 }
309
310 bool hasEOS = false;
311
312 size_t sizeCopied = 0;
313 while (sizeCopied < size && !mAudioQueue.empty()) {
314 QueueEntry *entry = &*mAudioQueue.begin();
315
316 if (entry->mBuffer == NULL) { // EOS
317 hasEOS = true;
318 mAudioQueue.erase(mAudioQueue.begin());
319 entry = NULL;
320 break;
321 }
322
323 if (entry->mOffset == 0) {
324 int64_t mediaTimeUs;
325 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
326 ALOGV("rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
327 if (mFirstAudioTimeUs == -1) {
328 mFirstAudioTimeUs = mediaTimeUs;
329 }
330 mAnchorTimeMediaUs = mediaTimeUs;
331
332 uint32_t numFramesPlayed;
333 CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK);
334
335 // TODO: figure out how to calculate initial latency.
336 // Otherwise, the initial time is not correct till the first sample
337 // is played.
338 mAnchorTimeMediaUs = mFirstAudioTimeUs
339 + (numFramesPlayed * mAudioSink->msecsPerFrame()) * 1000ll;
340 mAnchorTimeRealUs = ALooper::GetNowUs();
341 }
342
343 size_t copy = entry->mBuffer->size() - entry->mOffset;
344 size_t sizeRemaining = size - sizeCopied;
345 if (copy > sizeRemaining) {
346 copy = sizeRemaining;
347 }
348
349 memcpy((char *)buffer + sizeCopied,
350 entry->mBuffer->data() + entry->mOffset,
351 copy);
352
353 entry->mOffset += copy;
354 if (entry->mOffset == entry->mBuffer->size()) {
355 entry->mNotifyConsumed->post();
356 mAudioQueue.erase(mAudioQueue.begin());
357 entry = NULL;
358 }
359 sizeCopied += copy;
360 notifyIfMediaRenderingStarted();
361 }
362
363 if (sizeCopied != 0) {
364 notifyPosition();
365 }
366
367 if (hasEOS) {
368 (new AMessage(kWhatStopAudioSink, id()))->post();
369 }
370
371 return sizeCopied;
372}
373
Andreas Huber078cfcf2011-09-15 12:25:04 -0700374bool NuPlayer::Renderer::onDrainAudioQueue() {
375 uint32_t numFramesPlayed;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700376 if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
377 return false;
378 }
Andreas Huberc92fd242011-08-16 13:48:44 -0700379
Andreas Huber078cfcf2011-09-15 12:25:04 -0700380 ssize_t numFramesAvailableToWrite =
381 mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
382
383#if 0
384 if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
Steve Blockdf64d152012-01-04 20:05:49 +0000385 ALOGI("audio sink underrun");
Andreas Huber078cfcf2011-09-15 12:25:04 -0700386 } else {
Steve Block3856b092011-10-20 11:56:00 +0100387 ALOGV("audio queue has %d frames left to play",
Andreas Huber078cfcf2011-09-15 12:25:04 -0700388 mAudioSink->frameCount() - numFramesAvailableToWrite);
389 }
390#endif
391
392 size_t numBytesAvailableToWrite =
393 numFramesAvailableToWrite * mAudioSink->frameSize();
394
395 while (numBytesAvailableToWrite > 0 && !mAudioQueue.empty()) {
Andreas Huberc92fd242011-08-16 13:48:44 -0700396 QueueEntry *entry = &*mAudioQueue.begin();
397
398 if (entry->mBuffer == NULL) {
399 // EOS
400
401 notifyEOS(true /* audio */, entry->mFinalResult);
402
403 mAudioQueue.erase(mAudioQueue.begin());
404 entry = NULL;
Andreas Huber078cfcf2011-09-15 12:25:04 -0700405 return false;
Eric Laurent9b7d9502011-03-21 11:49:00 -0700406 }
407
Andreas Huberf9334412010-12-15 15:17:42 -0800408 if (entry->mOffset == 0) {
409 int64_t mediaTimeUs;
410 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
411
Steve Block3856b092011-10-20 11:56:00 +0100412 ALOGV("rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
Andreas Huberf9334412010-12-15 15:17:42 -0800413
414 mAnchorTimeMediaUs = mediaTimeUs;
415
416 uint32_t numFramesPlayed;
417 CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK);
418
419 uint32_t numFramesPendingPlayout =
420 mNumFramesWritten - numFramesPlayed;
421
422 int64_t realTimeOffsetUs =
423 (mAudioSink->latency() / 2 /* XXX */
424 + numFramesPendingPlayout
425 * mAudioSink->msecsPerFrame()) * 1000ll;
426
Steve Blockdf64d152012-01-04 20:05:49 +0000427 // ALOGI("realTimeOffsetUs = %lld us", realTimeOffsetUs);
Andreas Huberf9334412010-12-15 15:17:42 -0800428
429 mAnchorTimeRealUs =
430 ALooper::GetNowUs() + realTimeOffsetUs;
431 }
432
433 size_t copy = entry->mBuffer->size() - entry->mOffset;
434 if (copy > numBytesAvailableToWrite) {
435 copy = numBytesAvailableToWrite;
436 }
437
438 CHECK_EQ(mAudioSink->write(
439 entry->mBuffer->data() + entry->mOffset, copy),
440 (ssize_t)copy);
441
442 entry->mOffset += copy;
443 if (entry->mOffset == entry->mBuffer->size()) {
444 entry->mNotifyConsumed->post();
445 mAudioQueue.erase(mAudioQueue.begin());
Eric Laurent9b7d9502011-03-21 11:49:00 -0700446
Andreas Huberf9334412010-12-15 15:17:42 -0800447 entry = NULL;
448 }
449
Andreas Huber078cfcf2011-09-15 12:25:04 -0700450 numBytesAvailableToWrite -= copy;
451 size_t copiedFrames = copy / mAudioSink->frameSize();
452 mNumFramesWritten += copiedFrames;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700453
454 notifyIfMediaRenderingStarted();
Andreas Huberf9334412010-12-15 15:17:42 -0800455 }
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800456
457 notifyPosition();
Andreas Huber078cfcf2011-09-15 12:25:04 -0700458
459 return !mAudioQueue.empty();
Andreas Huberf9334412010-12-15 15:17:42 -0800460}
461
462void NuPlayer::Renderer::postDrainVideoQueue() {
Andreas Huberb4082222011-01-20 15:23:04 -0800463 if (mDrainVideoQueuePending || mSyncQueues || mPaused) {
Andreas Huberf9334412010-12-15 15:17:42 -0800464 return;
465 }
466
467 if (mVideoQueue.empty()) {
468 return;
469 }
470
471 QueueEntry &entry = *mVideoQueue.begin();
472
473 sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, id());
474 msg->setInt32("generation", mVideoQueueGeneration);
475
476 int64_t delayUs;
477
478 if (entry.mBuffer == NULL) {
479 // EOS doesn't carry a timestamp.
480 delayUs = 0;
Andreas Huberd5e56232013-03-12 11:01:43 -0700481 } else if (mFlags & FLAG_REAL_TIME) {
482 int64_t mediaTimeUs;
483 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
484
485 delayUs = mediaTimeUs - ALooper::GetNowUs();
Andreas Huberf9334412010-12-15 15:17:42 -0800486 } else {
487 int64_t mediaTimeUs;
488 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
489
490 if (mAnchorTimeMediaUs < 0) {
491 delayUs = 0;
492
Andreas Huber3831a062010-12-21 10:22:33 -0800493 if (!mHasAudio) {
Andreas Huberf9334412010-12-15 15:17:42 -0800494 mAnchorTimeMediaUs = mediaTimeUs;
495 mAnchorTimeRealUs = ALooper::GetNowUs();
496 }
497 } else {
498 int64_t realTimeUs =
499 (mediaTimeUs - mAnchorTimeMediaUs) + mAnchorTimeRealUs;
500
501 delayUs = realTimeUs - ALooper::GetNowUs();
502 }
503 }
504
505 msg->post(delayUs);
506
507 mDrainVideoQueuePending = true;
508}
509
510void NuPlayer::Renderer::onDrainVideoQueue() {
511 if (mVideoQueue.empty()) {
512 return;
513 }
514
515 QueueEntry *entry = &*mVideoQueue.begin();
516
517 if (entry->mBuffer == NULL) {
518 // EOS
519
Andreas Huberc92fd242011-08-16 13:48:44 -0700520 notifyEOS(false /* audio */, entry->mFinalResult);
Andreas Huberf9334412010-12-15 15:17:42 -0800521
522 mVideoQueue.erase(mVideoQueue.begin());
523 entry = NULL;
Andreas Huber3fe62152011-09-16 15:09:22 -0700524
525 mVideoLateByUs = 0ll;
526
527 notifyPosition();
Andreas Huberf9334412010-12-15 15:17:42 -0800528 return;
529 }
530
Andreas Huberd5e56232013-03-12 11:01:43 -0700531 int64_t realTimeUs;
532 if (mFlags & FLAG_REAL_TIME) {
533 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
534 } else {
535 int64_t mediaTimeUs;
536 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andreas Huberf9334412010-12-15 15:17:42 -0800537
Andreas Huberd5e56232013-03-12 11:01:43 -0700538 realTimeUs = mediaTimeUs - mAnchorTimeMediaUs + mAnchorTimeRealUs;
539 }
540
Andreas Huber3fe62152011-09-16 15:09:22 -0700541 mVideoLateByUs = ALooper::GetNowUs() - realTimeUs;
Andreas Huber3fe62152011-09-16 15:09:22 -0700542 bool tooLate = (mVideoLateByUs > 40000);
543
544 if (tooLate) {
Andreas Huberafed0e12011-09-20 15:39:58 -0700545 ALOGV("video late by %lld us (%.2f secs)",
546 mVideoLateByUs, mVideoLateByUs / 1E6);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700547 } else {
Oscar Rydhéd6074f02013-10-15 09:54:08 +0200548 ALOGV("rendering video at media time %.2f secs",
549 (mFlags & FLAG_REAL_TIME ? realTimeUs :
550 (realTimeUs + mAnchorTimeMediaUs - mAnchorTimeRealUs)) / 1E6);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700551 }
Andreas Huberf9334412010-12-15 15:17:42 -0800552
Glenn Kasten683525b2011-11-04 18:05:35 -0700553 entry->mNotifyConsumed->setInt32("render", !tooLate);
Andreas Huberf9334412010-12-15 15:17:42 -0800554 entry->mNotifyConsumed->post();
555 mVideoQueue.erase(mVideoQueue.begin());
556 entry = NULL;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800557
James Dongf57b4ea2012-07-20 13:38:36 -0700558 if (!mVideoRenderingStarted) {
559 mVideoRenderingStarted = true;
560 notifyVideoRenderingStart();
561 }
562
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700563 notifyIfMediaRenderingStarted();
564
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800565 notifyPosition();
Andreas Huberf9334412010-12-15 15:17:42 -0800566}
567
James Dongf57b4ea2012-07-20 13:38:36 -0700568void NuPlayer::Renderer::notifyVideoRenderingStart() {
569 sp<AMessage> notify = mNotify->dup();
570 notify->setInt32("what", kWhatVideoRenderingStart);
571 notify->post();
572}
573
Andreas Huberc92fd242011-08-16 13:48:44 -0700574void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult) {
Andreas Huberf9334412010-12-15 15:17:42 -0800575 sp<AMessage> notify = mNotify->dup();
576 notify->setInt32("what", kWhatEOS);
577 notify->setInt32("audio", static_cast<int32_t>(audio));
Andreas Huberc92fd242011-08-16 13:48:44 -0700578 notify->setInt32("finalResult", finalResult);
Andreas Huberf9334412010-12-15 15:17:42 -0800579 notify->post();
580}
581
582void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
583 int32_t audio;
584 CHECK(msg->findInt32("audio", &audio));
585
Andreas Huberbc7f5b22011-01-21 10:15:23 -0800586 if (audio) {
587 mHasAudio = true;
588 } else {
589 mHasVideo = true;
590 }
591
Andreas Huberf9334412010-12-15 15:17:42 -0800592 if (dropBufferWhileFlushing(audio, msg)) {
593 return;
594 }
595
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800596 sp<ABuffer> buffer;
597 CHECK(msg->findBuffer("buffer", &buffer));
Andreas Huberf9334412010-12-15 15:17:42 -0800598
599 sp<AMessage> notifyConsumed;
600 CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
601
602 QueueEntry entry;
603 entry.mBuffer = buffer;
604 entry.mNotifyConsumed = notifyConsumed;
605 entry.mOffset = 0;
606 entry.mFinalResult = OK;
607
608 if (audio) {
Wei Jiabc2fb722014-07-08 16:37:57 -0700609 Mutex::Autolock autoLock(mLock);
Andreas Huberf9334412010-12-15 15:17:42 -0800610 mAudioQueue.push_back(entry);
Wei Jiabc2fb722014-07-08 16:37:57 -0700611 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -0800612 } else {
613 mVideoQueue.push_back(entry);
614 postDrainVideoQueue();
615 }
616
Wei Jiabc2fb722014-07-08 16:37:57 -0700617 Mutex::Autolock autoLock(mLock);
Andreas Hubercb67cd12011-08-26 16:02:19 -0700618 if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
619 return;
Andreas Huberf9334412010-12-15 15:17:42 -0800620 }
Andreas Hubercb67cd12011-08-26 16:02:19 -0700621
622 sp<ABuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
623 sp<ABuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
624
625 if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
626 // EOS signalled on either queue.
Wei Jiabc2fb722014-07-08 16:37:57 -0700627 syncQueuesDone_l();
Andreas Hubercb67cd12011-08-26 16:02:19 -0700628 return;
629 }
630
631 int64_t firstAudioTimeUs;
632 int64_t firstVideoTimeUs;
633 CHECK(firstAudioBuffer->meta()
634 ->findInt64("timeUs", &firstAudioTimeUs));
635 CHECK(firstVideoBuffer->meta()
636 ->findInt64("timeUs", &firstVideoTimeUs));
637
638 int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
639
Steve Block3856b092011-10-20 11:56:00 +0100640 ALOGV("queueDiff = %.2f secs", diff / 1E6);
Andreas Hubercb67cd12011-08-26 16:02:19 -0700641
642 if (diff > 100000ll) {
643 // Audio data starts More than 0.1 secs before video.
644 // Drop some audio.
645
646 (*mAudioQueue.begin()).mNotifyConsumed->post();
647 mAudioQueue.erase(mAudioQueue.begin());
648 return;
649 }
650
Wei Jiabc2fb722014-07-08 16:37:57 -0700651 syncQueuesDone_l();
Andreas Huberf9334412010-12-15 15:17:42 -0800652}
653
Wei Jiabc2fb722014-07-08 16:37:57 -0700654void NuPlayer::Renderer::syncQueuesDone_l() {
Andreas Huberf9334412010-12-15 15:17:42 -0800655 if (!mSyncQueues) {
656 return;
657 }
658
659 mSyncQueues = false;
660
661 if (!mAudioQueue.empty()) {
Wei Jiabc2fb722014-07-08 16:37:57 -0700662 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -0800663 }
664
665 if (!mVideoQueue.empty()) {
666 postDrainVideoQueue();
667 }
668}
669
670void NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
671 int32_t audio;
672 CHECK(msg->findInt32("audio", &audio));
673
674 if (dropBufferWhileFlushing(audio, msg)) {
675 return;
676 }
677
678 int32_t finalResult;
679 CHECK(msg->findInt32("finalResult", &finalResult));
680
681 QueueEntry entry;
682 entry.mOffset = 0;
683 entry.mFinalResult = finalResult;
684
685 if (audio) {
Wei Jiabc2fb722014-07-08 16:37:57 -0700686 Mutex::Autolock autoLock(mLock);
Roger Jönssonb50e83e2013-01-21 16:26:41 +0100687 if (mAudioQueue.empty() && mSyncQueues) {
Wei Jiabc2fb722014-07-08 16:37:57 -0700688 syncQueuesDone_l();
Roger Jönssonb50e83e2013-01-21 16:26:41 +0100689 }
Andreas Huberf9334412010-12-15 15:17:42 -0800690 mAudioQueue.push_back(entry);
Wei Jiabc2fb722014-07-08 16:37:57 -0700691 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -0800692 } else {
Roger Jönssonb50e83e2013-01-21 16:26:41 +0100693 if (mVideoQueue.empty() && mSyncQueues) {
Wei Jiabc2fb722014-07-08 16:37:57 -0700694 Mutex::Autolock autoLock(mLock);
695 syncQueuesDone_l();
Roger Jönssonb50e83e2013-01-21 16:26:41 +0100696 }
Andreas Huberf9334412010-12-15 15:17:42 -0800697 mVideoQueue.push_back(entry);
698 postDrainVideoQueue();
699 }
700}
701
702void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
703 int32_t audio;
704 CHECK(msg->findInt32("audio", &audio));
705
706 // If we're currently syncing the queues, i.e. dropping audio while
707 // aligning the first audio/video buffer times and only one of the
708 // two queues has data, we may starve that queue by not requesting
709 // more buffers from the decoder. If the other source then encounters
710 // a discontinuity that leads to flushing, we'll never find the
711 // corresponding discontinuity on the other queue.
712 // Therefore we'll stop syncing the queues if at least one of them
713 // is flushed.
Wei Jiabc2fb722014-07-08 16:37:57 -0700714 {
715 Mutex::Autolock autoLock(mLock);
716 syncQueuesDone_l();
717 }
Andreas Huberf9334412010-12-15 15:17:42 -0800718
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700719 ALOGV("flushing %s", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800720 if (audio) {
Wei Jiabc2fb722014-07-08 16:37:57 -0700721 {
722 Mutex::Autolock autoLock(mLock);
723 flushQueue(&mAudioQueue);
724 }
Andreas Huberf9334412010-12-15 15:17:42 -0800725
726 Mutex::Autolock autoLock(mFlushLock);
727 mFlushingAudio = false;
728
729 mDrainAudioQueuePending = false;
730 ++mAudioQueueGeneration;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700731
732 prepareForMediaRenderingStart();
Wei Jiabc2fb722014-07-08 16:37:57 -0700733 if (offloadingAudio()) {
734 mFirstAudioTimeUs = -1;
735 mAudioSink->pause();
736 mAudioSink->flush();
737 mAudioSink->start();
738 }
Andreas Huberf9334412010-12-15 15:17:42 -0800739 } else {
740 flushQueue(&mVideoQueue);
741
742 Mutex::Autolock autoLock(mFlushLock);
743 mFlushingVideo = false;
744
745 mDrainVideoQueuePending = false;
746 ++mVideoQueueGeneration;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700747
748 prepareForMediaRenderingStart();
Andreas Huberf9334412010-12-15 15:17:42 -0800749 }
750
751 notifyFlushComplete(audio);
752}
753
754void NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
755 while (!queue->empty()) {
756 QueueEntry *entry = &*queue->begin();
757
758 if (entry->mBuffer != NULL) {
759 entry->mNotifyConsumed->post();
760 }
761
762 queue->erase(queue->begin());
763 entry = NULL;
764 }
765}
766
767void NuPlayer::Renderer::notifyFlushComplete(bool audio) {
768 sp<AMessage> notify = mNotify->dup();
769 notify->setInt32("what", kWhatFlushComplete);
770 notify->setInt32("audio", static_cast<int32_t>(audio));
771 notify->post();
772}
773
774bool NuPlayer::Renderer::dropBufferWhileFlushing(
775 bool audio, const sp<AMessage> &msg) {
776 bool flushing = false;
777
778 {
779 Mutex::Autolock autoLock(mFlushLock);
780 if (audio) {
781 flushing = mFlushingAudio;
782 } else {
783 flushing = mFlushingVideo;
784 }
785 }
786
787 if (!flushing) {
788 return false;
789 }
790
791 sp<AMessage> notifyConsumed;
792 if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
793 notifyConsumed->post();
794 }
795
796 return true;
797}
798
Andreas Huber3831a062010-12-21 10:22:33 -0800799void NuPlayer::Renderer::onAudioSinkChanged() {
Wei Jiabc2fb722014-07-08 16:37:57 -0700800 if (offloadingAudio()) {
801 return;
802 }
Andreas Huber3831a062010-12-21 10:22:33 -0800803 CHECK(!mDrainAudioQueuePending);
804 mNumFramesWritten = 0;
Marco Nelissen4110c102012-03-29 09:31:28 -0700805 uint32_t written;
806 if (mAudioSink->getFramesWritten(&written) == OK) {
807 mNumFramesWritten = written;
808 }
Andreas Huber3831a062010-12-21 10:22:33 -0800809}
810
Wei Jiabc2fb722014-07-08 16:37:57 -0700811void NuPlayer::Renderer::onDisableOffloadAudio() {
812 Mutex::Autolock autoLock(mLock);
813 mFlags &= ~FLAG_OFFLOAD_AUDIO;
814}
815
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800816void NuPlayer::Renderer::notifyPosition() {
817 if (mAnchorTimeRealUs < 0 || mAnchorTimeMediaUs < 0) {
818 return;
819 }
820
821 int64_t nowUs = ALooper::GetNowUs();
Andreas Huber714aa7b2011-09-13 08:28:38 -0700822
823 if (mLastPositionUpdateUs >= 0
824 && nowUs < mLastPositionUpdateUs + kMinPositionUpdateDelayUs) {
825 return;
826 }
827 mLastPositionUpdateUs = nowUs;
828
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800829 int64_t positionUs = (nowUs - mAnchorTimeRealUs) + mAnchorTimeMediaUs;
830
831 sp<AMessage> notify = mNotify->dup();
832 notify->setInt32("what", kWhatPosition);
833 notify->setInt64("positionUs", positionUs);
Andreas Huber3fe62152011-09-16 15:09:22 -0700834 notify->setInt64("videoLateByUs", mVideoLateByUs);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800835 notify->post();
836}
837
Andreas Huberb4082222011-01-20 15:23:04 -0800838void NuPlayer::Renderer::onPause() {
839 CHECK(!mPaused);
840
841 mDrainAudioQueuePending = false;
842 ++mAudioQueueGeneration;
843
844 mDrainVideoQueuePending = false;
845 ++mVideoQueueGeneration;
846
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700847 prepareForMediaRenderingStart();
848
Andreas Huberb4082222011-01-20 15:23:04 -0800849 if (mHasAudio) {
850 mAudioSink->pause();
851 }
852
Andreas Huberea9d51b2011-11-30 09:53:40 -0800853 ALOGV("now paused audio queue has %d entries, video has %d entries",
854 mAudioQueue.size(), mVideoQueue.size());
Andreas Huberb58ce9f2011-11-28 16:27:35 -0800855
Andreas Huberb4082222011-01-20 15:23:04 -0800856 mPaused = true;
857}
858
859void NuPlayer::Renderer::onResume() {
Andreas Huberb58ce9f2011-11-28 16:27:35 -0800860 if (!mPaused) {
861 return;
862 }
Andreas Huberb4082222011-01-20 15:23:04 -0800863
864 if (mHasAudio) {
865 mAudioSink->start();
866 }
867
868 mPaused = false;
869
Wei Jiabc2fb722014-07-08 16:37:57 -0700870 Mutex::Autolock autoLock(mLock);
Andreas Huberb4082222011-01-20 15:23:04 -0800871 if (!mAudioQueue.empty()) {
Wei Jiabc2fb722014-07-08 16:37:57 -0700872 postDrainAudioQueue_l();
Andreas Huberb4082222011-01-20 15:23:04 -0800873 }
874
875 if (!mVideoQueue.empty()) {
876 postDrainVideoQueue();
877 }
878}
879
Andreas Huberf9334412010-12-15 15:17:42 -0800880} // namespace android
881