Skip to content

Commit c7342fb

Browse files
theandi666Android (Google) Code Review
authored andcommitted
Merge "In order to recover from video lagging behind audio, drop avc frames"
2 parents 5c1c26a + 950fc9d commit c7342fb

File tree

8 files changed

+155
-44
lines changed

8 files changed

+155
-44
lines changed

media/libmediaplayerservice/nuplayer/NuPlayer.cpp

Lines changed: 80 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -34,25 +34,34 @@
3434
#include <media/stagefright/foundation/ADebug.h>
3535
#include <media/stagefright/foundation/AMessage.h>
3636
#include <media/stagefright/ACodec.h>
37+
#include <media/stagefright/MediaDefs.h>
3738
#include <media/stagefright/MediaErrors.h>
3839
#include <media/stagefright/MetaData.h>
3940
#include <surfaceflinger/Surface.h>
4041
#include <gui/ISurfaceTexture.h>
4142

43+
#include "avc_utils.h"
44+
4245
namespace android {
4346

4447
////////////////////////////////////////////////////////////////////////////////
4548

4649
NuPlayer::NuPlayer()
4750
: mUIDValid(false),
51+
mVideoIsAVC(false),
4852
mAudioEOS(false),
4953
mVideoEOS(false),
5054
mScanSourcesPending(false),
5155
mScanSourcesGeneration(0),
5256
mFlushingAudio(NONE),
5357
mFlushingVideo(NONE),
5458
mResetInProgress(false),
55-
mResetPostponed(false) {
59+
mResetPostponed(false),
60+
mSkipRenderingAudioUntilMediaTimeUs(-1ll),
61+
mSkipRenderingVideoUntilMediaTimeUs(-1ll),
62+
mVideoLateByUs(0ll),
63+
mNumFramesTotal(0ll),
64+
mNumFramesDropped(0ll) {
5665
}
5766

5867
NuPlayer::~NuPlayer() {
@@ -185,10 +194,14 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
185194
{
186195
LOGV("kWhatStart");
187196

197+
mVideoIsAVC = false;
188198
mAudioEOS = false;
189199
mVideoEOS = false;
190200
mSkipRenderingAudioUntilMediaTimeUs = -1;
191201
mSkipRenderingVideoUntilMediaTimeUs = -1;
202+
mVideoLateByUs = 0;
203+
mNumFramesTotal = 0;
204+
mNumFramesDropped = 0;
192205

193206
mSource->start();
194207

@@ -269,6 +282,8 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
269282
} else {
270283
CHECK(IsFlushingState(mFlushingVideo, &needShutdown));
271284
mFlushingVideo = FLUSHED;
285+
286+
mVideoLateByUs = 0;
272287
}
273288

274289
LOGV("decoder %s flush completed", audio ? "audio" : "video");
@@ -397,13 +412,18 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
397412
int64_t positionUs;
398413
CHECK(msg->findInt64("positionUs", &positionUs));
399414

415+
CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs));
416+
400417
if (mDriver != NULL) {
401418
sp<NuPlayerDriver> driver = mDriver.promote();
402419
if (driver != NULL) {
403420
driver->notifyPosition(positionUs);
421+
422+
driver->notifyFrameStats(
423+
mNumFramesTotal, mNumFramesDropped);
404424
}
405425
}
406-
} else {
426+
} else if (what == Renderer::kWhatFlushComplete) {
407427
CHECK_EQ(what, (int32_t)Renderer::kWhatFlushComplete);
408428

409429
int32_t audio;
@@ -565,6 +585,12 @@ status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
565585
return -EWOULDBLOCK;
566586
}
567587

588+
if (!audio) {
589+
const char *mime;
590+
CHECK(meta->findCString(kKeyMIMEType, &mime));
591+
mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime);
592+
}
593+
568594
sp<AMessage> notify =
569595
new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify,
570596
id());
@@ -598,53 +624,70 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
598624
}
599625

