blob: b543d9dd07a45cdde1d7ab10f615cbb364274f84 [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,
Andreas Huberd5e56232013-03-12 11:01:43 -070034 const sp<AMessage> &notify,
35 uint32_t flags)
Andreas Huberf9334412010-12-15 15:17:42 -080036 : mAudioSink(sink),
37 mNotify(notify),
Andreas Huberd5e56232013-03-12 11:01:43 -070038 mFlags(flags),
Andreas Huberf9334412010-12-15 15:17:42 -080039 mNumFramesWritten(0),
40 mDrainAudioQueuePending(false),
41 mDrainVideoQueuePending(false),
42 mAudioQueueGeneration(0),
43 mVideoQueueGeneration(0),
44 mAnchorTimeMediaUs(-1),
45 mAnchorTimeRealUs(-1),
46 mFlushingAudio(false),
47 mFlushingVideo(false),
Andreas Huberbc7f5b22011-01-21 10:15:23 -080048 mHasAudio(false),
49 mHasVideo(false),
50 mSyncQueues(false),
Andreas Huber714aa7b2011-09-13 08:28:38 -070051 mPaused(false),
James Dongf57b4ea2012-07-20 13:38:36 -070052 mVideoRenderingStarted(false),
Andreas Huber3fe62152011-09-16 15:09:22 -070053 mLastPositionUpdateUs(-1ll),
54 mVideoLateByUs(0ll) {
Andreas Huberf9334412010-12-15 15:17:42 -080055}
56
57NuPlayer::Renderer::~Renderer() {
58}
59
60void NuPlayer::Renderer::queueBuffer(
61 bool audio,
62 const sp<ABuffer> &buffer,
63 const sp<AMessage> &notifyConsumed) {
64 sp<AMessage> msg = new AMessage(kWhatQueueBuffer, id());
65 msg->setInt32("audio", static_cast<int32_t>(audio));
Andreas Huber2d8bedd2012-02-21 14:38:23 -080066 msg->setBuffer("buffer", buffer);
Andreas Huberf9334412010-12-15 15:17:42 -080067 msg->setMessage("notifyConsumed", notifyConsumed);
68 msg->post();
69}
70
71void NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
72 CHECK_NE(finalResult, (status_t)OK);
73
74 sp<AMessage> msg = new AMessage(kWhatQueueEOS, id());
75 msg->setInt32("audio", static_cast<int32_t>(audio));
76 msg->setInt32("finalResult", finalResult);
77 msg->post();
78}
79
80void NuPlayer::Renderer::flush(bool audio) {
81 {
82 Mutex::Autolock autoLock(mFlushLock);
83 if (audio) {
84 CHECK(!mFlushingAudio);
85 mFlushingAudio = true;
86 } else {
87 CHECK(!mFlushingVideo);
88 mFlushingVideo = true;
89 }
90 }
91
92 sp<AMessage> msg = new AMessage(kWhatFlush, id());
93 msg->setInt32("audio", static_cast<int32_t>(audio));
94 msg->post();
95}
96
97void NuPlayer::Renderer::signalTimeDiscontinuity() {
Andreas Huber14f76722013-01-15 09:04:18 -080098 // CHECK(mAudioQueue.empty());
99 // CHECK(mVideoQueue.empty());
Andreas Huberf9334412010-12-15 15:17:42 -0800100 mAnchorTimeMediaUs = -1;
101 mAnchorTimeRealUs = -1;
Andreas Huber14f76722013-01-15 09:04:18 -0800102 mSyncQueues = false;
Andreas Huberf9334412010-12-15 15:17:42 -0800103}
104
Andreas Huberb4082222011-01-20 15:23:04 -0800105void NuPlayer::Renderer::pause() {
106 (new AMessage(kWhatPause, id()))->post();
107}
108
109void NuPlayer::Renderer::resume() {
110 (new AMessage(kWhatResume, id()))->post();
111}
112
Andreas Huberf9334412010-12-15 15:17:42 -0800113void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
114 switch (msg->what()) {
115 case kWhatDrainAudioQueue:
116 {
117 int32_t generation;
118 CHECK(msg->findInt32("generation", &generation));
119 if (generation != mAudioQueueGeneration) {
120 break;
121 }
122
123 mDrainAudioQueuePending = false;
124
Andreas Huber078cfcf2011-09-15 12:25:04 -0700125 if (onDrainAudioQueue()) {
126 uint32_t numFramesPlayed;
127 CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
128 (status_t)OK);
Andreas Huberf9334412010-12-15 15:17:42 -0800129
Andreas Huber078cfcf2011-09-15 12:25:04 -0700130 uint32_t numFramesPendingPlayout =
131 mNumFramesWritten - numFramesPlayed;
132
133 // This is how long the audio sink will have data to
134 // play back.
135 int64_t delayUs =
136 mAudioSink->msecsPerFrame()
137 * numFramesPendingPlayout * 1000ll;
138
139 // Let's give it more data after about half that time
140 // has elapsed.
141 postDrainAudioQueue(delayUs / 2);
142 }
Andreas Huberf9334412010-12-15 15:17:42 -0800143 break;
144 }
145
146 case kWhatDrainVideoQueue:
147 {
148 int32_t generation;
149 CHECK(msg->findInt32("generation", &generation));
150 if (generation != mVideoQueueGeneration) {
151 break;
152 }
153
154 mDrainVideoQueuePending = false;
155
156 onDrainVideoQueue();
157
158 postDrainVideoQueue();
159 break;
160 }
161
162 case kWhatQueueBuffer:
163 {
164 onQueueBuffer(msg);
165 break;
166 }
167
168 case kWhatQueueEOS:
169 {
170 onQueueEOS(msg);
171 break;
172 }
173
174 case kWhatFlush:
175 {
176 onFlush(msg);
177 break;
178 }
179
Andreas Huber3831a062010-12-21 10:22:33 -0800180 case kWhatAudioSinkChanged:
181 {
182 onAudioSinkChanged();
183 break;
184 }
185
Andreas Huberb4082222011-01-20 15:23:04 -0800186 case kWhatPause:
187 {
188 onPause();
189 break;
190 }
191
192 case kWhatResume:
193 {
194 onResume();
195 break;
196 }
197
Andreas Huberf9334412010-12-15 15:17:42 -0800198 default:
199 TRESPASS();
200 break;
201 }
202}
203
Andreas Huber078cfcf2011-09-15 12:25:04 -0700204void NuPlayer::Renderer::postDrainAudioQueue(int64_t delayUs) {
Andreas Huberb4082222011-01-20 15:23:04 -0800205 if (mDrainAudioQueuePending || mSyncQueues || mPaused) {
Andreas Huberf9334412010-12-15 15:17:42 -0800206 return;
207 }
208
209 if (mAudioQueue.empty()) {
210 return;
211 }
212
213 mDrainAudioQueuePending = true;
214 sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, id());
215 msg->setInt32("generation", mAudioQueueGeneration);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700216 msg->post(delayUs);
Andreas Huberf9334412010-12-15 15:17:42 -0800217}
218
Andreas Huber3831a062010-12-21 10:22:33 -0800219void NuPlayer::Renderer::signalAudioSinkChanged() {
220 (new AMessage(kWhatAudioSinkChanged, id()))->post();
221}
222
Andreas Huber078cfcf2011-09-15 12:25:04 -0700223bool NuPlayer::Renderer::onDrainAudioQueue() {
224 uint32_t numFramesPlayed;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700225 if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
226 return false;
227 }
Andreas Huberc92fd242011-08-16 13:48:44 -0700228
Andreas Huber078cfcf2011-09-15 12:25:04 -0700229 ssize_t numFramesAvailableToWrite =
230 mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
231
232#if 0
233 if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
Steve Blockdf64d152012-01-04 20:05:49 +0000234 ALOGI("audio sink underrun");
Andreas Huber078cfcf2011-09-15 12:25:04 -0700235 } else {
Steve Block3856b092011-10-20 11:56:00 +0100236 ALOGV("audio queue has %d frames left to play",
Andreas Huber078cfcf2011-09-15 12:25:04 -0700237 mAudioSink->frameCount() - numFramesAvailableToWrite);
238 }
239#endif
240
241 size_t numBytesAvailableToWrite =
242 numFramesAvailableToWrite * mAudioSink->frameSize();
243
244 while (numBytesAvailableToWrite > 0 && !mAudioQueue.empty()) {
Andreas Huberc92fd242011-08-16 13:48:44 -0700245 QueueEntry *entry = &*mAudioQueue.begin();
246
247 if (entry->mBuffer == NULL) {
248 // EOS
249
250 notifyEOS(true /* audio */, entry->mFinalResult);
251
252 mAudioQueue.erase(mAudioQueue.begin());
253 entry = NULL;
Andreas Huber078cfcf2011-09-15 12:25:04 -0700254 return false;
Eric Laurent9b7d9502011-03-21 11:49:00 -0700255 }
256
Andreas Huberf9334412010-12-15 15:17:42 -0800257 if (entry->mOffset == 0) {
258 int64_t mediaTimeUs;
259 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
260
Steve Block3856b092011-10-20 11:56:00 +0100261 ALOGV("rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
Andreas Huberf9334412010-12-15 15:17:42 -0800262
263 mAnchorTimeMediaUs = mediaTimeUs;
264
265 uint32_t numFramesPlayed;
266 CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK);
267
268 uint32_t numFramesPendingPlayout =
269 mNumFramesWritten - numFramesPlayed;
270
271 int64_t realTimeOffsetUs =
272 (mAudioSink->latency() / 2 /* XXX */
273 + numFramesPendingPlayout
274 * mAudioSink->msecsPerFrame()) * 1000ll;
275
Steve Blockdf64d152012-01-04 20:05:49 +0000276 // ALOGI("realTimeOffsetUs = %lld us", realTimeOffsetUs);
Andreas Huberf9334412010-12-15 15:17:42 -0800277
278 mAnchorTimeRealUs =
279 ALooper::GetNowUs() + realTimeOffsetUs;
280 }
281
282 size_t copy = entry->mBuffer->size() - entry->mOffset;
283 if (copy > numBytesAvailableToWrite) {
284 copy = numBytesAvailableToWrite;
285 }
286
287 CHECK_EQ(mAudioSink->write(
288 entry->mBuffer->data() + entry->mOffset, copy),
289 (ssize_t)copy);
290
291 entry->mOffset += copy;
292 if (entry->mOffset == entry->mBuffer->size()) {
293 entry->mNotifyConsumed->post();
294 mAudioQueue.erase(mAudioQueue.begin());
Eric Laurent9b7d9502011-03-21 11:49:00 -0700295
Andreas Huberf9334412010-12-15 15:17:42 -0800296 entry = NULL;
297 }
298
Andreas Huber078cfcf2011-09-15 12:25:04 -0700299 numBytesAvailableToWrite -= copy;
300 size_t copiedFrames = copy / mAudioSink->frameSize();
301 mNumFramesWritten += copiedFrames;
Andreas Huberf9334412010-12-15 15:17:42 -0800302 }
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800303
304 notifyPosition();
Andreas Huber078cfcf2011-09-15 12:25:04 -0700305
306 return !mAudioQueue.empty();
Andreas Huberf9334412010-12-15 15:17:42 -0800307}
308
309void NuPlayer::Renderer::postDrainVideoQueue() {
Andreas Huberb4082222011-01-20 15:23:04 -0800310 if (mDrainVideoQueuePending || mSyncQueues || mPaused) {
Andreas Huberf9334412010-12-15 15:17:42 -0800311 return;
312 }
313
314 if (mVideoQueue.empty()) {
315 return;
316 }
317
318 QueueEntry &entry = *mVideoQueue.begin();
319
320 sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, id());
321 msg->setInt32("generation", mVideoQueueGeneration);
322
323 int64_t delayUs;
324
325 if (entry.mBuffer == NULL) {
326 // EOS doesn't carry a timestamp.
327 delayUs = 0;
Andreas Huberd5e56232013-03-12 11:01:43 -0700328 } else if (mFlags & FLAG_REAL_TIME) {
329 int64_t mediaTimeUs;
330 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
331
332 delayUs = mediaTimeUs - ALooper::GetNowUs();
Andreas Huberf9334412010-12-15 15:17:42 -0800333 } else {
334 int64_t mediaTimeUs;
335 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
336
337 if (mAnchorTimeMediaUs < 0) {
338 delayUs = 0;
339
Andreas Huber3831a062010-12-21 10:22:33 -0800340 if (!mHasAudio) {
Andreas Huberf9334412010-12-15 15:17:42 -0800341 mAnchorTimeMediaUs = mediaTimeUs;
342 mAnchorTimeRealUs = ALooper::GetNowUs();
343 }
344 } else {
345 int64_t realTimeUs =
346 (mediaTimeUs - mAnchorTimeMediaUs) + mAnchorTimeRealUs;
347
348 delayUs = realTimeUs - ALooper::GetNowUs();
349 }
350 }
351
352 msg->post(delayUs);
353
354 mDrainVideoQueuePending = true;
355}
356
357void NuPlayer::Renderer::onDrainVideoQueue() {
358 if (mVideoQueue.empty()) {
359 return;
360 }
361
362 QueueEntry *entry = &*mVideoQueue.begin();
363
364 if (entry->mBuffer == NULL) {
365 // EOS
366
Andreas Huberc92fd242011-08-16 13:48:44 -0700367 notifyEOS(false /* audio */, entry->mFinalResult);
Andreas Huberf9334412010-12-15 15:17:42 -0800368
369 mVideoQueue.erase(mVideoQueue.begin());
370 entry = NULL;
Andreas Huber3fe62152011-09-16 15:09:22 -0700371
372 mVideoLateByUs = 0ll;
373
374 notifyPosition();
Andreas Huberf9334412010-12-15 15:17:42 -0800375 return;
376 }
377
Andreas Huberd5e56232013-03-12 11:01:43 -0700378 int64_t realTimeUs;
379 if (mFlags & FLAG_REAL_TIME) {
380 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
381 } else {
382 int64_t mediaTimeUs;
383 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andreas Huberf9334412010-12-15 15:17:42 -0800384
Andreas Huberd5e56232013-03-12 11:01:43 -0700385 realTimeUs = mediaTimeUs - mAnchorTimeMediaUs + mAnchorTimeRealUs;
386 }
387
Andreas Huber3fe62152011-09-16 15:09:22 -0700388 mVideoLateByUs = ALooper::GetNowUs() - realTimeUs;
Andreas Huber3fe62152011-09-16 15:09:22 -0700389 bool tooLate = (mVideoLateByUs > 40000);
390
391 if (tooLate) {
Andreas Huberafed0e12011-09-20 15:39:58 -0700392 ALOGV("video late by %lld us (%.2f secs)",
393 mVideoLateByUs, mVideoLateByUs / 1E6);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700394 } else {
Steve Block3856b092011-10-20 11:56:00 +0100395 ALOGV("rendering video at media time %.2f secs", mediaTimeUs / 1E6);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700396 }
Andreas Huberf9334412010-12-15 15:17:42 -0800397
Glenn Kasten683525b2011-11-04 18:05:35 -0700398 entry->mNotifyConsumed->setInt32("render", !tooLate);
Andreas Huberf9334412010-12-15 15:17:42 -0800399 entry->mNotifyConsumed->post();
400 mVideoQueue.erase(mVideoQueue.begin());
401 entry = NULL;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800402
James Dongf57b4ea2012-07-20 13:38:36 -0700403 if (!mVideoRenderingStarted) {
404 mVideoRenderingStarted = true;
405 notifyVideoRenderingStart();
406 }
407
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800408 notifyPosition();
Andreas Huberf9334412010-12-15 15:17:42 -0800409}
410
James Dongf57b4ea2012-07-20 13:38:36 -0700411void NuPlayer::Renderer::notifyVideoRenderingStart() {
412 sp<AMessage> notify = mNotify->dup();
413 notify->setInt32("what", kWhatVideoRenderingStart);
414 notify->post();
415}
416
Andreas Huberc92fd242011-08-16 13:48:44 -0700417void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult) {
Andreas Huberf9334412010-12-15 15:17:42 -0800418 sp<AMessage> notify = mNotify->dup();
419 notify->setInt32("what", kWhatEOS);
420 notify->setInt32("audio", static_cast<int32_t>(audio));
Andreas Huberc92fd242011-08-16 13:48:44 -0700421 notify->setInt32("finalResult", finalResult);
Andreas Huberf9334412010-12-15 15:17:42 -0800422 notify->post();
423}
424
425void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
426 int32_t audio;
427 CHECK(msg->findInt32("audio", &audio));
428
Andreas Huberbc7f5b22011-01-21 10:15:23 -0800429 if (audio) {
430 mHasAudio = true;
431 } else {
432 mHasVideo = true;
433 }
434
Andreas Huberf9334412010-12-15 15:17:42 -0800435 if (dropBufferWhileFlushing(audio, msg)) {
436 return;
437 }
438
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800439 sp<ABuffer> buffer;
440 CHECK(msg->findBuffer("buffer", &buffer));
Andreas Huberf9334412010-12-15 15:17:42 -0800441
442 sp<AMessage> notifyConsumed;
443 CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
444
445 QueueEntry entry;
446 entry.mBuffer = buffer;
447 entry.mNotifyConsumed = notifyConsumed;
448 entry.mOffset = 0;
449 entry.mFinalResult = OK;
450
451 if (audio) {
452 mAudioQueue.push_back(entry);
453 postDrainAudioQueue();
454 } else {
455 mVideoQueue.push_back(entry);
456 postDrainVideoQueue();
457 }
458
Andreas Hubercb67cd12011-08-26 16:02:19 -0700459 if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
460 return;
Andreas Huberf9334412010-12-15 15:17:42 -0800461 }
Andreas Hubercb67cd12011-08-26 16:02:19 -0700462
463 sp<ABuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
464 sp<ABuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
465
466 if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
467 // EOS signalled on either queue.
468 syncQueuesDone();
469 return;
470 }
471
472 int64_t firstAudioTimeUs;
473 int64_t firstVideoTimeUs;
474 CHECK(firstAudioBuffer->meta()
475 ->findInt64("timeUs", &firstAudioTimeUs));
476 CHECK(firstVideoBuffer->meta()
477 ->findInt64("timeUs", &firstVideoTimeUs));
478
479 int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
480
Steve Block3856b092011-10-20 11:56:00 +0100481 ALOGV("queueDiff = %.2f secs", diff / 1E6);
Andreas Hubercb67cd12011-08-26 16:02:19 -0700482
483 if (diff > 100000ll) {
484 // Audio data starts More than 0.1 secs before video.
485 // Drop some audio.
486
487 (*mAudioQueue.begin()).mNotifyConsumed->post();
488 mAudioQueue.erase(mAudioQueue.begin());
489 return;
490 }
491
492 syncQueuesDone();
Andreas Huberf9334412010-12-15 15:17:42 -0800493}
494
495void NuPlayer::Renderer::syncQueuesDone() {
496 if (!mSyncQueues) {
497 return;
498 }
499
500 mSyncQueues = false;
501
502 if (!mAudioQueue.empty()) {
503 postDrainAudioQueue();
504 }
505
506 if (!mVideoQueue.empty()) {
507 postDrainVideoQueue();
508 }
509}
510
511void NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
512 int32_t audio;
513 CHECK(msg->findInt32("audio", &audio));
514
515 if (dropBufferWhileFlushing(audio, msg)) {
516 return;
517 }
518
519 int32_t finalResult;
520 CHECK(msg->findInt32("finalResult", &finalResult));
521
522 QueueEntry entry;
523 entry.mOffset = 0;
524 entry.mFinalResult = finalResult;
525
526 if (audio) {
Roger Jönssonb50e83e2013-01-21 16:26:41 +0100527 if (mAudioQueue.empty() && mSyncQueues) {
528 syncQueuesDone();
529 }
Andreas Huberf9334412010-12-15 15:17:42 -0800530 mAudioQueue.push_back(entry);
531 postDrainAudioQueue();
532 } else {
Roger Jönssonb50e83e2013-01-21 16:26:41 +0100533 if (mVideoQueue.empty() && mSyncQueues) {
534 syncQueuesDone();
535 }
Andreas Huberf9334412010-12-15 15:17:42 -0800536 mVideoQueue.push_back(entry);
537 postDrainVideoQueue();
538 }
539}
540
541void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
542 int32_t audio;
543 CHECK(msg->findInt32("audio", &audio));
544
545 // If we're currently syncing the queues, i.e. dropping audio while
546 // aligning the first audio/video buffer times and only one of the
547 // two queues has data, we may starve that queue by not requesting
548 // more buffers from the decoder. If the other source then encounters
549 // a discontinuity that leads to flushing, we'll never find the
550 // corresponding discontinuity on the other queue.
551 // Therefore we'll stop syncing the queues if at least one of them
552 // is flushed.
553 syncQueuesDone();
554
555 if (audio) {
556 flushQueue(&mAudioQueue);
557
558 Mutex::Autolock autoLock(mFlushLock);
559 mFlushingAudio = false;
560
561 mDrainAudioQueuePending = false;
562 ++mAudioQueueGeneration;
563 } else {
564 flushQueue(&mVideoQueue);
565
566 Mutex::Autolock autoLock(mFlushLock);
567 mFlushingVideo = false;
568
569 mDrainVideoQueuePending = false;
570 ++mVideoQueueGeneration;
571 }
572
573 notifyFlushComplete(audio);
574}
575
576void NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
577 while (!queue->empty()) {
578 QueueEntry *entry = &*queue->begin();
579
580 if (entry->mBuffer != NULL) {
581 entry->mNotifyConsumed->post();
582 }
583
584 queue->erase(queue->begin());
585 entry = NULL;
586 }
587}
588
589void NuPlayer::Renderer::notifyFlushComplete(bool audio) {
590 sp<AMessage> notify = mNotify->dup();
591 notify->setInt32("what", kWhatFlushComplete);
592 notify->setInt32("audio", static_cast<int32_t>(audio));
593 notify->post();
594}
595
596bool NuPlayer::Renderer::dropBufferWhileFlushing(
597 bool audio, const sp<AMessage> &msg) {
598 bool flushing = false;
599
600 {
601 Mutex::Autolock autoLock(mFlushLock);
602 if (audio) {
603 flushing = mFlushingAudio;
604 } else {
605 flushing = mFlushingVideo;
606 }
607 }
608
609 if (!flushing) {
610 return false;
611 }
612
613 sp<AMessage> notifyConsumed;
614 if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
615 notifyConsumed->post();
616 }
617
618 return true;
619}
620
Andreas Huber3831a062010-12-21 10:22:33 -0800621void NuPlayer::Renderer::onAudioSinkChanged() {
622 CHECK(!mDrainAudioQueuePending);
623 mNumFramesWritten = 0;
Marco Nelissen4110c102012-03-29 09:31:28 -0700624 uint32_t written;
625 if (mAudioSink->getFramesWritten(&written) == OK) {
626 mNumFramesWritten = written;
627 }
Andreas Huber3831a062010-12-21 10:22:33 -0800628}
629
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800630void NuPlayer::Renderer::notifyPosition() {
631 if (mAnchorTimeRealUs < 0 || mAnchorTimeMediaUs < 0) {
632 return;
633 }
634
635 int64_t nowUs = ALooper::GetNowUs();
Andreas Huber714aa7b2011-09-13 08:28:38 -0700636
637 if (mLastPositionUpdateUs >= 0
638 && nowUs < mLastPositionUpdateUs + kMinPositionUpdateDelayUs) {
639 return;
640 }
641 mLastPositionUpdateUs = nowUs;
642
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800643 int64_t positionUs = (nowUs - mAnchorTimeRealUs) + mAnchorTimeMediaUs;
644
645 sp<AMessage> notify = mNotify->dup();
646 notify->setInt32("what", kWhatPosition);
647 notify->setInt64("positionUs", positionUs);
Andreas Huber3fe62152011-09-16 15:09:22 -0700648 notify->setInt64("videoLateByUs", mVideoLateByUs);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800649 notify->post();
650}
651
Andreas Huberb4082222011-01-20 15:23:04 -0800652void NuPlayer::Renderer::onPause() {
653 CHECK(!mPaused);
654
655 mDrainAudioQueuePending = false;
656 ++mAudioQueueGeneration;
657
658 mDrainVideoQueuePending = false;
659 ++mVideoQueueGeneration;
660
661 if (mHasAudio) {
662 mAudioSink->pause();
663 }
664
Andreas Huberea9d51b2011-11-30 09:53:40 -0800665 ALOGV("now paused audio queue has %d entries, video has %d entries",
666 mAudioQueue.size(), mVideoQueue.size());
Andreas Huberb58ce9f2011-11-28 16:27:35 -0800667
Andreas Huberb4082222011-01-20 15:23:04 -0800668 mPaused = true;
669}
670
671void NuPlayer::Renderer::onResume() {
Andreas Huberb58ce9f2011-11-28 16:27:35 -0800672 if (!mPaused) {
673 return;
674 }
Andreas Huberb4082222011-01-20 15:23:04 -0800675
676 if (mHasAudio) {
677 mAudioSink->start();
678 }
679
680 mPaused = false;
681
682 if (!mAudioQueue.empty()) {
683 postDrainAudioQueue();
684 }
685
686 if (!mVideoQueue.empty()) {
687 postDrainVideoQueue();
688 }
689}
690
Andreas Huberf9334412010-12-15 15:17:42 -0800691} // namespace android
692