Merge changes from topic "largeAudioBuffer" into main

* changes:
  Enabling large audio for BLOCK_MODEL
  Support for multi access-unit output in codec framework
  Large audio frames in MediaCodec
diff --git a/media/aconfig/codec_fwk.aconfig b/media/aconfig/codec_fwk.aconfig
index 183bd99..06aceeb 100644
--- a/media/aconfig/codec_fwk.aconfig
+++ b/media/aconfig/codec_fwk.aconfig
@@ -5,6 +5,13 @@
 package: "android.media.codec"
 
 flag {
+  name: "aidl_hal_input_surface"
+  namespace: "codec_fwk"
+  description: "Feature flags for enabling AIDL HAL InputSurface handling"
+  bug: "201479783"
+}
+
+flag {
   name: "dynamic_color_aspects"
   namespace: "codec_fwk"
   description: "Feature flag for dynamic color aspect support"
diff --git a/media/codec2/Android.mk b/media/codec2/Android.mk
deleted file mode 100644
index 82d739f..0000000
--- a/media/codec2/Android.mk
+++ /dev/null
@@ -1,48 +0,0 @@
-# =============================================================================
-# DOCUMENTATION GENERATION
-# =============================================================================
-C2_ROOT := $(call my-dir)
-
-C2_DOCS_ROOT := $(OUT_DIR)/target/common/docs/codec2
-
-C2_OUT_TEMP := $(PRODUCT_OUT)/gen/ETC/Codec2-docs_intermediates
-
-C2_DOXY := $(or $(shell command -v doxygen),\
-		$(shell command -v /Applications/Doxygen.app/Contents/Resources/doxygen))
-
-.PHONY: check-doxygen
-check-doxygen:
-ifndef C2_DOXY
-	$(error 'doxygen is not available')
-endif
-
-$(C2_OUT_TEMP)/doxy-api.config: $(C2_ROOT)/docs/doxygen.config
-	# only document include directory, no internal sections
-	sed 's/\(^INPUT *=.*\)/\1include\//; \
-	s/\(^INTERNAL_DOCS *= *\).*/\1NO/; \
-	s/\(^ENABLED_SECTIONS *=.*\)INTERNAL\(.*\).*/\1\2/; \
-	s:\(^OUTPUT_DIRECTORY *= \)out:\1'$(OUT_DIR)':;' \
-		$(C2_ROOT)/docs/doxygen.config > $@
-
-$(C2_OUT_TEMP)/doxy-internal.config: $(C2_ROOT)/docs/doxygen.config
-	sed 's:\(^OUTPUT_DIRECTORY *= \)out\(.*\)api:\1'$(OUT_DIR)'\2internal:;' \
-		$(C2_ROOT)/docs/doxygen.config > $@
-
-.PHONY: docs-api
-docs-api: $(C2_OUT_TEMP)/doxy-api.config check-doxygen
-	echo API docs are building in $(C2_DOCS_ROOT)/api
-	rm -rf $(C2_DOCS_ROOT)/api
-	mkdir -p $(C2_DOCS_ROOT)/api
-	$(C2_DOXY) $(C2_OUT_TEMP)/doxy-api.config
-
-.PHONY: docs-internal
-docs-internal: $(C2_OUT_TEMP)/doxy-internal.config check-doxygen
-	echo Internal docs are building in $(C2_DOCS_ROOT)/internal
-	rm -rf $(C2_DOCS_ROOT)/internal
-	mkdir -p $(C2_DOCS_ROOT)/internal
-	$(C2_DOXY) $(C2_OUT_TEMP)/doxy-internal.config
-
-.PHONY: docs-all
-docs-all: docs-api docs-internal
-
-include $(call all-makefiles-under,$(call my-dir))
diff --git a/media/codec2/components/OWNERS b/media/codec2/components/OWNERS
new file mode 100644
index 0000000..453999a
--- /dev/null
+++ b/media/codec2/components/OWNERS
@@ -0,0 +1 @@
+kyslov@google.com
\ No newline at end of file
diff --git a/media/codec2/docs/doxygen.config b/media/codec2/docs/doxygen.config
index 5c3bea3..ab8b53b 100644
--- a/media/codec2/docs/doxygen.config
+++ b/media/codec2/docs/doxygen.config
@@ -162,7 +162,7 @@
 # will be relative from the directory where doxygen is started.
 # This tag requires that the tag FULL_PATH_NAMES is set to YES.
 
-STRIP_FROM_PATH        = frameworks/av/media/libstagefright/codec2
+STRIP_FROM_PATH        = frameworks/av/media/codec2
 
 # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
 # path mentioned in the documentation of a class, which tells the reader which
@@ -781,7 +781,7 @@
 # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = frameworks/av/media/libstagefright/codec2/
+INPUT                  = frameworks/av/media/codec2/
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -897,7 +897,7 @@
 # need to set EXTENSION_MAPPING for the extension otherwise the files are not
 # properly processed by doxygen.
 
-INPUT_FILTER           = frameworks/av/media/libstagefright/codec2/docs/doxyfilter.sh
+INPUT_FILTER           = frameworks/av/media/codec2/docs/doxyfilter.sh
 
 # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
 # basis. Doxygen will compare the file name with each pattern and apply the
diff --git a/media/codec2/doxygen.sh b/media/codec2/doxygen.sh
new file mode 100755
index 0000000..ca5aeed
--- /dev/null
+++ b/media/codec2/doxygen.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+# Copyright (C) 2024 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# =============================================================================
+# DOCUMENTATION GENERATION
+# =============================================================================
+
+if [ -z "$ANDROID_BUILD_TOP" ]; then
+  echo "error: Android build is not set up. Run this command after lunch." >&2
+  exit 2
+fi
+
+OUT_DIR=$ANDROID_BUILD_TOP/out
+
+# Codec 2.0 source and target paths
+C2_ROOT=$(dirname "$0")
+C2_DOCS_ROOT=$OUT_DIR/target/common/docs/codec2
+C2_OUT_TEMP=$ANDROID_PRODUCT_OUT/gen/ETC/Codec2-docs_intermediates
+
+# Doxygen path
+DOXY=$(which doxygen)
+DOXY_MAC="/Applications/Doxygen.app/Contents/Resources/doxygen"
+if [ -z "$DOXY" -a -x "$DOXY_MAC" ]; then
+  DOXY=$DOXY_MAC
+fi
+
+if [ -z "$DOXY" ]; then
+  echo "error: doxygen is not available" >&2
+  exit 2
+fi
+
+# Create doxygen config
+# ---------------------
+gen_doxy() {
+  local variant=$1
+  local variant_lc=$(echo $variant | tr A-Z a-z)
+  mkdir -p $C2_OUT_TEMP
+  if [ "$variant_lc" == "api" ]; then
+    # only document include directory, no internal sections
+    sed 's/\(^INPUT *=.*\)/\1core\/include\//;
+      s/\(^INTERNAL_DOCS *= *\).*/\1NO/;
+      s/\(^ENABLED_SECTIONS *=.*\)INTERNAL\(.*\).*/\1\2/;
+      s:\(^OUTPUT_DIRECTORY *= \)out\(.*\)api:\1'$OUT_DIR'\2'$variant_lc':;' \
+      $C2_ROOT/docs/doxygen.config > $C2_OUT_TEMP/doxy-$variant_lc.config
+
+    ls -la $C2_OUT_TEMP/doxy-$variant_lc.config
+  else
+    sed 's:\(^OUTPUT_DIRECTORY *= \)out\(.*\)api:\1'$OUT_DIR'\2'$variant_lc':;' \
+      $C2_ROOT/docs/doxygen.config > $C2_OUT_TEMP/doxy-$variant_lc.config
+  fi
+
+  echo $variant docs are building in $C2_DOCS_ROOT/$variant_lc
+  rm -rf $C2_DOCS_ROOT/$variant_lc
+  mkdir -p $C2_DOCS_ROOT/$variant_lc
+  pushd $ANDROID_BUILD_TOP
+  $DOXY $C2_OUT_TEMP/doxy-$variant_lc.config
+  popd
+}
+
+usage() {
+  echo "usage: $(basename "$0") [target]"
+  echo "  where target can be one of:"
+  echo "    all:      build both API and internal docs (default)"
+  echo "    api:      build API docs only"
+  echo "    internal: build internal docs which include implementation details"
+}
+
+TARGET=${1:-all}
+case "$TARGET" in
+  api) gen_doxy API;;
+  internal) gen_doxy Internal;;
+  all) gen_doxy API; gen_doxy Internal;;
+  -h) usage; exit 0;;
+  *) echo "unknown target '$TARGET'" >&2; usage; exit 2;;
+esac
diff --git a/media/codec2/hal/aidl/Component.cpp b/media/codec2/hal/aidl/Component.cpp
index 3ec3089..ba5f8d4 100644
--- a/media/codec2/hal/aidl/Component.cpp
+++ b/media/codec2/hal/aidl/Component.cpp
@@ -53,8 +53,10 @@
 struct Component::Listener : public C2Component::Listener {
 
     Listener(const std::shared_ptr<Component>& component) :
-        mComponent(component),
-        mListener(component->mListener) {
+            mComponent(component),
+            mListener(component->mListener) {
+        CHECK(component);
+        CHECK(component->mListener);
     }
 
     virtual void onError_nb(
@@ -518,6 +520,8 @@
             mInit = res;
         }
 
+        // b/321902635, mListener should not be null.
+        CHECK(mListener);
         mDeathRecipient = ::ndk::ScopedAIBinder_DeathRecipient(
                 AIBinder_DeathRecipient_new(OnBinderDied));
         mDeathContext = new DeathContext{ref<Component>()};
diff --git a/media/codec2/hal/aidl/ComponentStore.cpp b/media/codec2/hal/aidl/ComponentStore.cpp
index f0a1490..3f687b5 100644
--- a/media/codec2/hal/aidl/ComponentStore.cpp
+++ b/media/codec2/hal/aidl/ComponentStore.cpp
@@ -210,6 +210,8 @@
     c2_status_t status =
             mStore->createComponent(name, &c2component);
 
+    ALOGD("createComponent(): listener(%d)", bool(listener));
+
     if (status == C2_OK) {
 #ifndef __ANDROID_APEX__
         c2component = GetFilterWrapper()->maybeWrapComponent(c2component);
@@ -218,7 +220,8 @@
         std::shared_ptr<Component> comp =
             SharedRefBase::make<Component>(c2component, listener, ref<ComponentStore>(), pool);
         *component = comp;
-        if (!component) {
+        if (!component || !comp) {
+            ALOGE("createComponent(): component cannot be returned");
             status = C2_CORRUPTED;
         } else {
             reportComponentBirth(comp.get());
diff --git a/media/libmediaplayerservice/fuzzer/Android.bp b/media/libmediaplayerservice/fuzzer/Android.bp
index b511372..507da29 100644
--- a/media/libmediaplayerservice/fuzzer/Android.bp
+++ b/media/libmediaplayerservice/fuzzer/Android.bp
@@ -124,14 +124,19 @@
     ],
     defaults: [
         "libmediaplayerserviceFuzzer_defaults",
+        "libmediaplayerservice_defaults",
     ],
     static_libs: [
         "libplayerservice_datasource",
     ],
     shared_libs: [
+        "libmediaplayerservice",
         "libdatasource",
         "libdrmframework",
+        "libstagefright_httplive",
+        "libmediaextractorservice",
     ],
+    include_dirs: ["frameworks/av/services/mediaextractor"],
 }
 
 cc_fuzz {
diff --git a/media/libmediaplayerservice/fuzzer/metadataretriever_fuzzer.cpp b/media/libmediaplayerservice/fuzzer/metadataretriever_fuzzer.cpp
index a7cb689..857223d 100644
--- a/media/libmediaplayerservice/fuzzer/metadataretriever_fuzzer.cpp
+++ b/media/libmediaplayerservice/fuzzer/metadataretriever_fuzzer.cpp
@@ -15,6 +15,8 @@
  *
  */
 
+#include <MediaExtractorService.h>
+#include <MediaPlayerService.h>
 #include <StagefrightMetadataRetriever.h>
 #include <binder/ProcessState.h>
 #include <datasource/FileSource.h>
@@ -54,58 +56,96 @@
                             MEDIA_MIMETYPE_CONTAINER_MPEG2PS,  MEDIA_MIMETYPE_CONTAINER_HEIF,
                             MEDIA_MIMETYPE_TEXT_3GPP,          MEDIA_MIMETYPE_TEXT_SUBRIP,
                             MEDIA_MIMETYPE_TEXT_VTT,           MEDIA_MIMETYPE_TEXT_CEA_608,
-                            MEDIA_MIMETYPE_TEXT_CEA_708,       MEDIA_MIMETYPE_DATA_TIMED_ID3};
+                            MEDIA_MIMETYPE_TEXT_CEA_708,       MEDIA_MIMETYPE_DATA_TIMED_ID3,
+                            MEDIA_MIMETYPE_IMAGE_AVIF,         MEDIA_MIMETYPE_AUDIO_MPEGH_MHA1,
+                            MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1,   MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L3,
+                            MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L4,  MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L3,
+                            MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L4,  MEDIA_MIMETYPE_AUDIO_DTS,
+                            MEDIA_MIMETYPE_AUDIO_DTS_HD,       MEDIA_MIMETYPE_AUDIO_DTS_HD_MA,
+                            MEDIA_MIMETYPE_AUDIO_DTS_UHD,      MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1,
+                            MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2,   MEDIA_MIMETYPE_AUDIO_EVRC,
+                            MEDIA_MIMETYPE_AUDIO_EVRCB,        MEDIA_MIMETYPE_AUDIO_EVRCWB,
+                            MEDIA_MIMETYPE_AUDIO_EVRCNW,       MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS,
+                            MEDIA_MIMETYPE_AUDIO_APTX,         MEDIA_MIMETYPE_AUDIO_DRA,
+                            MEDIA_MIMETYPE_AUDIO_DOLBY_MAT,    MEDIA_MIMETYPE_AUDIO_DOLBY_TRUEHD,
+                            MEDIA_MIMETYPE_AUDIO_DOLBY_MAT_1_0,MEDIA_MIMETYPE_AUDIO_AAC_MP4,
+                            MEDIA_MIMETYPE_AUDIO_DOLBY_MAT_2_0,MEDIA_MIMETYPE_AUDIO_DOLBY_MAT_2_1,
+                            MEDIA_MIMETYPE_AUDIO_AAC_MAIN,     MEDIA_MIMETYPE_AUDIO_AAC_LC,
+                            MEDIA_MIMETYPE_AUDIO_AAC_SSR,      MEDIA_MIMETYPE_AUDIO_AAC_LTP,
+                            MEDIA_MIMETYPE_AUDIO_AAC_HE_V1,    MEDIA_MIMETYPE_AUDIO_AAC_SCALABLE,
+                            MEDIA_MIMETYPE_AUDIO_AAC_ERLC,     MEDIA_MIMETYPE_AUDIO_AAC_ADTS_MAIN,
+                            MEDIA_MIMETYPE_AUDIO_AAC_HE_V2,    MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V1,
+                            MEDIA_MIMETYPE_AUDIO_AAC_XHE,      MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V2,
+                            MEDIA_MIMETYPE_AUDIO_AAC_LD,       MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LC,
+                            MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SSR, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LTP,
+                            MEDIA_MIMETYPE_AUDIO_AAC_ADIF,     MEDIA_MIMETYPE_AUDIO_IEC60958,
+                            MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ERLC,MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LD,
+                            MEDIA_MIMETYPE_AUDIO_AAC_ELD,      MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V1,
+                            MEDIA_MIMETYPE_AUDIO_AAC_ADTS_XHE, MEDIA_MIMETYPE_AUDIO_AAC_LATM_LC,
+                            MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ELD, MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V2,
+                            MEDIA_MIMETYPE_AUDIO_IEC61937,
+                            MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SCALABLE,};
+
+constexpr size_t kMaxSize = 100;
 
 class MetadataRetrieverFuzzer {
    public:
     MetadataRetrieverFuzzer(const uint8_t *data, size_t size)
-        : mFdp(data, size),
-          mMdRetriever(new StagefrightMetadataRetriever()),
-          mDataSourceFd(memfd_create("InputFile", MFD_ALLOW_SEALING)) {}
-    ~MetadataRetrieverFuzzer() { close(mDataSourceFd); }
+        : mFdp(data, size), mMdRetriever(new StagefrightMetadataRetriever()) {}
     bool setDataSource(const uint8_t *data, size_t size);
     void getData();
 
    private:
     FuzzedDataProvider mFdp;
     sp<StagefrightMetadataRetriever> mMdRetriever = nullptr;
-    const int32_t mDataSourceFd;
+    int32_t mDataSourceFd;
 };
 
 void MetadataRetrieverFuzzer::getData() {
-    int64_t timeUs = mFdp.ConsumeIntegral<int64_t>();
-    int32_t option = mFdp.ConsumeIntegral<int32_t>();
-    int32_t colorFormat = mFdp.ConsumeIntegral<int32_t>();
-    bool metaOnly = mFdp.ConsumeBool();
-    mMdRetriever->getFrameAtTime(timeUs, option, colorFormat, metaOnly);
-
-    int32_t index = mFdp.ConsumeIntegral<int32_t>();
-    colorFormat = mFdp.ConsumeIntegral<int32_t>();
-    metaOnly = mFdp.ConsumeBool();
-    bool thumbnail = mFdp.ConsumeBool();
-    mMdRetriever->getImageAtIndex(index, colorFormat, metaOnly, thumbnail);
-
-    index = mFdp.ConsumeIntegral<int32_t>();
-    colorFormat = mFdp.ConsumeIntegral<int32_t>();
-    int32_t left = mFdp.ConsumeIntegral<int32_t>();
-    int32_t top = mFdp.ConsumeIntegral<int32_t>();
-    int32_t right = mFdp.ConsumeIntegral<int32_t>();
-    int32_t bottom = mFdp.ConsumeIntegral<int32_t>();
-    mMdRetriever->getImageRectAtIndex(index, colorFormat, left, top, right, bottom);
-
-    index = mFdp.ConsumeIntegral<int32_t>();
-    colorFormat = mFdp.ConsumeIntegral<int32_t>();
-    metaOnly = mFdp.ConsumeBool();
-    mMdRetriever->getFrameAtIndex(index, colorFormat, metaOnly);
-
-    mMdRetriever->extractAlbumArt();
-
-    int32_t keyCode = mFdp.ConsumeIntegral<int32_t>();
-    mMdRetriever->extractMetadata(keyCode);
+    while (mFdp.remaining_bytes()) {
+        auto invokeMediaApi = mFdp.PickValueInArray<const std::function<void()>>({
+                [&]() {
+                    mMdRetriever->getFrameAtTime(mFdp.ConsumeIntegral<int64_t>() /* timeUs */,
+                                                 mFdp.ConsumeIntegral<int32_t>() /* option */,
+                                                 mFdp.ConsumeIntegral<int32_t>() /* colorFormat */,
+                                                 mFdp.ConsumeBool() /* metaOnly */);
+                },
+                [&]() {
+                    mMdRetriever->getImageAtIndex(mFdp.ConsumeIntegral<int32_t>() /* index */,
+                                                  mFdp.ConsumeIntegral<int32_t>() /* colorFormat */,
+                                                  mFdp.ConsumeBool() /* metaOnly */,
+                                                  mFdp.ConsumeBool() /* thumbnail */);
+                },
+                [&]() {
+                    mMdRetriever->getImageRectAtIndex(
+                            mFdp.ConsumeIntegral<int32_t>() /* index */,
+                            mFdp.ConsumeIntegral<int32_t>() /* colorFormat */,
+                            mFdp.ConsumeIntegral<int32_t>() /* left */,
+                            mFdp.ConsumeIntegral<int32_t>() /* top */,
+                            mFdp.ConsumeIntegral<int32_t>() /* right */,
+                            mFdp.ConsumeIntegral<int32_t>() /* bottom */);
+                },
+                [&]() {
+                    mMdRetriever->getFrameAtIndex(mFdp.ConsumeIntegral<int32_t>() /* index */,
+                                                  mFdp.ConsumeIntegral<int32_t>() /* colorFormat */,
+                                                  mFdp.ConsumeBool() /* metaOnly */);
+                },
+                [&]() { mMdRetriever->extractAlbumArt(); },
+                [&]() {
+                    mMdRetriever->extractMetadata(mFdp.ConsumeIntegral<int32_t>() /* keyCode */);
+                },
+        });
+        invokeMediaApi();
+    }
 }
 
 bool MetadataRetrieverFuzzer::setDataSource(const uint8_t *data, size_t size) {
     status_t status = -1;
+    std::unique_ptr<std::FILE, decltype(&fclose)> fp(tmpfile(), &fclose);
+    mDataSourceFd = fileno(fp.get());
+    if (mDataSourceFd < 0) {
+        return false;
+    }
 
     enum DataSourceChoice {FromHttp, FromFd, FromFileSource, kMaxValue = FromFileSource};
     switch (mFdp.ConsumeEnum<DataSourceChoice>()) {
@@ -114,7 +154,7 @@
             mHeaders.add(String8(mFdp.ConsumeRandomLengthString().c_str()),
                          String8(mFdp.ConsumeRandomLengthString().c_str()));
 
-            uint32_t dataBlobSize = mFdp.ConsumeIntegralInRange<uint16_t>(0, size);
+            uint32_t dataBlobSize = mFdp.ConsumeIntegralInRange<uint16_t>(0, min(kMaxSize,size));
             vector<uint8_t> uriSuffix = mFdp.ConsumeBytes<uint8_t>(dataBlobSize);
 
             string uri("data:");
@@ -146,6 +186,12 @@
     return true;
 }
 
+extern "C" int LLVMFuzzerInitialize(int* /* argc */, char*** /* argv */) {
+    MediaPlayerService::instantiate();
+    MediaExtractorService::instantiate();
+    return 0;
+}
+
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
     MetadataRetrieverFuzzer mrtFuzzer(data, size);
     ProcessState::self()->startThreadPool();
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 2145dd9..f9ceef2 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -2188,7 +2188,7 @@
                 int32_t colorFormat = OMX_COLOR_FormatUnused;
                 OMX_U32 flexibleEquivalent = OMX_COLOR_FormatUnused;
                 if (!outputFormat->findInt32("color-format", &colorFormat)) {
-                    ALOGE("ouptut port did not have a color format (wrong domain?)");
+                    ALOGE("output port did not have a color format (wrong domain?)");
                     return BAD_VALUE;
                 }
                 ALOGD("[%s] Requested output format %#x and got %#x.",
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index a0a2891..bc1a97c 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -172,6 +172,7 @@
     const char *getTrackType() const;
     void resetInternal();
     int64_t trackMetaDataSize();
+    bool isTimestampValid(int64_t timeUs);
 
 private:
     // A helper class to handle faster write box with table entries
@@ -2430,6 +2431,42 @@
     return OK;
 }
 
+bool MPEG4Writer::isSampleMetadataValid(size_t trackIndex, int64_t timeUs) {
+    // Track Index starts from zero, so it should be at least 1 less than size.
+    if (trackIndex >= mTracks.size()) {
+        ALOGE("Incorrect trackIndex %zu, mTracks->size() %zu", trackIndex, mTracks.size());
+        return false;
+    }
+
+    List<Track *>::iterator it = mTracks.begin();
+
+    // (*it) is already pointing to trackIndex 0.
+    for (int i = 1; i <= trackIndex; i++) {
+        it++;
+    }
+
+    return (*it)->isTimestampValid(timeUs);
+}
+
+bool MPEG4Writer::Track::isTimestampValid(int64_t timeUs) {
+    // No timescale if HEIF
+    if (mIsHeif) {
+        return true;
+    }
+
+    // Ensure that the timeUs value does not have extremely low or high values
+    // that would cause an underflow or overflow, like in the calculation -
+    // mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6
+    if (abs(timeUs) >= (INT64_MAX - 5E5) / mTimeScale) {
+        return false;
+    }
+    // Limit check for calculations in ctts box
+    if (abs(timeUs) + kMaxCttsOffsetTimeUs >= INT64_MAX / mTimeScale) {
+        return false;
+    }
+    return true;
+}
+
 bool MPEG4Writer::Track::isExifData(
         MediaBufferBase *buffer, uint32_t *tiffHdrOffset) const {
     if (!mIsHeif) {
diff --git a/media/libstagefright/include/media/stagefright/MPEG4Writer.h b/media/libstagefright/include/media/stagefright/MPEG4Writer.h
index 054a4b8..1ff8acf 100644
--- a/media/libstagefright/include/media/stagefright/MPEG4Writer.h
+++ b/media/libstagefright/include/media/stagefright/MPEG4Writer.h
@@ -77,6 +77,9 @@
     virtual void setStartTimeOffsetMs(int ms) { mStartTimeOffsetMs = ms; }
     virtual int32_t getStartTimeOffsetMs() const { return mStartTimeOffsetMs; }
     virtual status_t setNextFd(int fd);
+    // Returns true if the timestamp is valid which is compatible with the Mpeg4.
+    // Note that this overloads that method in the base class.
+    bool isSampleMetadataValid(size_t trackIndex, int64_t timeUs) override;
 
 protected:
     virtual ~MPEG4Writer();