Merge "add trunksize as restriction for function parseClearEncryptedSizes()" into rvc-dev
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.cpp b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
index 19ccbf9..c2d2540 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
@@ -628,6 +628,7 @@
         mComplexity = mIntf->getComplexity_l();
         mQuality = mIntf->getQuality_l();
         mGop = mIntf->getGop_l();
+        mRequestSync = mIntf->getRequestSync_l();
     }
 
     c2_status_t status = initEncParams();
@@ -956,7 +957,7 @@
         }
     }
 
-    // handle dynamic config parameters
+    // handle dynamic bitrate change
     {
         IntfImpl::Lock lock = mIntf->lock();
         std::shared_ptr<C2StreamBitrateInfo::output> bitrate = mIntf->getBitrate_l();
@@ -983,6 +984,26 @@
         work->workletsProcessed = 1u;
         return;
     }
+    // handle request key frame
+    {
+        IntfImpl::Lock lock = mIntf->lock();
+        std::shared_ptr<C2StreamRequestSyncFrameTuning::output> requestSync;
+        requestSync = mIntf->getRequestSync_l();
+        lock.unlock();
+        if (requestSync != mRequestSync) {
+            // we can handle IDR immediately
+            if (requestSync->value) {
+                // unset request
+                C2StreamRequestSyncFrameTuning::output clearSync(0u, C2_FALSE);
+                std::vector<std::unique_ptr<C2SettingResult>> failures;
+                mIntf->config({ &clearSync }, C2_MAY_BLOCK, &failures);
+                ALOGV("Got sync request");
+                //Force this as an IDR frame
+                s_encode_ip.i4_force_idr_flag = 1;
+            }
+            mRequestSync = requestSync;
+        }
+    }
 
     uint64_t timeDelay = 0;
     uint64_t timeTaken = 0;
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.h b/media/codec2/components/hevc/C2SoftHevcEnc.h
index 140b4a9..5ea4602 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.h
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.h
@@ -88,6 +88,7 @@
     std::shared_ptr<C2StreamComplexityTuning::output> mComplexity;
     std::shared_ptr<C2StreamQualityTuning::output> mQuality;
     std::shared_ptr<C2StreamGopTuning::output> mGop;
+    std::shared_ptr<C2StreamRequestSyncFrameTuning::output> mRequestSync;
 #ifdef FILE_DUMP_ENABLE
     char mInFile[200];
     char mOutFile[200];
diff --git a/media/codec2/components/vpx/C2SoftVpxDec.cpp b/media/codec2/components/vpx/C2SoftVpxDec.cpp
index c7d73f4..3eef1e3 100644
--- a/media/codec2/components/vpx/C2SoftVpxDec.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxDec.cpp
@@ -784,7 +784,13 @@
         }
 
     }
-    CHECK(img->fmt == VPX_IMG_FMT_I420 || img->fmt == VPX_IMG_FMT_I42016);
+    if(img->fmt != VPX_IMG_FMT_I420 && img->fmt != VPX_IMG_FMT_I42016) {
+        ALOGE("img->fmt %d not supported", img->fmt);
+        mSignalledError = true;
+        work->workletsProcessed = 1u;
+        work->result = C2_CORRUPTED;
+        return false;
+    }
 
     std::shared_ptr<C2GraphicBlock> block;
     uint32_t format = HAL_PIXEL_FORMAT_YV12;
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 35978e3..c493594 100755
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -19,6 +19,7 @@
 
 #include <ctype.h>
 #include <inttypes.h>
+#include <algorithm>
 #include <memory>
 #include <stdint.h>
 #include <stdlib.h>
@@ -149,9 +150,13 @@
     bool mIsAudio;
     sp<ItemTable> mItemTable;
 
-    // Start offset from composition time to presentation time.
-    // Support shift only for video tracks through mElstShiftStartTicks for now.
+    /* Shift start offset (move to earlier time) when media_time > 0,
+     * in media time scale.
+     */
     uint64_t mElstShiftStartTicks;
+    /* Initial start offset (move to later time), empty edit list entry
+     * in media time scale.
+     */
     uint64_t mElstInitialEmptyEditTicks;
 
     size_t parseNALSize(const uint8_t *data) const;
