blob: 1ba76a5db1024f6a603ba32cffbd7848cf4e67d2 [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>
Andreas Huberf9334412010-12-15 15:17:42 -080026
27namespace android {
28
Andreas Huber714aa7b2011-09-13 08:28:38 -070029// static
30const int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll;
31
Andreas Huberf9334412010-12-15 15:17:42 -080032NuPlayer::Renderer::Renderer(
33 const sp<MediaPlayerBase::AudioSink> &sink,
34 const sp<AMessage> &notify)
35 : mAudioSink(sink),
36 mNotify(notify),
37 mNumFramesWritten(0),
38 mDrainAudioQueuePending(false),
39 mDrainVideoQueuePending(false),
40 mAudioQueueGeneration(0),
41 mVideoQueueGeneration(0),
42 mAnchorTimeMediaUs(-1),
43 mAnchorTimeRealUs(-1),
44 mFlushingAudio(false),
45 mFlushingVideo(false),
Andreas Huberbc7f5b22011-01-21 10:15:23 -080046 mHasAudio(false),
47 mHasVideo(false),
48 mSyncQueues(false),
Andreas Huber714aa7b2011-09-13 08:28:38 -070049 mPaused(false),
James Dongf57b4ea2012-07-20 13:38:36 -070050 mVideoRenderingStarted(false),
Andreas Huber3fe62152011-09-16 15:09:22 -070051 mLastPositionUpdateUs(-1ll),
52 mVideoLateByUs(0ll) {
Andreas Huberf9334412010-12-15 15:17:42 -080053}
54
55NuPlayer::Renderer::~Renderer() {
56}
57
58void NuPlayer::Renderer::queueBuffer(
59 bool audio,
60 const sp<ABuffer> &buffer,
61 const sp<AMessage> &notifyConsumed) {
62 sp<AMessage> msg = new AMessage(kWhatQueueBuffer, id());
63 msg->setInt32("audio", static_cast<int32_t>(audio));
Andreas Huber2d8bedd2012-02-21 14:38:23 -080064 msg->setBuffer("buffer", buffer);
Andreas Huberf9334412010-12-15 15:17:42 -080065 msg->setMessage("notifyConsumed", notifyConsumed);
66 msg->post();
67}
68
69void NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
70 CHECK_NE(finalResult, (status_t)OK);
71
72 sp<AMessage> msg = new AMessage(kWhatQueueEOS, id());
73 msg->setInt32("audio", static_cast<int32_t>(audio));
74 msg->setInt32("finalResult", finalResult);
75 msg->post();
76}
77
78void NuPlayer::Renderer::flush(bool audio) {
79 {
80 Mutex::Autolock autoLock(mFlushLock);
81 if (audio) {
82 CHECK(!mFlushingAudio);
83 mFlushingAudio = true;
84 } else {
85 CHECK(!mFlushingVideo);
86 mFlushingVideo = true;
87 }
88 }
89
90 sp<AMessage> msg = new AMessage(kWhatFlush, id());
91 msg->setInt32("audio", static_cast<int32_t>(audio));
92 msg->post();
93}
94
95void NuPlayer::Renderer::signalTimeDiscontinuity() {
96 CHECK(mAudioQueue.empty());
97 CHECK(mVideoQueue.empty());
98 mAnchorTimeMediaUs = -1;
99 mAnchorTimeRealUs = -1;
Andreas Huber3831a062010-12-21 10:22:33 -0800100 mSyncQueues = mHasAudio && mHasVideo;
Andreas Huberf9334412010-12-15 15:17:42 -0800101}
102
Andreas Huberb4082222011-01-20 15:23:04 -0800103void NuPlayer::Renderer::pause() {
104 (new AMessage(kWhatPause, id()))->post();
105}
106
107void NuPlayer::Renderer::resume() {
108 (new AMessage(kWhatResume, id()))->post();
109}
110
Andreas Huberf9334412010-12-15 15:17:42 -0800111void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
112 switch (msg->what()) {
113 case kWhatDrainAudioQueue:
114 {
115 int32_t generation;
116 CHECK(msg->findInt32("generation", &generation));
117 if (generation != mAudioQueueGeneration) {
118 break;
119 }
120
121 mDrainAudioQueuePending = false;
122
Andreas Huber078cfcf2011-09-15 12:25:04 -0700123 if (onDrainAudioQueue()) {
124 uint32_t numFramesPlayed;
125 CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
126 (status_t)OK);
Andreas Huberf9334412010-12-15 15:17:42 -0800127
Andreas Huber078cfcf2011-09-15 12:25:04 -0700128 uint32_t numFramesPendingPlayout =
129 mNumFramesWritten - numFramesPlayed;
130
131 // This is how long the audio sink will have data to
132 // play back.
133 int64_t delayUs =
134 mAudioSink->msecsPerFrame()
135 * numFramesPendingPlayout * 1000ll;
136
137 // Let's give it more data after about half that time
138 // has elapsed.
139 postDrainAudioQueue(delayUs / 2);
140 }
Andreas Huberf9334412010-12-15 15:17:42 -0800141 break;
142 }
143
144 case kWhatDrainVideoQueue:
145 {
146 int32_t generation;
147 CHECK(msg->findInt32("generation", &generation));
148 if (generation != mVideoQueueGeneration) {
149 break;
150 }
151
152 mDrainVideoQueuePending = false;
153
154 onDrainVideoQueue();
155
156 postDrainVideoQueue();
157 break;
158 }
159
160 case kWhatQueueBuffer:
161 {
162 onQueueBuffer(msg);
163 break;
164 }
165
166 case kWhatQueueEOS:
167 {
168 onQueueEOS(msg);
169 break;
170 }
171
172 case kWhatFlush:
173 {
174 onFlush(msg);
175 break;
176 }
177
Andreas Huber3831a062010-12-21 10:22:33 -0800178 case kWhatAudioSinkChanged:
179 {
180 onAudioSinkChanged();
181 break;
182 }
183
Andreas Huberb4082222011-01-20 15:23:04 -0800184 case kWhatPause:
185 {
186 onPause();
187 break;
188 }
189
190 case kWhatResume:
191 {
192 onResume();
193 break;
194 }
195
Andreas Huberf9334412010-12-15 15:17:42 -0800196 default:
197 TRESPASS();
198 break;
199 }
200}
201
Andreas Huber078cfcf2011-09-15 12:25:04 -0700202void NuPlayer::Renderer::postDrainAudioQueue(int64_t delayUs) {
Andreas Huberb4082222011-01-20 15:23:04 -0800203 if (mDrainAudioQueuePending || mSyncQueues || mPaused) {
Andreas Huberf9334412010-12-15 15:17:42 -0800204 return;
205 }
206
207 if (mAudioQueue.empty()) {
208 return;
209 }
210
211 mDrainAudioQueuePending = true;
212 sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, id());
213 msg->setInt32("generation", mAudioQueueGeneration);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700214 msg->post(delayUs);
Andreas Huberf9334412010-12-15 15:17:42 -0800215}
216
Andreas Huber3831a062010-12-21 10:22:33 -0800217void NuPlayer::Renderer::signalAudioSinkChanged() {
218 (new AMessage(kWhatAudioSinkChanged, id()))->post();
219}
220
Andreas Huber078cfcf2011-09-15 12:25:04 -0700221bool NuPlayer::Renderer::onDrainAudioQueue() {
222 uint32_t numFramesPlayed;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700223 if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
224 return false;
225 }
Andreas Huberc92fd242011-08-16 13:48:44 -0700226
Andreas Huber078cfcf2011-09-15 12:25:04 -0700227 ssize_t numFramesAvailableToWrite =
228 mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
229
230#if 0
231 if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
Steve Blockdf64d152012-01-04 20:05:49 +0000232 ALOGI("audio sink underrun");
Andreas Huber078cfcf2011-09-15 12:25:04 -0700233 } else {
Steve Block3856b092011-10-20 11:56:00 +0100234 ALOGV("audio queue has %d frames left to play",
Andreas Huber078cfcf2011-09-15 12:25:04 -0700235 mAudioSink->frameCount() - numFramesAvailableToWrite);
236 }
237#endif
238
239 size_t numBytesAvailableToWrite =
240 numFramesAvailableToWrite * mAudioSink->frameSize();
241
242 while (numBytesAvailableToWrite > 0 && !mAudioQueue.empty()) {
Andreas Huberc92fd242011-08-16 13:48:44 -0700243 QueueEntry *entry = &*mAudioQueue.begin();
244
245 if (entry->mBuffer == NULL) {
246 // EOS
247
248 notifyEOS(true /* audio */, entry->mFinalResult);
249
250 mAudioQueue.erase(mAudioQueue.begin());
251 entry = NULL;
Andreas Huber078cfcf2011-09-15 12:25:04 -0700252 return false;
Eric Laurent9b7d9502011-03-21 11:49:00 -0700253 }
254
Andreas Huberf9334412010-12-15 15:17:42 -0800255 if (entry->mOffset == 0) {
256 int64_t mediaTimeUs;
257 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
258
Steve Block3856b092011-10-20 11:56:00 +0100259 ALOGV("rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
Andreas Huberf9334412010-12-15 15:17:42 -0800260
261 mAnchorTimeMediaUs = mediaTimeUs;
262
263 uint32_t numFramesPlayed;
264 CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK);
265
266 uint32_t numFramesPendingPlayout =
267 mNumFramesWritten - numFramesPlayed;
268
269 int64_t realTimeOffsetUs =
270 (mAudioSink->latency() / 2 /* XXX */
271 + numFramesPendingPlayout
272 * mAudioSink->msecsPerFrame()) * 1000ll;
273
Steve Blockdf64d152012-01-04 20:05:49 +0000274 // ALOGI("realTimeOffsetUs = %lld us", realTimeOffsetUs);
Andreas Huberf9334412010-12-15 15:17:42 -0800275
276 mAnchorTimeRealUs =
277 ALooper::GetNowUs() + realTimeOffsetUs;
278 }
279
280 size_t copy = entry->mBuffer->size() - entry->mOffset;
281 if (copy > numBytesAvailableToWrite) {
282 copy = numBytesAvailableToWrite;
283 }
284
285 CHECK_EQ(mAudioSink->write(
286 entry->mBuffer->data() + entry->mOffset, copy),
287 (ssize_t)copy);
288
289 entry->mOffset += copy;
290 if (entry->mOffset == entry->mBuffer->size()) {
291 entry->mNotifyConsumed->post();
292 mAudioQueue.erase(mAudioQueue.begin());
Eric Laurent9b7d9502011-03-21 11:49:00 -0700293
Andreas Huberf9334412010-12-15 15:17:42 -0800294 entry = NULL;
295 }
296
Andreas Huber078cfcf2011-09-15 12:25:04 -0700297 numBytesAvailableToWrite -= copy;
298 size_t copiedFrames = copy / mAudioSink->frameSize();
299 mNumFramesWritten += copiedFrames;
Andreas Huberf9334412010-12-15 15:17:42 -0800300 }
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800301
302 notifyPosition();
Andreas Huber078cfcf2011-09-15 12:25:04 -0700303
304 return !mAudioQueue.empty();
Andreas Huberf9334412010-12-15 15:17:42 -0800305}
306
307void NuPlayer::Renderer::postDrainVideoQueue() {
Andreas Huberb4082222011-01-20 15:23:04 -0800308 if (mDrainVideoQueuePending || mSyncQueues || mPaused) {
Andreas Huberf9334412010-12-15 15:17:42 -0800309 return;
310 }
311
312 if (mVideoQueue.empty()) {
313 return;
314 }
315
316 QueueEntry &entry = *mVideoQueue.begin();
317
318 sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, id());
319 msg->setInt32("generation", mVideoQueueGeneration);
320
321 int64_t delayUs;
322
323 if (entry.mBuffer == NULL) {
324 // EOS doesn't carry a timestamp.
325 delayUs = 0;
326 } else {
327 int64_t mediaTimeUs;
328 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
329
330 if (mAnchorTimeMediaUs < 0) {
331 delayUs = 0;
332
Andreas Huber3831a062010-12-21 10:22:33 -0800333 if (!mHasAudio) {
Andreas Huberf9334412010-12-15 15:17:42 -0800334 mAnchorTimeMediaUs = mediaTimeUs;
335 mAnchorTimeRealUs = ALooper::GetNowUs();
336 }
337 } else {
338 int64_t realTimeUs =
339 (mediaTimeUs - mAnchorTimeMediaUs) + mAnchorTimeRealUs;
340
341 delayUs = realTimeUs - ALooper::GetNowUs();
342 }
343 }
344
345 msg->post(delayUs);
346
347 mDrainVideoQueuePending = true;
348}
349
350void NuPlayer::Renderer::onDrainVideoQueue() {
351 if (mVideoQueue.empty()) {
352 return;
353 }
354
355 QueueEntry *entry = &*mVideoQueue.begin();
356
357 if (entry->mBuffer == NULL) {
358 // EOS
359
Andreas Huberc92fd242011-08-16 13:48:44 -0700360 notifyEOS(false /* audio */, entry->mFinalResult);
Andreas Huberf9334412010-12-15 15:17:42 -0800361
362 mVideoQueue.erase(mVideoQueue.begin());
363 entry = NULL;
Andreas Huber3fe62152011-09-16 15:09:22 -0700364
365 mVideoLateByUs = 0ll;
366
367 notifyPosition();
Andreas Huberf9334412010-12-15 15:17:42 -0800368 return;
369 }
370
Andreas Huberf9334412010-12-15 15:17:42 -0800371 int64_t mediaTimeUs;
372 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
373
Andreas Huber078cfcf2011-09-15 12:25:04 -0700374 int64_t realTimeUs = mediaTimeUs - mAnchorTimeMediaUs + mAnchorTimeRealUs;
Andreas Huber3fe62152011-09-16 15:09:22 -0700375 mVideoLateByUs = ALooper::GetNowUs() - realTimeUs;
Andreas Huber078cfcf2011-09-15 12:25:04 -0700376
Andreas Huber3fe62152011-09-16 15:09:22 -0700377 bool tooLate = (mVideoLateByUs > 40000);
378
379 if (tooLate) {
Andreas Huberafed0e12011-09-20 15:39:58 -0700380 ALOGV("video late by %lld us (%.2f secs)",
381 mVideoLateByUs, mVideoLateByUs / 1E6);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700382 } else {
Steve Block3856b092011-10-20 11:56:00 +0100383 ALOGV("rendering video at media time %.2f secs", mediaTimeUs / 1E6);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700384 }
Andreas Huberf9334412010-12-15 15:17:42 -0800385
Glenn Kasten683525b2011-11-04 18:05:35 -0700386 entry->mNotifyConsumed->setInt32("render", !tooLate);
Andreas Huberf9334412010-12-15 15:17:42 -0800387 entry->mNotifyConsumed->post();
388 mVideoQueue.erase(mVideoQueue.begin());
389 entry = NULL;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800390
James Dongf57b4ea2012-07-20 13:38:36 -0700391 if (!mVideoRenderingStarted) {
392 mVideoRenderingStarted = true;
393 notifyVideoRenderingStart();
394 }
395
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800396 notifyPosition();
Andreas Huberf9334412010-12-15 15:17:42 -0800397}
398
James Dongf57b4ea2012-07-20 13:38:36 -0700399void NuPlayer::Renderer::notifyVideoRenderingStart() {
400 sp<AMessage> notify = mNotify->dup();
401 notify->setInt32("what", kWhatVideoRenderingStart);
402 notify->post();
403}
404
Andreas Huberc92fd242011-08-16 13:48:44 -0700405void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult) {
Andreas Huberf9334412010-12-15 15:17:42 -0800406 sp<AMessage> notify = mNotify->dup();
407 notify->setInt32("what", kWhatEOS);
408 notify->setInt32("audio", static_cast<int32_t>(audio));
Andreas Huberc92fd242011-08-16 13:48:44 -0700409 notify->setInt32("finalResult", finalResult);
Andreas Huberf9334412010-12-15 15:17:42 -0800410 notify->post();
411}
412
413void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
414 int32_t audio;
415 CHECK(msg->findInt32("audio", &audio));
416
Andreas Huberbc7f5b22011-01-21 10:15:23 -0800417 if (audio) {
418 mHasAudio = true;
419 } else {
420 mHasVideo = true;
421 }
422
Andreas Huberf9334412010-12-15 15:17:42 -0800423 if (dropBufferWhileFlushing(audio, msg)) {
424 return;
425 }
426
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800427 sp<ABuffer> buffer;
428 CHECK(msg->findBuffer("buffer", &buffer));
Andreas Huberf9334412010-12-15 15:17:42 -0800429
430 sp<AMessage> notifyConsumed;
431 CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
432
433 QueueEntry entry;
434 entry.mBuffer = buffer;
435 entry.mNotifyConsumed = notifyConsumed;
436 entry.mOffset = 0;
437 entry.mFinalResult = OK;
438
439 if (audio) {
440 mAudioQueue.push_back(entry);
441 postDrainAudioQueue();
442 } else {
443 mVideoQueue.push_back(entry);
444 postDrainVideoQueue();
445 }
446
Andreas Hubercb67cd12011-08-26 16:02:19 -0700447 if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
448 return;
Andreas Huberf9334412010-12-15 15:17:42 -0800449 }
Andreas Hubercb67cd12011-08-26 16:02:19 -0700450
451 sp<ABuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
452 sp<ABuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
453
454 if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
455 // EOS signalled on either queue.
456 syncQueuesDone();
457 return;
458 }
459
460 int64_t firstAudioTimeUs;
461 int64_t firstVideoTimeUs;
462 CHECK(firstAudioBuffer->meta()
463 ->findInt64("timeUs", &firstAudioTimeUs));
464 CHECK(firstVideoBuffer->meta()
465 ->findInt64("timeUs", &firstVideoTimeUs));
466
467 int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
468
Steve Block3856b092011-10-20 11:56:00 +0100469 ALOGV("queueDiff = %.2f secs", diff / 1E6);
Andreas Hubercb67cd12011-08-26 16:02:19 -0700470
471 if (diff > 100000ll) {
472 // Audio data starts More than 0.1 secs before video.
473 // Drop some audio.
474
475 (*mAudioQueue.begin()).mNotifyConsumed->post();
476 mAudioQueue.erase(mAudioQueue.begin());
477 return;
478 }
479
480 syncQueuesDone();
Andreas Huberf9334412010-12-15 15:17:42 -0800481}
482
483void NuPlayer::Renderer::syncQueuesDone() {
484 if (!mSyncQueues) {
485 return;
486 }
487
488 mSyncQueues = false;
489
490 if (!mAudioQueue.empty()) {
491 postDrainAudioQueue();
492 }
493
494 if (!mVideoQueue.empty()) {
495 postDrainVideoQueue();
496 }
497}
498
499void NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
500 int32_t audio;
501 CHECK(msg->findInt32("audio", &audio));
502
503 if (dropBufferWhileFlushing(audio, msg)) {
504 return;
505 }
506
507 int32_t finalResult;
508 CHECK(msg->findInt32("finalResult", &finalResult));
509
510 QueueEntry entry;
511 entry.mOffset = 0;
512 entry.mFinalResult = finalResult;
513
514 if (audio) {
Roger Jönssonb50e83e2013-01-21 16:26:41 +0100515 if (mAudioQueue.empty() && mSyncQueues) {
516 syncQueuesDone();
517 }
Andreas Huberf9334412010-12-15 15:17:42 -0800518 mAudioQueue.push_back(entry);
519 postDrainAudioQueue();
520 } else {
Roger Jönssonb50e83e2013-01-21 16:26:41 +0100521 if (mVideoQueue.empty() && mSyncQueues) {
522 syncQueuesDone();
523 }
Andreas Huberf9334412010-12-15 15:17:42 -0800524 mVideoQueue.push_back(entry);
525 postDrainVideoQueue();
526 }
527}
528
529void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
530 int32_t audio;
531 CHECK(msg->findInt32("audio", &audio));
532
533 // If we're currently syncing the queues, i.e. dropping audio while
534 // aligning the first audio/video buffer times and only one of the
535 // two queues has data, we may starve that queue by not requesting
536 // more buffers from the decoder. If the other source then encounters
537 // a discontinuity that leads to flushing, we'll never find the
538 // corresponding discontinuity on the other queue.
539 // Therefore we'll stop syncing the queues if at least one of them
540 // is flushed.
541 syncQueuesDone();
542
543 if (audio) {
544 flushQueue(&mAudioQueue);
545
546 Mutex::Autolock autoLock(mFlushLock);
547 mFlushingAudio = false;
548
549 mDrainAudioQueuePending = false;
550 ++mAudioQueueGeneration;
551 } else {
552 flushQueue(&mVideoQueue);
553
554 Mutex::Autolock autoLock(mFlushLock);
555 mFlushingVideo = false;
556
557 mDrainVideoQueuePending = false;
558 ++mVideoQueueGeneration;
559 }
560
561 notifyFlushComplete(audio);
562}
563
564void NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
565 while (!queue->empty()) {
566 QueueEntry *entry = &*queue->begin();
567
568 if (entry->mBuffer != NULL) {
569 entry->mNotifyConsumed->post();
570 }
571
572 queue->erase(queue->begin());
573 entry = NULL;
574 }
575}
576
577void NuPlayer::Renderer::notifyFlushComplete(bool audio) {
578 sp<AMessage> notify = mNotify->dup();
579 notify->setInt32("what", kWhatFlushComplete);
580 notify->setInt32("audio", static_cast<int32_t>(audio));
581 notify->post();
582}
583
584bool NuPlayer::Renderer::dropBufferWhileFlushing(
585 bool audio, const sp<AMessage> &msg) {
586 bool flushing = false;
587
588 {
589 Mutex::Autolock autoLock(mFlushLock);
590 if (audio) {
591 flushing = mFlushingAudio;
592 } else {
593 flushing = mFlushingVideo;
594 }
595 }
596
597 if (!flushing) {
598 return false;
599 }
600
601 sp<AMessage> notifyConsumed;
602 if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
603 notifyConsumed->post();
604 }
605
606 return true;
607}
608
Andreas Huber3831a062010-12-21 10:22:33 -0800609void NuPlayer::Renderer::onAudioSinkChanged() {
610 CHECK(!mDrainAudioQueuePending);
611 mNumFramesWritten = 0;
Marco Nelissen4110c102012-03-29 09:31:28 -0700612 uint32_t written;
613 if (mAudioSink->getFramesWritten(&written) == OK) {
614 mNumFramesWritten = written;
615 }
Andreas Huber3831a062010-12-21 10:22:33 -0800616}
617
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800618void NuPlayer::Renderer::notifyPosition() {
619 if (mAnchorTimeRealUs < 0 || mAnchorTimeMediaUs < 0) {
620 return;
621 }
622
623 int64_t nowUs = ALooper::GetNowUs();
Andreas Huber714aa7b2011-09-13 08:28:38 -0700624
625 if (mLastPositionUpdateUs >= 0
626 && nowUs < mLastPositionUpdateUs + kMinPositionUpdateDelayUs) {
627 return;
628 }
629 mLastPositionUpdateUs = nowUs;
630
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800631 int64_t positionUs = (nowUs - mAnchorTimeRealUs) + mAnchorTimeMediaUs;
632
633 sp<AMessage> notify = mNotify->dup();
634 notify->setInt32("what", kWhatPosition);
635 notify->setInt64("positionUs", positionUs);
Andreas Huber3fe62152011-09-16 15:09:22 -0700636 notify->setInt64("videoLateByUs", mVideoLateByUs);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800637 notify->post();
638}
639
Andreas Huberb4082222011-01-20 15:23:04 -0800640void NuPlayer::Renderer::onPause() {
641 CHECK(!mPaused);
642
643 mDrainAudioQueuePending = false;
644 ++mAudioQueueGeneration;
645
646 mDrainVideoQueuePending = false;
647 ++mVideoQueueGeneration;
648
649 if (mHasAudio) {
650 mAudioSink->pause();
651 }
652
Andreas Huberea9d51b2011-11-30 09:53:40 -0800653 ALOGV("now paused audio queue has %d entries, video has %d entries",
654 mAudioQueue.size(), mVideoQueue.size());
Andreas Huberb58ce9f2011-11-28 16:27:35 -0800655
Andreas Huberb4082222011-01-20 15:23:04 -0800656 mPaused = true;
657}
658
659void NuPlayer::Renderer::onResume() {
Andreas Huberb58ce9f2011-11-28 16:27:35 -0800660 if (!mPaused) {
661 return;
662 }
Andreas Huberb4082222011-01-20 15:23:04 -0800663
664 if (mHasAudio) {
665 mAudioSink->start();
666 }
667
668 mPaused = false;
669
670 if (!mAudioQueue.empty()) {
671 postDrainAudioQueue();
672 }
673
674 if (!mVideoQueue.empty()) {
675 postDrainVideoQueue();
676 }
677}
678
Andreas Huberf9334412010-12-15 15:17:42 -0800679} // namespace android
680