blob: bf5271e7dcbca56f0205580d1fe9233a1d05672e [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
Martin Storsjoda38df52013-09-25 16:05:36 +030023#include "SoftwareRenderer.h"
24
Andreas Huberf9334412010-12-15 15:17:42 -080025#include <media/stagefright/foundation/ABuffer.h>
26#include <media/stagefright/foundation/ADebug.h>
Andreas Huber5bc087c2010-12-23 10:27:40 -080027#include <media/stagefright/foundation/AMessage.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),
Martin Storsjoda38df52013-09-25 16:05:36 +030039 mSoftRenderer(NULL),
Andreas Huberf9334412010-12-15 15:17:42 -080040 mNotify(notify),
Andreas Huberd5e56232013-03-12 11:01:43 -070041 mFlags(flags),
Andreas Huberf9334412010-12-15 15:17:42 -080042 mNumFramesWritten(0),
43 mDrainAudioQueuePending(false),
44 mDrainVideoQueuePending(false),
45 mAudioQueueGeneration(0),
46 mVideoQueueGeneration(0),
47 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() {
Martin Storsjoda38df52013-09-25 16:05:36 +030063 delete mSoftRenderer;
64}
65
66void NuPlayer::Renderer::setSoftRenderer(SoftwareRenderer *softRenderer) {
67 delete mSoftRenderer;
68 mSoftRenderer = softRenderer;
Andreas Huberf9334412010-12-15 15:17:42 -080069}
70
71void NuPlayer::Renderer::queueBuffer(
72 bool audio,
73 const sp<ABuffer> &buffer,
74 const sp<AMessage> &notifyConsumed) {
75 sp<AMessage> msg = new AMessage(kWhatQueueBuffer, id());
76 msg->setInt32("audio", static_cast<int32_t>(audio));
Andreas Huber2d8bedd2012-02-21 14:38:23 -080077 msg->setBuffer("buffer", buffer);
Andreas Huberf9334412010-12-15 15:17:42 -080078 msg->setMessage("notifyConsumed", notifyConsumed);
79 msg->post();
80}
81
82void NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
83 CHECK_NE(finalResult, (status_t)OK);
84
85 sp<AMessage> msg = new AMessage(kWhatQueueEOS, id());
86 msg->setInt32("audio", static_cast<int32_t>(audio));
87 msg->setInt32("finalResult", finalResult);
88 msg->post();
89}
90
91void NuPlayer::Renderer::flush(bool audio) {
92 {
93 Mutex::Autolock autoLock(mFlushLock);
94 if (audio) {
95 CHECK(!mFlushingAudio);
96 mFlushingAudio = true;
97 } else {
98 CHECK(!mFlushingVideo);
99 mFlushingVideo = true;
100 }
101 }
102
103 sp<AMessage> msg = new AMessage(kWhatFlush, id());
104 msg->setInt32("audio", static_cast<int32_t>(audio));
105 msg->post();
106}
107
108void NuPlayer::Renderer::signalTimeDiscontinuity() {
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()) {
126 case kWhatDrainAudioQueue:
127 {
128 int32_t generation;
129 CHECK(msg->findInt32("generation", &generation));
130 if (generation != mAudioQueueGeneration) {
131 break;
132 }
133
134 mDrainAudioQueuePending = false;
135
Andreas Huber078cfcf2011-09-15 12:25:04 -0700136 if (onDrainAudioQueue()) {
137 uint32_t numFramesPlayed;
138 CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
139 (status_t)OK);
Andreas Huberf9334412010-12-15 15:17:42 -0800140
Andreas Huber078cfcf2011-09-15 12:25:04 -0700141 uint32_t numFramesPendingPlayout =
142 mNumFramesWritten - numFramesPlayed;
143
144 // This is how long the audio sink will have data to
145 // play back.
146 int64_t delayUs =
147 mAudioSink->msecsPerFrame()
148 * numFramesPendingPlayout * 1000ll;
149
150 // Let's give it more data after about half that time
151 // has elapsed.
152 postDrainAudioQueue(delayUs / 2);
153 }
Andreas Huberf9334412010-12-15 15:17:42 -0800154 break;
155 }
156
157 case kWhatDrainVideoQueue:
158 {
159 int32_t generation;
160 CHECK(msg->findInt32("generation", &generation));
161 if (generation != mVideoQueueGeneration) {
162 break;
163 }
164
165 mDrainVideoQueuePending = false;
166
167 onDrainVideoQueue();
168
169 postDrainVideoQueue();
170 break;
171 }
172
173 case kWhatQueueBuffer:
174 {
175 onQueueBuffer(msg);
176 break;
177 }
178
179 case kWhatQueueEOS:
180 {
181 onQueueEOS(msg);
182 break;
183 }
184
185 case kWhatFlush:
186 {
187 onFlush(msg);
188 break;
189 }
190
Andreas Huber3831a062010-12-21 10:22:33 -0800191 case kWhatAudioSinkChanged:
192 {
193 onAudioSinkChanged();
194 break;
195 }
196
Andreas Huberb4082222011-01-20 15:23:04 -0800197 case kWhatPause:
198 {
199 onPause();
200 break;
201 }
202
203 case kWhatResume:
204 {
205 onResume();
206 break;
207 }
208
Andreas Huberf9334412010-12-15 15:17:42 -0800209 default:
210 TRESPASS();
211 break;
212 }
213}
214
Andreas Huber078cfcf2011-09-15 12:25:04 -0700215void NuPlayer::Renderer::postDrainAudioQueue(int64_t delayUs) {
Andreas Huberb4082222011-01-20 15:23:04 -0800216 if (mDrainAudioQueuePending || mSyncQueues || mPaused) {
Andreas Huberf9334412010-12-15 15:17:42 -0800217 return;
218 }
219
220 if (mAudioQueue.empty()) {
221 return;
222 }
223
224 mDrainAudioQueuePending = true;
225 sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, id());
226 msg->setInt32("generation", mAudioQueueGeneration);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700227 msg->post(delayUs);
Andreas Huberf9334412010-12-15 15:17:42 -0800228}
229
Andreas Huber3831a062010-12-21 10:22:33 -0800230void NuPlayer::Renderer::signalAudioSinkChanged() {
231 (new AMessage(kWhatAudioSinkChanged, id()))->post();
232}
233
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700234void NuPlayer::Renderer::prepareForMediaRenderingStart() {
235 mAudioRenderingStartGeneration = mAudioQueueGeneration;
236 mVideoRenderingStartGeneration = mVideoQueueGeneration;
237}
238
239void NuPlayer::Renderer::notifyIfMediaRenderingStarted() {
240 if (mVideoRenderingStartGeneration == mVideoQueueGeneration &&
241 mAudioRenderingStartGeneration == mAudioQueueGeneration) {
242 mVideoRenderingStartGeneration = -1;
243 mAudioRenderingStartGeneration = -1;
244
245 sp<AMessage> notify = mNotify->dup();
246 notify->setInt32("what", kWhatMediaRenderingStart);
247 notify->post();
248 }
249}
250
Andreas Huber078cfcf2011-09-15 12:25:04 -0700251bool NuPlayer::Renderer::onDrainAudioQueue() {
252 uint32_t numFramesPlayed;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700253 if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
254 return false;
255 }
Andreas Huberc92fd242011-08-16 13:48:44 -0700256
Andreas Huber078cfcf2011-09-15 12:25:04 -0700257 ssize_t numFramesAvailableToWrite =
258 mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
259
260#if 0
261 if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
Steve Blockdf64d152012-01-04 20:05:49 +0000262 ALOGI("audio sink underrun");
Andreas Huber078cfcf2011-09-15 12:25:04 -0700263 } else {
Steve Block3856b092011-10-20 11:56:00 +0100264 ALOGV("audio queue has %d frames left to play",
Andreas Huber078cfcf2011-09-15 12:25:04 -0700265 mAudioSink->frameCount() - numFramesAvailableToWrite);
266 }
267#endif
268
269 size_t numBytesAvailableToWrite =
270 numFramesAvailableToWrite * mAudioSink->frameSize();
271
272 while (numBytesAvailableToWrite > 0 && !mAudioQueue.empty()) {
Andreas Huberc92fd242011-08-16 13:48:44 -0700273 QueueEntry *entry = &*mAudioQueue.begin();
274
275 if (entry->mBuffer == NULL) {
276 // EOS
277
278 notifyEOS(true /* audio */, entry->mFinalResult);
279
280 mAudioQueue.erase(mAudioQueue.begin());
281 entry = NULL;
Andreas Huber078cfcf2011-09-15 12:25:04 -0700282 return false;
Eric Laurent9b7d9502011-03-21 11:49:00 -0700283 }
284
Andreas Huberf9334412010-12-15 15:17:42 -0800285 if (entry->mOffset == 0) {
286 int64_t mediaTimeUs;
287 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
288
Steve Block3856b092011-10-20 11:56:00 +0100289 ALOGV("rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
Andreas Huberf9334412010-12-15 15:17:42 -0800290
291 mAnchorTimeMediaUs = mediaTimeUs;
292
293 uint32_t numFramesPlayed;
294 CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK);
295
296 uint32_t numFramesPendingPlayout =
297 mNumFramesWritten - numFramesPlayed;
298
299 int64_t realTimeOffsetUs =
300 (mAudioSink->latency() / 2 /* XXX */
301 + numFramesPendingPlayout
302 * mAudioSink->msecsPerFrame()) * 1000ll;
303
Steve Blockdf64d152012-01-04 20:05:49 +0000304 // ALOGI("realTimeOffsetUs = %lld us", realTimeOffsetUs);
Andreas Huberf9334412010-12-15 15:17:42 -0800305
306 mAnchorTimeRealUs =
307 ALooper::GetNowUs() + realTimeOffsetUs;
308 }
309
310 size_t copy = entry->mBuffer->size() - entry->mOffset;
311 if (copy > numBytesAvailableToWrite) {
312 copy = numBytesAvailableToWrite;
313 }
314
315 CHECK_EQ(mAudioSink->write(
316 entry->mBuffer->data() + entry->mOffset, copy),
317 (ssize_t)copy);
318
319 entry->mOffset += copy;
320 if (entry->mOffset == entry->mBuffer->size()) {
321 entry->mNotifyConsumed->post();
322 mAudioQueue.erase(mAudioQueue.begin());
Eric Laurent9b7d9502011-03-21 11:49:00 -0700323
Andreas Huberf9334412010-12-15 15:17:42 -0800324 entry = NULL;
325 }
326
Andreas Huber078cfcf2011-09-15 12:25:04 -0700327 numBytesAvailableToWrite -= copy;
328 size_t copiedFrames = copy / mAudioSink->frameSize();
329 mNumFramesWritten += copiedFrames;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700330
331 notifyIfMediaRenderingStarted();
Andreas Huberf9334412010-12-15 15:17:42 -0800332 }
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800333
334 notifyPosition();
Andreas Huber078cfcf2011-09-15 12:25:04 -0700335
336 return !mAudioQueue.empty();
Andreas Huberf9334412010-12-15 15:17:42 -0800337}
338
339void NuPlayer::Renderer::postDrainVideoQueue() {
Andreas Huberb4082222011-01-20 15:23:04 -0800340 if (mDrainVideoQueuePending || mSyncQueues || mPaused) {
Andreas Huberf9334412010-12-15 15:17:42 -0800341 return;
342 }
343
344 if (mVideoQueue.empty()) {
345 return;
346 }
347
348 QueueEntry &entry = *mVideoQueue.begin();
349
350 sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, id());
351 msg->setInt32("generation", mVideoQueueGeneration);
352
353 int64_t delayUs;
354
355 if (entry.mBuffer == NULL) {
356 // EOS doesn't carry a timestamp.
357 delayUs = 0;
Andreas Huberd5e56232013-03-12 11:01:43 -0700358 } else if (mFlags & FLAG_REAL_TIME) {
359 int64_t mediaTimeUs;
360 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
361
362 delayUs = mediaTimeUs - ALooper::GetNowUs();
Andreas Huberf9334412010-12-15 15:17:42 -0800363 } else {
364 int64_t mediaTimeUs;
365 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
366
367 if (mAnchorTimeMediaUs < 0) {
368 delayUs = 0;
369
Andreas Huber3831a062010-12-21 10:22:33 -0800370 if (!mHasAudio) {
Andreas Huberf9334412010-12-15 15:17:42 -0800371 mAnchorTimeMediaUs = mediaTimeUs;
372 mAnchorTimeRealUs = ALooper::GetNowUs();
373 }
374 } else {
375 int64_t realTimeUs =
376 (mediaTimeUs - mAnchorTimeMediaUs) + mAnchorTimeRealUs;
377
378 delayUs = realTimeUs - ALooper::GetNowUs();
379 }
380 }
381
382 msg->post(delayUs);
383
384 mDrainVideoQueuePending = true;
385}
386
387void NuPlayer::Renderer::onDrainVideoQueue() {
388 if (mVideoQueue.empty()) {
389 return;
390 }
391
392 QueueEntry *entry = &*mVideoQueue.begin();
393
394 if (entry->mBuffer == NULL) {
395 // EOS
396
Andreas Huberc92fd242011-08-16 13:48:44 -0700397 notifyEOS(false /* audio */, entry->mFinalResult);
Andreas Huberf9334412010-12-15 15:17:42 -0800398
399 mVideoQueue.erase(mVideoQueue.begin());
400 entry = NULL;
Andreas Huber3fe62152011-09-16 15:09:22 -0700401
402 mVideoLateByUs = 0ll;
403
404 notifyPosition();
Andreas Huberf9334412010-12-15 15:17:42 -0800405 return;
406 }
407
Andreas Huberd5e56232013-03-12 11:01:43 -0700408 int64_t realTimeUs;
409 if (mFlags & FLAG_REAL_TIME) {
410 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
411 } else {
412 int64_t mediaTimeUs;
413 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andreas Huberf9334412010-12-15 15:17:42 -0800414
Andreas Huberd5e56232013-03-12 11:01:43 -0700415 realTimeUs = mediaTimeUs - mAnchorTimeMediaUs + mAnchorTimeRealUs;
416 }
417
Andreas Huber3fe62152011-09-16 15:09:22 -0700418 mVideoLateByUs = ALooper::GetNowUs() - realTimeUs;
Andreas Huber3fe62152011-09-16 15:09:22 -0700419 bool tooLate = (mVideoLateByUs > 40000);
420
421 if (tooLate) {
Andreas Huberafed0e12011-09-20 15:39:58 -0700422 ALOGV("video late by %lld us (%.2f secs)",
423 mVideoLateByUs, mVideoLateByUs / 1E6);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700424 } else {
Oscar Rydhéd6074f02013-10-15 09:54:08 +0200425 ALOGV("rendering video at media time %.2f secs",
426 (mFlags & FLAG_REAL_TIME ? realTimeUs :
427 (realTimeUs + mAnchorTimeMediaUs - mAnchorTimeRealUs)) / 1E6);
Martin Storsjoda38df52013-09-25 16:05:36 +0300428 if (mSoftRenderer != NULL) {
429 mSoftRenderer->render(entry->mBuffer->data(), entry->mBuffer->size(), NULL);
430 }
Andreas Huber078cfcf2011-09-15 12:25:04 -0700431 }
Andreas Huberf9334412010-12-15 15:17:42 -0800432
Glenn Kasten683525b2011-11-04 18:05:35 -0700433 entry->mNotifyConsumed->setInt32("render", !tooLate);
Andreas Huberf9334412010-12-15 15:17:42 -0800434 entry->mNotifyConsumed->post();
435 mVideoQueue.erase(mVideoQueue.begin());
436 entry = NULL;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800437
James Dongf57b4ea2012-07-20 13:38:36 -0700438 if (!mVideoRenderingStarted) {
439 mVideoRenderingStarted = true;
440 notifyVideoRenderingStart();
441 }
442
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700443 notifyIfMediaRenderingStarted();
444
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800445 notifyPosition();
Andreas Huberf9334412010-12-15 15:17:42 -0800446}
447
James Dongf57b4ea2012-07-20 13:38:36 -0700448void NuPlayer::Renderer::notifyVideoRenderingStart() {
449 sp<AMessage> notify = mNotify->dup();
450 notify->setInt32("what", kWhatVideoRenderingStart);
451 notify->post();
452}
453
Andreas Huberc92fd242011-08-16 13:48:44 -0700454void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult) {
Andreas Huberf9334412010-12-15 15:17:42 -0800455 sp<AMessage> notify = mNotify->dup();
456 notify->setInt32("what", kWhatEOS);
457 notify->setInt32("audio", static_cast<int32_t>(audio));
Andreas Huberc92fd242011-08-16 13:48:44 -0700458 notify->setInt32("finalResult", finalResult);
Andreas Huberf9334412010-12-15 15:17:42 -0800459 notify->post();
460}
461
462void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
463 int32_t audio;
464 CHECK(msg->findInt32("audio", &audio));
465
Andreas Huberbc7f5b22011-01-21 10:15:23 -0800466 if (audio) {
467 mHasAudio = true;
468 } else {
469 mHasVideo = true;
470 }
471
Andreas Huberf9334412010-12-15 15:17:42 -0800472 if (dropBufferWhileFlushing(audio, msg)) {
473 return;
474 }
475
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800476 sp<ABuffer> buffer;
477 CHECK(msg->findBuffer("buffer", &buffer));
Andreas Huberf9334412010-12-15 15:17:42 -0800478
479 sp<AMessage> notifyConsumed;
480 CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
481
482 QueueEntry entry;
483 entry.mBuffer = buffer;
484 entry.mNotifyConsumed = notifyConsumed;
485 entry.mOffset = 0;
486 entry.mFinalResult = OK;
487
488 if (audio) {
489 mAudioQueue.push_back(entry);
490 postDrainAudioQueue();
491 } else {
492 mVideoQueue.push_back(entry);
493 postDrainVideoQueue();
494 }
495
Andreas Hubercb67cd12011-08-26 16:02:19 -0700496 if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
497 return;
Andreas Huberf9334412010-12-15 15:17:42 -0800498 }
Andreas Hubercb67cd12011-08-26 16:02:19 -0700499
500 sp<ABuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
501 sp<ABuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
502
503 if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
504 // EOS signalled on either queue.
505 syncQueuesDone();
506 return;
507 }
508
509 int64_t firstAudioTimeUs;
510 int64_t firstVideoTimeUs;
511 CHECK(firstAudioBuffer->meta()
512 ->findInt64("timeUs", &firstAudioTimeUs));
513 CHECK(firstVideoBuffer->meta()
514 ->findInt64("timeUs", &firstVideoTimeUs));
515
516 int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
517
Steve Block3856b092011-10-20 11:56:00 +0100518 ALOGV("queueDiff = %.2f secs", diff / 1E6);
Andreas Hubercb67cd12011-08-26 16:02:19 -0700519
520 if (diff > 100000ll) {
521 // Audio data starts More than 0.1 secs before video.
522 // Drop some audio.
523
524 (*mAudioQueue.begin()).mNotifyConsumed->post();
525 mAudioQueue.erase(mAudioQueue.begin());
526 return;
527 }
528
529 syncQueuesDone();
Andreas Huberf9334412010-12-15 15:17:42 -0800530}
531
532void NuPlayer::Renderer::syncQueuesDone() {
533 if (!mSyncQueues) {
534 return;
535 }
536
537 mSyncQueues = false;
538
539 if (!mAudioQueue.empty()) {
540 postDrainAudioQueue();
541 }
542
543 if (!mVideoQueue.empty()) {
544 postDrainVideoQueue();
545 }
546}
547
548void NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
549 int32_t audio;
550 CHECK(msg->findInt32("audio", &audio));
551
552 if (dropBufferWhileFlushing(audio, msg)) {
553 return;
554 }
555
556 int32_t finalResult;
557 CHECK(msg->findInt32("finalResult", &finalResult));
558
559 QueueEntry entry;
560 entry.mOffset = 0;
561 entry.mFinalResult = finalResult;
562
563 if (audio) {
Roger Jönssonb50e83e2013-01-21 16:26:41 +0100564 if (mAudioQueue.empty() && mSyncQueues) {
565 syncQueuesDone();
566 }
Andreas Huberf9334412010-12-15 15:17:42 -0800567 mAudioQueue.push_back(entry);
568 postDrainAudioQueue();
569 } else {
Roger Jönssonb50e83e2013-01-21 16:26:41 +0100570 if (mVideoQueue.empty() && mSyncQueues) {
571 syncQueuesDone();
572 }
Andreas Huberf9334412010-12-15 15:17:42 -0800573 mVideoQueue.push_back(entry);
574 postDrainVideoQueue();
575 }
576}
577
578void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
579 int32_t audio;
580 CHECK(msg->findInt32("audio", &audio));
581
582 // If we're currently syncing the queues, i.e. dropping audio while
583 // aligning the first audio/video buffer times and only one of the
584 // two queues has data, we may starve that queue by not requesting
585 // more buffers from the decoder. If the other source then encounters
586 // a discontinuity that leads to flushing, we'll never find the
587 // corresponding discontinuity on the other queue.
588 // Therefore we'll stop syncing the queues if at least one of them
589 // is flushed.
590 syncQueuesDone();
591
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700592 ALOGV("flushing %s", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800593 if (audio) {
594 flushQueue(&mAudioQueue);
595
596 Mutex::Autolock autoLock(mFlushLock);
597 mFlushingAudio = false;
598
599 mDrainAudioQueuePending = false;
600 ++mAudioQueueGeneration;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700601
602 prepareForMediaRenderingStart();
Andreas Huberf9334412010-12-15 15:17:42 -0800603 } else {
604 flushQueue(&mVideoQueue);
605
606 Mutex::Autolock autoLock(mFlushLock);
607 mFlushingVideo = false;
608
609 mDrainVideoQueuePending = false;
610 ++mVideoQueueGeneration;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700611
612 prepareForMediaRenderingStart();
Andreas Huberf9334412010-12-15 15:17:42 -0800613 }
614
615 notifyFlushComplete(audio);
616}
617
618void NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
619 while (!queue->empty()) {
620 QueueEntry *entry = &*queue->begin();
621
622 if (entry->mBuffer != NULL) {
623 entry->mNotifyConsumed->post();
624 }
625
626 queue->erase(queue->begin());
627 entry = NULL;
628 }
629}
630
631void NuPlayer::Renderer::notifyFlushComplete(bool audio) {
632 sp<AMessage> notify = mNotify->dup();
633 notify->setInt32("what", kWhatFlushComplete);
634 notify->setInt32("audio", static_cast<int32_t>(audio));
635 notify->post();
636}
637
638bool NuPlayer::Renderer::dropBufferWhileFlushing(
639 bool audio, const sp<AMessage> &msg) {
640 bool flushing = false;
641
642 {
643 Mutex::Autolock autoLock(mFlushLock);
644 if (audio) {
645 flushing = mFlushingAudio;
646 } else {
647 flushing = mFlushingVideo;
648 }
649 }
650
651 if (!flushing) {
652 return false;
653 }
654
655 sp<AMessage> notifyConsumed;
656 if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
657 notifyConsumed->post();
658 }
659
660 return true;
661}
662
Andreas Huber3831a062010-12-21 10:22:33 -0800663void NuPlayer::Renderer::onAudioSinkChanged() {
664 CHECK(!mDrainAudioQueuePending);
665 mNumFramesWritten = 0;
Marco Nelissen4110c102012-03-29 09:31:28 -0700666 uint32_t written;
667 if (mAudioSink->getFramesWritten(&written) == OK) {
668 mNumFramesWritten = written;
669 }
Andreas Huber3831a062010-12-21 10:22:33 -0800670}
671
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800672void NuPlayer::Renderer::notifyPosition() {
673 if (mAnchorTimeRealUs < 0 || mAnchorTimeMediaUs < 0) {
674 return;
675 }
676
677 int64_t nowUs = ALooper::GetNowUs();
Andreas Huber714aa7b2011-09-13 08:28:38 -0700678
679 if (mLastPositionUpdateUs >= 0
680 && nowUs < mLastPositionUpdateUs + kMinPositionUpdateDelayUs) {
681 return;
682 }
683 mLastPositionUpdateUs = nowUs;
684
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800685 int64_t positionUs = (nowUs - mAnchorTimeRealUs) + mAnchorTimeMediaUs;
686
687 sp<AMessage> notify = mNotify->dup();
688 notify->setInt32("what", kWhatPosition);
689 notify->setInt64("positionUs", positionUs);
Andreas Huber3fe62152011-09-16 15:09:22 -0700690 notify->setInt64("videoLateByUs", mVideoLateByUs);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800691 notify->post();
692}
693
Andreas Huberb4082222011-01-20 15:23:04 -0800694void NuPlayer::Renderer::onPause() {
695 CHECK(!mPaused);
696
697 mDrainAudioQueuePending = false;
698 ++mAudioQueueGeneration;
699
700 mDrainVideoQueuePending = false;
701 ++mVideoQueueGeneration;
702
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700703 prepareForMediaRenderingStart();
704
Andreas Huberb4082222011-01-20 15:23:04 -0800705 if (mHasAudio) {
706 mAudioSink->pause();
707 }
708
Andreas Huberea9d51b2011-11-30 09:53:40 -0800709 ALOGV("now paused audio queue has %d entries, video has %d entries",
710 mAudioQueue.size(), mVideoQueue.size());
Andreas Huberb58ce9f2011-11-28 16:27:35 -0800711
Andreas Huberb4082222011-01-20 15:23:04 -0800712 mPaused = true;
713}
714
715void NuPlayer::Renderer::onResume() {
Andreas Huberb58ce9f2011-11-28 16:27:35 -0800716 if (!mPaused) {
717 return;
718 }
Andreas Huberb4082222011-01-20 15:23:04 -0800719
720 if (mHasAudio) {
721 mAudioSink->start();
722 }
723
724 mPaused = false;
725
726 if (!mAudioQueue.empty()) {
727 postDrainAudioQueue();
728 }
729
730 if (!mVideoQueue.empty()) {
731 postDrainVideoQueue();
732 }
733}
734
Andreas Huberf9334412010-12-15 15:17:42 -0800735} // namespace android
736