@@ -1216,7 +1221,6 @@
                 off64_t entriesoffset = data_offset + 8;
                 uint64_t segment_duration;
                 int64_t media_time;
-                uint64_t empty_edit_ticks = 0;
                 bool empty_edit_present = false;
                 for (int i = 0; i < entry_count; ++i) {
                     switch (version) {
@@ -1248,45 +1252,37 @@
                     }
                     // Empty edit entry would have to be first entry.
                     if (media_time == -1 && i == 0) {
-                        int64_t durationUs;
-                        if (AMediaFormat_getInt64(mFileMetaData, AMEDIAFORMAT_KEY_DURATION,
-                                                  &durationUs)) {
-                            empty_edit_ticks = segment_duration;
-                            ALOGV("initial empty edit ticks: %" PRIu64, empty_edit_ticks);
-                            empty_edit_present = true;
-                        }
-                    }
-                    // Process second entry only when the first entry was an empty edit entry.
-                    if (empty_edit_present && i == 1) {
-                        int64_t durationUs;
-                        if (AMediaFormat_getInt64(mLastTrack->meta, AMEDIAFORMAT_KEY_DURATION,
-                                                  &durationUs) &&
-                            mHeaderTimescale != 0) {
-                            // Support only segment_duration<=track_duration and media_time==0 case.
-                            uint64_t segmentDurationUs =
-                                    segment_duration * 1000000 / mHeaderTimescale;
-                            if (segmentDurationUs == 0 || segmentDurationUs > durationUs ||
-                                media_time != 0) {
-                                ALOGW("for now, unsupported second entry in empty edit list");
-                            }
-                        }
+                        empty_edit_present = true;
+                        ALOGV("initial empty edit ticks: %" PRIu64, segment_duration);
+                        /* In movie header timescale, and needs to be converted to media timescale
+                         * after we get that from a track's 'mdhd' atom,
+                         * which at times come after 'elst'.
+                         */
+                        mLastTrack->elst_initial_empty_edit_ticks = segment_duration;
+                    } else if (media_time >= 0 && i == 0) {
+                        ALOGV("first edit list entry");
+                        mLastTrack->elst_media_time = media_time;
+                        mLastTrack->elst_segment_duration = segment_duration;
+                        ALOGV("segment_duration: %" PRIu64 " media_time: %" PRId64,
+                              segment_duration, media_time);
+                        // media_time is in media timescale as are STTS/CTTS entries.
+                        mLastTrack->elst_shift_start_ticks = media_time;
+                    } else if (empty_edit_present && i == 1) {
+                        // Process second entry only when the first entry was an empty edit entry.
+                        ALOGV("second edit list entry");
+                        mLastTrack->elst_media_time = media_time;
+                        mLastTrack->elst_segment_duration = segment_duration;
+                        ALOGV("segment_duration: %" PRIu64 " media_time: %" PRId64,
+                              segment_duration, media_time);
+                        mLastTrack->elst_shift_start_ticks = media_time;
+                    } else {
+                        ALOGW("for now, unsupported entry in edit list %" PRIu32, entry_count);
                     }
                 }
                 // save these for later, because the elst atom might precede
                 // the atoms that actually gives us the duration and sample rate
                 // needed to calculate the padding and delay values
                 mLastTrack->elst_needs_processing = true;
-                if (empty_edit_present) {
-                    /* In movie header timescale, and needs to be converted to media timescale once
-                     * we get that from a track's 'mdhd' atom, which at times come after 'elst'.
-                     */
-                    mLastTrack->elst_initial_empty_edit_ticks = empty_edit_ticks;
-                } else {
-                    mLastTrack->elst_media_time = media_time;
-                    mLastTrack->elst_segment_duration = segment_duration;
-                    ALOGV("segment_duration: %" PRIu64 " media_time: %" PRId64, segment_duration,
-                          media_time);
-                }
             }
             break;
         }
@@ -4325,9 +4321,9 @@
         }
     }
 
-    // media_time is in media timescale as are STTS/CTTS entries.
-    track->elst_shift_start_ticks = track->elst_media_time;
     ALOGV("track->elst_shift_start_ticks :%" PRIu64, track->elst_shift_start_ticks);