600626
sp<ABuffer> accessUnit;
601-
status_t err = mSource->dequeueAccessUnit(audio, &accessUnit);
602627

603-
if (err == -EWOULDBLOCK) {
604-
return err;
605-
} else if (err != OK) {
606-
if (err == INFO_DISCONTINUITY) {
607-
int32_t type;
608-
CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
628+
bool dropAccessUnit;
629+
do {
630+
status_t err = mSource->dequeueAccessUnit(audio, &accessUnit);
609631

610-
bool formatChange =
611-
type == ATSParser::DISCONTINUITY_FORMATCHANGE;
632+
if (err == -EWOULDBLOCK) {
633+
return err;
634+
} else if (err != OK) {
635+
if (err == INFO_DISCONTINUITY) {
636+
int32_t type;
637+
CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
612638

613-
LOGV("%s discontinuity (formatChange=%d)",
614-
audio ? "audio" : "video", formatChange);
639+
bool formatChange =
640+
type == ATSParser::DISCONTINUITY_FORMATCHANGE;
615641

616-
if (audio) {
617-
mSkipRenderingAudioUntilMediaTimeUs = -1;
618-
} else {
619-
mSkipRenderingVideoUntilMediaTimeUs = -1;
620-
}
642+
LOGV("%s discontinuity (formatChange=%d)",
643+
audio ? "audio" : "video", formatChange);
621644

622-
sp<AMessage> extra;
623-
if (accessUnit->meta()->findMessage("extra", &extra)
624-
&& extra != NULL) {
625-
int64_t resumeAtMediaTimeUs;
626-
if (extra->findInt64(
627-
"resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
628-
LOGI("suppressing rendering of %s until %lld us",
629-
audio ? "audio" : "video", resumeAtMediaTimeUs);
645+
if (audio) {
646+
mSkipRenderingAudioUntilMediaTimeUs = -1;
647+
} else {
648+
mSkipRenderingVideoUntilMediaTimeUs = -1;
649+
}
630650

631-
if (audio) {
632-
mSkipRenderingAudioUntilMediaTimeUs =
633-
resumeAtMediaTimeUs;
634-
} else {
635-
mSkipRenderingVideoUntilMediaTimeUs =
636-
resumeAtMediaTimeUs;
651+
sp<AMessage> extra;
652+
if (accessUnit->meta()->findMessage("extra", &extra)
653+
&& extra != NULL) {
654+
int64_t resumeAtMediaTimeUs;
655+
if (extra->findInt64(
656+
"resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
657+
LOGI("suppressing rendering of %s until %lld us",
658+
audio ? "audio" : "video", resumeAtMediaTimeUs);
659+
660+
if (audio) {
661+
mSkipRenderingAudioUntilMediaTimeUs =
662+
resumeAtMediaTimeUs;
663+
} else {
664+
mSkipRenderingVideoUntilMediaTimeUs =
665+
resumeAtMediaTimeUs;
666+
}
637667
}
638668
}
669+
670+
flushDecoder(audio, formatChange);
639671
}
640672

641-
flushDecoder(audio, formatChange);
673+
reply->setInt32("err", err);
674+
reply->post();
675+
return OK;
642676
}
643677

644-
reply->setInt32("err", err);
645-
reply->post();
646-
return OK;
647-
}
678+
if (!audio) {
679+
++mNumFramesTotal;
680+
}
681+
682+
dropAccessUnit = false;
683+
if (!audio
684+
&& mVideoLateByUs > 100000ll
685+
&& mVideoIsAVC
686+
&& !IsAVCReferenceFrame(accessUnit)) {
687+
dropAccessUnit = true;
688+
++mNumFramesDropped;
689+
}
690+
} while (dropAccessUnit);
648691

649692
// LOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
650693

media/libmediaplayerservice/nuplayer/NuPlayer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ struct NuPlayer : public AHandler {
9292
sp<NativeWindowWrapper> mNativeWindow;
9393
sp<MediaPlayerBase::AudioSink> mAudioSink;
9494
sp<Decoder> mVideoDecoder;
95+
bool mVideoIsAVC;
9596
sp<Decoder> mAudioDecoder;
9697
sp<Renderer> mRenderer;
9798

@@ -119,6 +120,9 @@ struct NuPlayer : public AHandler {
119120
int64_t mSkipRenderingAudioUntilMediaTimeUs;
120121
int64_t mSkipRenderingVideoUntilMediaTimeUs;
121122

123+
int64_t mVideoLateByUs;
124+
int64_t mNumFramesTotal, mNumFramesDropped;
125+
122126
status_t instantiateDecoder(bool audio, sp<Decoder> *decoder);
123127

124128
status_t feedDecoderInputData(bool audio, const sp<AMessage> &msg);

media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ NuPlayerDriver::NuPlayerDriver()
3131
: mResetInProgress(false),
3232
mDurationUs(-1),
3333
mPositionUs(-1),
34+
mNumFramesTotal(0),
35+
mNumFramesDropped(0),
3436
mLooper(new ALooper),
3537
mState(UNINITIALIZED),
3638
mStartupSeekTimeUs(-1) {
@@ -292,4 +294,30 @@ void NuPlayerDriver::notifySeekComplete() {
292294
sendEvent(MEDIA_SEEK_COMPLETE);
293295
}
294296

297+
void NuPlayerDriver::notifyFrameStats(
298+
int64_t numFramesTotal, int64_t numFramesDropped) {
299+
Mutex::Autolock autoLock(mLock);
300+
mNumFramesTotal = numFramesTotal;
301+
mNumFramesDropped = numFramesDropped;
302+
}
303+
304+
status_t NuPlayerDriver::dump(int fd, const Vector<String16> &args) const {
305+
Mutex::Autolock autoLock(mLock);
306+
307+
FILE *out = fdopen(dup(fd), "w");
308+
309+
fprintf(out, " NuPlayer\n");
310+
fprintf(out, " numFramesTotal(%lld), numFramesDropped(%lld), "
311+
"percentageDropped(%.2f)\n",
312+
mNumFramesTotal,
313+
mNumFramesDropped,
314+
mNumFramesTotal == 0
315+
? 0.0 : (double)mNumFramesDropped / mNumFramesTotal);
316+
317+
fclose(out);
318+
out = NULL;
319+
320+
return OK;
321+
}
322+
295323
} // namespace android

media/libmediaplayerservice/nuplayer/NuPlayerDriver.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,23 +60,28 @@ struct NuPlayerDriver : public MediaPlayerInterface {
6060
virtual status_t getMetadata(
6161
const media::Metadata::Filter& ids, Parcel *records);
6262

63+
virtual status_t dump(int fd, const Vector<String16> &args) const;
64+
6365
void notifyResetComplete();
6466
void notifyDuration(int64_t durationUs);
6567
void notifyPosition(int64_t positionUs);
6668
void notifySeekComplete();
69+
void notifyFrameStats(int64_t numFramesTotal, int64_t numFramesDropped);
6770

6871
protected:
6972
virtual ~NuPlayerDriver();
7073

7174
private:
72-
Mutex mLock;
75+
mutable Mutex mLock;
7376
Condition mCondition;
7477

7578
// The following are protected through "mLock"
7679
// >>>
7780
bool mResetInProgress;
7881
int64_t mDurationUs;
7982
int64_t mPositionUs;
83+
int64_t mNumFramesTotal;
84+
int64_t mNumFramesDropped;
8085
// <<<
8186

8287
sp<ALooper> mLooper;

media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ NuPlayer::Renderer::Renderer(
4747
mHasVideo(false),
4848
mSyncQueues(false),
4949
mPaused(false),
50-
mLastPositionUpdateUs(-1ll) {
50+
mLastPositionUpdateUs(-1ll),
51+
mVideoLateByUs(0ll) {
5152
}
5253

5354
NuPlayer::Renderer::~Renderer() {
@@ -357,22 +358,26 @@ void NuPlayer::Renderer::onDrainVideoQueue() {
357358

358359
mVideoQueue.erase(mVideoQueue.begin());
359360
entry = NULL;
361+
362+
mVideoLateByUs = 0ll;
363+
364+
notifyPosition();
360365
return;
361366
}
362367

363-
#if 0
364368
int64_t mediaTimeUs;
365369
CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
366370

367371
int64_t realTimeUs = mediaTimeUs - mAnchorTimeMediaUs + mAnchorTimeRealUs;
368-
int64_t lateByUs = ALooper::GetNowUs() - realTimeUs;
372+
mVideoLateByUs = ALooper::GetNowUs() - realTimeUs;
369373

370-
if (lateByUs > 40000) {
371-
LOGI("video late by %lld us (%.2f secs)", lateByUs, lateByUs / 1E6);
374+
bool tooLate = (mVideoLateByUs > 40000);
375+
376+
if (tooLate) {
377+
LOGV("video late by %lld us (%.2f secs)", lateByUs, lateByUs / 1E6);
372378
} else {
373379
LOGV("rendering video at media time %.2f secs", mediaTimeUs / 1E6);
374380
}
375-
#endif
376381

377382
entry->mNotifyConsumed->setInt32("render", true);
378383
entry->mNotifyConsumed->post();
@@ -604,6 +609,7 @@ void NuPlayer::Renderer::notifyPosition() {
604609
sp<AMessage> notify = mNotify->dup();
605610
notify->setInt32("what", kWhatPosition);
606611
notify->setInt64("positionUs", positionUs);
612+
notify->setInt64("videoLateByUs", mVideoLateByUs);
607613
notify->post();
608614
}
609615

media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ struct NuPlayer::Renderer : public AHandler {
101101
bool mPaused;
102102

103103
int64_t mLastPositionUpdateUs;
104+
int64_t mVideoLateByUs;
104105

105106
bool onDrainAudioQueue();
106107
void postDrainAudioQueue(int64_t delayUs = 0);
@@ -118,6 +119,7 @@ struct NuPlayer::Renderer : public AHandler {
118119
void notifyEOS(bool audio, status_t finalResult);
119120
void notifyFlushComplete(bool audio);
120121
void notifyPosition();
122+
void notifyVideoLateBy(int64_t lateByUs);
121123

122124
void flushQueue(List<QueueEntry> *queue);
123125
bool dropBufferWhileFlushing(bool audio, const sp<AMessage> &msg);

media/libstagefright/avc_utils.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,28 @@ bool IsIDR(const sp<ABuffer> &buffer) {
329329
return foundIDR;
330330
}
331331

332+
bool IsAVCReferenceFrame(const sp<ABuffer> &accessUnit) {
333+
const uint8_t *data = accessUnit->data();
334+
size_t size = accessUnit->size();
335+
336+
const uint8_t *nalStart;
337+
size_t nalSize;
338+
while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
339+
CHECK_GT(nalSize, 0u);
340+
341+
unsigned nalType = nalStart[0] & 0x1f;
342+
343+
if (nalType == 5) {
344+
return true;
345+
} else if (nalType == 1) {
346+
unsigned nal_ref_idc = (nalStart[0] >> 5) & 3;
347+
return nal_ref_idc != 0;
348+
}
349+
}
350+
351+
return true;
352+
}
353+
332354
sp<MetaData> MakeAACCodecSpecificData(
333355
unsigned profile, unsigned sampling_freq_index,
334356
unsigned channel_configuration) {

media/libstagefright/include/avc_utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ struct MetaData;
5050
sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit);
5151

5252
bool IsIDR(const sp<ABuffer> &accessUnit);
53+
bool IsAVCReferenceFrame(const sp<ABuffer> &accessUnit);
5354

5455
const char *AVCProfileToString(uint8_t profile);
5556

0 commit comments

Comments
 (0)