Merge commit '2381f06f374ee0cb8bca0edf5388394432b00e6d' into HEAD
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 750287f..3669a5b 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -32,6 +32,8 @@
 
 #include "ATSParser.h"
 
+#include "SoftwareRenderer.h"
+
 #include <cutils/properties.h> // for property_get
 #include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/foundation/ABuffer.h>
@@ -146,6 +148,7 @@
     : mUIDValid(false),
       mSourceFlags(0),
       mVideoIsAVC(false),
+      mNeedsSwRenderer(false),
       mAudioEOS(false),
       mVideoEOS(false),
       mScanSourcesPending(false),
@@ -444,6 +447,7 @@
             ALOGV("kWhatStart");
 
             mVideoIsAVC = false;
+            mNeedsSwRenderer = false;
             mAudioEOS = false;
             mVideoEOS = false;
             mSkipRenderingAudioUntilMediaTimeUs = -1;
@@ -680,6 +684,20 @@
 
                     notifyListener(
                             MEDIA_SET_VIDEO_SIZE, displayWidth, displayHeight);
+
+                    if (mNeedsSwRenderer && mNativeWindow != NULL) {
+                        int32_t colorFormat;
+                        CHECK(codecRequest->findInt32("color-format", &colorFormat));
+
+                        sp<MetaData> meta = new MetaData;
+                        meta->setInt32(kKeyWidth, width);
+                        meta->setInt32(kKeyHeight, height);
+                        meta->setRect(kKeyCropRect, cropLeft, cropTop, cropRight, cropBottom);
+                        meta->setInt32(kKeyColorFormat, colorFormat);
+
+                        mRenderer->setSoftRenderer(
+                                new SoftwareRenderer(mNativeWindow->getNativeWindow(), meta));
+                    }
                 }
             } else if (what == ACodec::kWhatShutdownCompleted) {
                 ALOGV("%s shutdown completed", audio ? "audio" : "video");
@@ -703,8 +721,13 @@
                 mRenderer->queueEOS(audio, UNKNOWN_ERROR);
             } else if (what == ACodec::kWhatDrainThisBuffer) {
                 renderBuffer(audio, codecRequest);
-            } else if (what != ACodec::kWhatComponentAllocated
-                    && what != ACodec::kWhatComponentConfigured
+            } else if (what == ACodec::kWhatComponentAllocated) {
+                if (!audio) {
+                    AString name;
+                    CHECK(codecRequest->findString("componentName", &name));
+                    mNeedsSwRenderer = name.startsWith("OMX.google.");
+                }
+            } else if (what != ACodec::kWhatComponentConfigured
                     && what != ACodec::kWhatBuffersAllocated) {
                 ALOGV("Unhandled codec notification %d '%c%c%c%c'.",
                       what,
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 13350f3..590e1f2 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -116,6 +116,7 @@
     sp<MediaPlayerBase::AudioSink> mAudioSink;
     sp<Decoder> mVideoDecoder;
     bool mVideoIsAVC;
+    bool mNeedsSwRenderer;
     sp<Decoder> mAudioDecoder;
     sp<Renderer> mRenderer;
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 3b2784b..92b9a92 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -20,6 +20,8 @@
 
 #include "NuPlayerRenderer.h"
 
+#include "SoftwareRenderer.h"
+
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -34,6 +36,7 @@
         const sp<AMessage> &notify,
         uint32_t flags)
     : mAudioSink(sink),
+      mSoftRenderer(NULL),
       mNotify(notify),
       mFlags(flags),
       mNumFramesWritten(0),
@@ -57,6 +60,12 @@
 }
 
 NuPlayer::Renderer::~Renderer() {
+    delete mSoftRenderer;
+}
+
+void NuPlayer::Renderer::setSoftRenderer(SoftwareRenderer *softRenderer) {
+    delete mSoftRenderer;
+    mSoftRenderer = softRenderer;
 }
 
 void NuPlayer::Renderer::queueBuffer(
@@ -414,6 +423,9 @@
              mVideoLateByUs, mVideoLateByUs / 1E6);
     } else {
         ALOGV("rendering video at media time %.2f secs", mediaTimeUs / 1E6);
+        if (mSoftRenderer != NULL) {
+            mSoftRenderer->render(entry->mBuffer->data(), entry->mBuffer->size(), NULL);
+        }
     }
 
     entry->mNotifyConsumed->setInt32("render", !tooLate);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index 94a05ea..9124e03 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -23,6 +23,7 @@
 namespace android {
 
 struct ABuffer;
+class SoftwareRenderer;
 
 struct NuPlayer::Renderer : public AHandler {
     enum Flags {
@@ -56,6 +57,8 @@
         kWhatMediaRenderingStart = 'mdrd',
     };
 
+    void setSoftRenderer(SoftwareRenderer *softRenderer);
+
 protected:
     virtual ~Renderer();
 
@@ -83,6 +86,7 @@
     static const int64_t kMinPositionUpdateDelayUs;
 
     sp<MediaPlayerBase::AudioSink> mAudioSink;
+    SoftwareRenderer *mSoftRenderer;
     sp<AMessage> mNotify;
     uint32_t mFlags;
     List<QueueEntry> mAudioQueue;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 8cf5026..9b36b6a 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -682,8 +682,9 @@
             }
             sinf->len = dataLen - 3;
             sinf->IPMPData = new char[sinf->len];
+            data_offset += 2;
 
-            if (mDataSource->readAt(data_offset + 2, sinf->IPMPData, sinf->len) < sinf->len) {
+            if (mDataSource->readAt(data_offset, sinf->IPMPData, sinf->len) < sinf->len) {
                 return ERROR_IO;
             }
             data_offset += sinf->len;
@@ -962,6 +963,12 @@
                     mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
 
                     int64_t paddingus = duration - (segment_duration + media_time);
+                    if (paddingus < 0) {
+                        // track duration from media header (which is what kKeyDuration is) might
+                        // be slightly shorter than the segment duration, which would make the
+                        // padding negative. Clamp to zero.
+                        paddingus = 0;
+                    }
                     int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000;
                     mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples);
                 }