+
+    uint64_t elst_initial_empty_edit_ticks = 0;
     if (mHeaderTimescale != 0) {
         // Convert empty_edit_ticks from movie timescale to media timescale.
         uint64_t elst_initial_empty_edit_ticks_mul = 0, elst_initial_empty_edit_ticks_add = 0;
@@ -4338,15 +4334,15 @@
             ALOGE("track->elst_initial_empty_edit_ticks overflow");
             return nullptr;
         }
-        track->elst_initial_empty_edit_ticks = elst_initial_empty_edit_ticks_add / mHeaderTimescale;
-        ALOGV("track->elst_initial_empty_edit_ticks :%" PRIu64,
-              track->elst_initial_empty_edit_ticks);
+        elst_initial_empty_edit_ticks = elst_initial_empty_edit_ticks_add / mHeaderTimescale;
     }
+    ALOGV("elst_initial_empty_edit_ticks in MediaTimeScale :%" PRIu64,
+          elst_initial_empty_edit_ticks);
 
     MPEG4Source* source =
             new MPEG4Source(track->meta, mDataSource, track->timescale, track->sampleTable,
                             mSidxEntries, trex, mMoofOffset, itemTable,
-                            track->elst_shift_start_ticks, track->elst_initial_empty_edit_ticks);
+                            track->elst_shift_start_ticks, elst_initial_empty_edit_ticks);
     if (source->init() != OK) {
         delete source;
         return NULL;
@@ -5906,9 +5902,22 @@
                     break;
             }
             if( mode != ReadOptions::SEEK_FRAME_INDEX) {
-                seekTimeUs += ((long double)mElstShiftStartTicks * 1000000) / mTimescale;
-                ALOGV("shifted seekTimeUs :%" PRId64 ", mElstShiftStartTicks:%" PRIu64, seekTimeUs,
-                      mElstShiftStartTicks);
+                int64_t elstInitialEmptyEditUs = 0, elstShiftStartUs = 0;
+                if (mElstInitialEmptyEditTicks > 0) {
+                    elstInitialEmptyEditUs = ((long double)mElstInitialEmptyEditTicks * 1000000) /
+                                             mTimescale;
+                    /* Sample's composition time from ctts/stts entries are non-negative(>=0).
+                     * Hence, lower bound on seekTimeUs is 0.
+                     */
+                    seekTimeUs = std::max(seekTimeUs - elstInitialEmptyEditUs, (int64_t)0);
+                }
+                if (mElstShiftStartTicks > 0) {
+                    elstShiftStartUs = ((long double)mElstShiftStartTicks * 1000000) / mTimescale;
+                    seekTimeUs += elstShiftStartUs;
+                }
+                ALOGV("shifted seekTimeUs:%" PRId64 ", elstInitialEmptyEditUs:%" PRIu64
+                      ", elstShiftStartUs:%" PRIu64, seekTimeUs, elstInitialEmptyEditUs,
+                      elstShiftStartUs);
             }
 
             uint32_t sampleIndex;
@@ -5954,7 +5963,12 @@
 
             if (mode == ReadOptions::SEEK_CLOSEST
                 || mode == ReadOptions::SEEK_FRAME_INDEX) {
-                sampleTime -= mElstShiftStartTicks;
+                if (mElstInitialEmptyEditTicks > 0) {
+                    sampleTime += mElstInitialEmptyEditTicks;
+                }
+                if (mElstShiftStartTicks > 0){
+                    sampleTime -= mElstShiftStartTicks;
+                }
                 targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
             }
 
@@ -5997,12 +6011,12 @@
             if(err == OK) {
                 if (mElstInitialEmptyEditTicks > 0) {
                     cts += mElstInitialEmptyEditTicks;
-                } else {
+                }
+                if (mElstShiftStartTicks > 0) {
                     // cts can be negative. for example, initial audio samples for gapless playback.
                     cts -= (int64_t)mElstShiftStartTicks;
                 }
             }
