resolved conflicts for merge of e1009a0f to master
diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp
index fd02bcc..d987250 100644
--- a/cmds/stagefright/codec.cpp
+++ b/cmds/stagefright/codec.cpp
@@ -45,9 +45,10 @@
fprintf(stderr, "usage: %s [-a] use audio\n"
"\t\t[-v] use video\n"
"\t\t[-p] playback\n"
- "\t\t[-S] allocate buffers from a surface\n",
+ "\t\t[-S] allocate buffers from a surface\n"
+ "\t\t[-R] render output to surface (enables -S)\n"
+ "\t\t[-T] use render timestamps (enables -R)\n",
me);
-
exit(1);
}
@@ -71,7 +72,9 @@
const char *path,
bool useAudio,
bool useVideo,
- const android::sp<android::Surface> &surface) {
+ const android::sp<android::Surface> &surface,
+ bool renderSurface,
+ bool useTimestamp) {
using namespace android;
static int64_t kTimeout = 500ll;
@@ -136,6 +139,7 @@
CHECK(!stateByTrack.isEmpty());
int64_t startTimeUs = ALooper::GetNowUs();
+ int64_t startTimeRender = -1;
for (size_t i = 0; i < stateByTrack.size(); ++i) {
CodecState *state = &stateByTrack.editValueAt(i);
@@ -260,7 +264,23 @@
++state->mNumBuffersDecoded;
state->mNumBytesDecoded += size;
- err = state->mCodec->releaseOutputBuffer(index);
+ if (surface == NULL || !renderSurface) {
+ err = state->mCodec->releaseOutputBuffer(index);
+ } else if (useTimestamp) {
+ if (startTimeRender == -1) {
+ // begin rendering 2 vsyncs (~33ms) after first decode
+ startTimeRender =
+ systemTime(SYSTEM_TIME_MONOTONIC) + 33000000
+ - (presentationTimeUs * 1000);
+ }
+ presentationTimeUs =
+ (presentationTimeUs * 1000) + startTimeRender;
+ err = state->mCodec->renderOutputBufferAndRelease(
+ index, presentationTimeUs);
+ } else {
+ err = state->mCodec->renderOutputBufferAndRelease(index);
+ }
+
CHECK_EQ(err, (status_t)OK);
if (flags & MediaCodec::BUFFER_FLAG_EOS) {
@@ -320,34 +340,42 @@
bool useVideo = false;
bool playback = false;
bool useSurface = false;
+ bool renderSurface = false;
+ bool useTimestamp = false;
int res;
- while ((res = getopt(argc, argv, "havpSD")) >= 0) {
+ while ((res = getopt(argc, argv, "havpSDRT")) >= 0) {
switch (res) {
case 'a':
{
useAudio = true;
break;
}
-
case 'v':
{
useVideo = true;
break;
}
-
case 'p':
{
playback = true;
break;
}
-
+ case 'T':
+ {
+ useTimestamp = true;
+ }
+ // fall through
+ case 'R':
+ {
+ renderSurface = true;
+ }
+ // fall through
case 'S':
{
useSurface = true;
break;
}
-
case '?':
case 'h':
default:
@@ -422,7 +450,8 @@
player->stop();
player->reset();
} else {
- decode(looper, argv[0], useAudio, useVideo, surface);
+ decode(looper, argv[0], useAudio, useVideo, surface, renderSurface,
+ useTimestamp);
}
if (playback || (useSurface && useVideo)) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 4748546..6cfbcdc 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -236,6 +236,9 @@
case STATE_PAUSED:
{
+ if (mAtEOS) {
+ mPlayer->seekToAsync(0);
+ }
mPlayer->resume();
break;
}
@@ -287,6 +290,14 @@
switch (mState) {
case STATE_PREPARED:
{
+ int curpos = 0;
+ if (mPositionUs > 0) {
+ curpos = (mPositionUs + 500ll) / 1000;
+ }
+ if (curpos == msec) {
+ // nothing to do, and doing something anyway could result in deadlock (b/15323063)
+ break;
+ }
mStartupSeekTimeUs = seekTimeUs;
// pretend that the seek completed. It will actually happen when starting playback.
// TODO: actually perform the seek here, so the player is ready to go at the new
@@ -535,6 +546,8 @@
if (mLooping) {
mPlayer->seekToAsync(0);
break;
+ } else {
+ mState = STATE_PAUSED;
}
// fall through
}
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 19da6ee..b84886e 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -2809,7 +2809,6 @@
{
if (objectType == AOT_SBR || objectType == AOT_PS) {
- const int32_t extensionSamplingFrequency = br.getBits(4);
objectType = br.getBits(5);
if (objectType == AOT_ESCAPE) {
@@ -2827,9 +2826,30 @@
const int32_t coreCoderDelay = br.getBits(14);
}
- const int32_t extensionFlag = br.getBits(1);
+ int32_t extensionFlag = -1;
+ if (br.numBitsLeft() > 0) {
+ extensionFlag = br.getBits(1);
+ } else {
+ switch (objectType) {
+ // 14496-3 4.5.1.1 extensionFlag
+ case AOT_AAC_LC:
+ extensionFlag = 0;
+ break;
+ case AOT_ER_AAC_LC:
+ case AOT_ER_AAC_SCAL:
+ case AOT_ER_BSAC:
+ case AOT_ER_AAC_LD:
+ extensionFlag = 1;
+ break;
+ default:
+ TRESPASS();
+ break;
+ }
+ ALOGW("csd missing extension flag; assuming %d for object type %u.",
+ extensionFlag, objectType);
+ }
- if (numChannels == 0 ) {
+ if (numChannels == 0) {
int32_t channelsEffectiveNum = 0;
int32_t channelsNum = 0;
const int32_t ElementInstanceTag = br.getBits(4);