Merge change 24450 into eclair

* changes:
  Minor API change in MPEG4Writer, support for amr output into MPEG4 containers.
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 894d46c..433fb18 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -124,6 +124,9 @@
         case FOURCC('s', 'a', 'm', 'r'):
             return "audio/3gpp";
 
+        case FOURCC('s', 'a', 'w', 'b'):
+            return "audio/amr-wb";
+
         case FOURCC('m', 'p', '4', 'v'):
             return "video/mp4v-es";
 
@@ -189,6 +192,10 @@
         --index;
     }
 
+    if (track == NULL) {
+        return NULL;
+    }
+
     return track->meta;
 }
 
@@ -472,6 +479,7 @@
 
         case FOURCC('m', 'p', '4', 'a'):
         case FOURCC('s', 'a', 'm', 'r'):
+        case FOURCC('s', 'a', 'w', 'b'):
         {
             if (mHandlerType != FOURCC('s', 'o', 'u', 'n')) {
                 return ERROR_MALFORMED;
@@ -491,7 +499,8 @@
             uint16_t data_ref_index = U16_AT(&buffer[6]);
             uint16_t num_channels = U16_AT(&buffer[16]);
 
-            if (!strcasecmp("audio/3gpp", FourCC2MIME(chunk_type))) {
+            if (!strcasecmp("audio/3gpp", FourCC2MIME(chunk_type))
+                || !strcasecmp("audio/amr-wb", FourCC2MIME(chunk_type))) {
                 // AMR audio is always mono.
                 num_channels = 1;
             }
@@ -705,6 +714,10 @@
         --index;
     }
 
+    if (track == NULL) {
+        return NULL;
+    }
+
     return new MPEG4Source(
             track->meta, mDataSource, track->sampleTable);
 }
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 2e02697..3ab44b0 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -2067,6 +2067,55 @@
     }
 }
 
+static const char *amrBandModeString(OMX_AUDIO_AMRBANDMODETYPE type) {
+    static const char *kNames[] = {
+        "OMX_AUDIO_AMRBandModeUnused",
+        "OMX_AUDIO_AMRBandModeNB0",
+        "OMX_AUDIO_AMRBandModeNB1",
+        "OMX_AUDIO_AMRBandModeNB2",
+        "OMX_AUDIO_AMRBandModeNB3",
+        "OMX_AUDIO_AMRBandModeNB4",
+        "OMX_AUDIO_AMRBandModeNB5",
+        "OMX_AUDIO_AMRBandModeNB6",
+        "OMX_AUDIO_AMRBandModeNB7",
+        "OMX_AUDIO_AMRBandModeWB0",
+        "OMX_AUDIO_AMRBandModeWB1",
+        "OMX_AUDIO_AMRBandModeWB2",
+        "OMX_AUDIO_AMRBandModeWB3",
+        "OMX_AUDIO_AMRBandModeWB4",
+        "OMX_AUDIO_AMRBandModeWB5",
+        "OMX_AUDIO_AMRBandModeWB6",
+        "OMX_AUDIO_AMRBandModeWB7",
+        "OMX_AUDIO_AMRBandModeWB8",
+    };
+
+    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
+
+    if (type < 0 || (size_t)type >= numNames) {
+        return "UNKNOWN";
+    } else {
+        return kNames[type];
+    }
+}
+
+static const char *amrFrameFormatString(OMX_AUDIO_AMRFRAMEFORMATTYPE type) {
+    static const char *kNames[] = {
+        "OMX_AUDIO_AMRFrameFormatConformance",
+        "OMX_AUDIO_AMRFrameFormatIF1",
+        "OMX_AUDIO_AMRFrameFormatIF2",
+        "OMX_AUDIO_AMRFrameFormatFSF",
+        "OMX_AUDIO_AMRFrameFormatRTPPayload",
+        "OMX_AUDIO_AMRFrameFormatITU",
+    };
+
+    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
+
+    if (type < 0 || (size_t)type >= numNames) {
+        return "UNKNOWN";
+    } else {
+        return kNames[type];
+    }
+}
 
 void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
     OMX_PARAM_PORTDEFINITIONTYPE def;
@@ -2153,6 +2202,20 @@
                         ? "signed" : "unsigned");
 
                 printf("  ePCMMode = %s\n", audioPCMModeString(params.ePCMMode));
+            } else if (audioDef->eEncoding == OMX_AUDIO_CodingAMR) {
+                OMX_AUDIO_PARAM_AMRTYPE amr;
+                InitOMXParams(&amr);
+                amr.nPortIndex = portIndex;
+
+                err = mOMX->get_parameter(
+                        mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
+                CHECK_EQ(err, OK);
+
+                printf("  nChannels = %ld\n", amr.nChannels);
+                printf("  eAMRBandMode = %s\n",
+                        amrBandModeString(amr.eAMRBandMode));
+                printf("  eAMRFrameFormat = %s\n",
+                        amrFrameFormatString(amr.eAMRFrameFormat));
             }
 
             break;
@@ -2229,7 +2292,28 @@
                 // The codec-reported sampleRate is not reliable...
                 mOutputFormat->setInt32(kKeySampleRate, sampleRate);
             } else if (audio_def->eEncoding == OMX_AUDIO_CodingAMR) {
-                mOutputFormat->setCString(kKeyMIMEType, "audio/3gpp");
+                OMX_AUDIO_PARAM_AMRTYPE amr;
+                InitOMXParams(&amr);
+                amr.nPortIndex = kPortIndexOutput;
+
+                err = mOMX->get_parameter(
+                        mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
+                CHECK_EQ(err, OK);
+
+                CHECK_EQ(amr.nChannels, 1);
+                mOutputFormat->setInt32(kKeyChannelCount, 1);
+
+                if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeNB0
+                    && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeNB7) {
+                    mOutputFormat->setCString(kKeyMIMEType, "audio/3gpp");
+                    mOutputFormat->setInt32(kKeySampleRate, 8000);
+                } else if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0
+                            && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeWB8) {
+                    mOutputFormat->setCString(kKeyMIMEType, "audio/amr-wb");
+                    mOutputFormat->setInt32(kKeySampleRate, 16000);
+                } else {
+                    CHECK(!"Unknown AMR band mode.");
+                }
             } else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) {
                 mOutputFormat->setCString(kKeyMIMEType, "audio/mp4a-latm");
             } else {