-
         } else {
             err = mItemTable->getImageOffsetAndSize(
                     options && options->getSeekTo(&seekTimeUs, &mode) ?
@@ -6282,10 +6296,22 @@
     int64_t seekTimeUs;
     ReadOptions::SeekMode mode;
     if (options && options->getSeekTo(&seekTimeUs, &mode)) {
-
-        seekTimeUs += ((long double)mElstShiftStartTicks * 1000000) / mTimescale;
-        ALOGV("shifted seekTimeUs :%" PRId64 ", mElstShiftStartTicks:%" PRIu64, seekTimeUs,
-              mElstShiftStartTicks);
+        int64_t elstInitialEmptyEditUs = 0, elstShiftStartUs = 0;
+        if (mElstInitialEmptyEditTicks > 0) {
+            elstInitialEmptyEditUs = ((long double)mElstInitialEmptyEditTicks * 1000000) /
+                                     mTimescale;
+            /* Sample's composition time from ctts/stts entries are non-negative(>=0).
+             * Hence, lower bound on seekTimeUs is 0.
+             */
+            seekTimeUs = std::max(seekTimeUs - elstInitialEmptyEditUs, (int64_t)0);
+        }
+        if (mElstShiftStartTicks > 0){
+            elstShiftStartUs = ((long double)mElstShiftStartTicks * 1000000) / mTimescale;
+            seekTimeUs += elstShiftStartUs;
+        }
+        ALOGV("shifted seekTimeUs:%" PRId64 ", elstInitialEmptyEditUs:%" PRIu64
+              ", elstShiftStartUs:%" PRIu64, seekTimeUs, elstInitialEmptyEditUs,
+              elstShiftStartUs);
 
         int numSidxEntries = mSegments.size();
         if (numSidxEntries != 0) {
@@ -6376,7 +6402,8 @@
 
         if (mElstInitialEmptyEditTicks > 0) {
             cts += mElstInitialEmptyEditTicks;
-        } else {
+        }
+        if (mElstShiftStartTicks > 0) {
             // cts can be negative. for example, initial audio samples for gapless playback.
             cts -= (int64_t)mElstShiftStartTicks;
         }
diff --git a/media/extractors/mp4/MPEG4Extractor.h b/media/extractors/mp4/MPEG4Extractor.h
index 53ec6bc..3af432d 100644
--- a/media/extractors/mp4/MPEG4Extractor.h
+++ b/media/extractors/mp4/MPEG4Extractor.h
@@ -88,9 +88,9 @@
          */
         int64_t elst_media_time;
         uint64_t elst_segment_duration;
-        // Shift start offset only when media_time > 0.
+        // Shift start offset (move to earlier time) when media_time > 0.
         uint64_t elst_shift_start_ticks;
-        // Initial start offset, empty edit list entry.
+        // Initial start offset (move to later time), from empty edit list entry.
         uint64_t elst_initial_empty_edit_ticks;
         bool subsample_encryption;
 
diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp
index e5115d9..fa13f32 100644
--- a/media/libstagefright/ACodecBufferChannel.cpp
+++ b/media/libstagefright/ACodecBufferChannel.cpp
@@ -134,7 +134,12 @@
     }
     ssize_t result = -1;
     ssize_t codecDataOffset = 0;
-    if (mCrypto != NULL) {
+    if (numSubSamples == 1
+            && subSamples[0].mNumBytesOfClearData == 0
+            && subSamples[0].mNumBytesOfEncryptedData == 0) {
+        // We don't need to go through crypto or descrambler if the input is empty.
+        result = 0;
+    } else if (mCrypto != NULL) {
         hardware::drm::V1_0::DestinationBuffer destination;
         if (secure) {
             destination.type = DrmBufferType::NATIVE_HANDLE;
diff --git a/services/mediacodec/registrant/CodecServiceRegistrant.cpp b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
index 83d233e..184251a 100644
--- a/services/mediacodec/registrant/CodecServiceRegistrant.cpp
+++ b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
@@ -17,11 +17,13 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "CodecServiceRegistrant"
 
+#include <android-base/properties.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 
 #include <C2Component.h>
 #include <C2PlatformSupport.h>
+#include <codec2/hidl/1.0/ComponentStore.h>
 #include <codec2/hidl/1.1/ComponentStore.h>
 #include <codec2/hidl/1.1/Configurable.h>
 #include <codec2/hidl/1.1/types.h>
@@ -43,6 +45,10 @@
 // Converter from IComponentStore to C2ComponentStore.
 class H2C2ComponentStore : public C2ComponentStore {
 protected:
+    using IComponentStore =
+        ::android::hardware::media::c2::V1_0::IComponentStore;
+    using IConfigurable =
+        ::android::hardware::media::c2::V1_0::IConfigurable;
     sp<IComponentStore> mStore;
     sp<IConfigurable> mConfigurable;
 public:
@@ -399,36 +405,67 @@
 } // unnamed namespace
 
 extern "C" void RegisterCodecServices() {
-    using namespace ::android::hardware::media::c2::V1_1;
     LOG(INFO) << "Creating software Codec2 service...";
-    sp<ComponentStore> store =
-        new ComponentStore(::android::GetCodec2PlatformComponentStore());
-    if (store == nullptr) {
-        LOG(ERROR) <<
-                "Cannot create software Codec2 service.";
-    } else {
-        if (!ionPropertiesDefined()) {
-            std::string preferredStoreName = "default";
-            sp<IComponentStore> preferredStore =
-                IComponentStore::getService(preferredStoreName.c_str());
-            if (preferredStore) {
-                ::android::SetPreferredCodec2ComponentStore(
-                        std::make_shared<H2C2ComponentStore>(preferredStore));
-                LOG(INFO) <<
-                        "Preferred Codec2 store is set to \"" <<
-                        preferredStoreName << "\".";
-            } else {
-                LOG(INFO) <<
-                        "Preferred Codec2 store is defaulted to \"software\".";
+    std::shared_ptr<C2ComponentStore> store =
+        android::GetCodec2PlatformComponentStore();
+    if (!store) {
+        LOG(ERROR) << "Failed to create Codec2 service.";
+        return;
+    }
+
+    using namespace ::android::hardware::media::c2;
+
+    int platformVersion =
+        android::base::GetIntProperty("ro.build.version.sdk", int32_t(29));
+    // STOPSHIP: Remove code name checking once platform version bumps up to 30.
+    std::string codeName =
+        android::base::GetProperty("ro.build.version.codename", "");
+    if (codeName == "R") {
+        platformVersion = 30;
+    }
+
+    switch (platformVersion) {
+        case 30: {
+            android::sp<V1_1::IComponentStore> storeV1_1 =
+                new V1_1::utils::ComponentStore(store);
+            if (storeV1_1->registerAsService("software") != android::OK) {
+                LOG(ERROR) << "Cannot register software Codec2 v1.1 service.";
+                return;
             }
+            break;
         }
-        if (store->registerAsService("software") != android::OK) {
-            LOG(ERROR) <<
-                    "Cannot register software Codec2 service.";
-        } else {
-            LOG(INFO) <<
-                    "Software Codec2 service created.";
+        case 29: {
+            android::sp<V1_0::IComponentStore> storeV1_0 =
+                new V1_0::utils::ComponentStore(store);
+            if (storeV1_0->registerAsService("software") != android::OK) {
+                LOG(ERROR) << "Cannot register software Codec2 v1.0 service.";
+                return;
+            }
+            break;
+        }
+        default: {
+            LOG(ERROR) << "The platform version " << platformVersion <<
+                          " is not supported.";
+            return;
         }
     }
+    if (!ionPropertiesDefined()) {
+        using IComponentStore =
+            ::android::hardware::media::c2::V1_0::IComponentStore;
+        std::string const preferredStoreName = "default";
+        sp<IComponentStore> preferredStore =
+            IComponentStore::getService(preferredStoreName.c_str());
+        if (preferredStore) {
+            ::android::SetPreferredCodec2ComponentStore(
+                    std::make_shared<H2C2ComponentStore>(preferredStore));
+            LOG(INFO) <<
+                    "Preferred Codec2 store is set to \"" <<
+                    preferredStoreName << "\".";
+        } else {
+            LOG(INFO) <<
+                    "Preferred Codec2 store is defaulted to \"software\".";
+        }
+    }
+    LOG(INFO) << "Software Codec2 service created and registered.";
 }