Merge "C2: Update graphic buffer allocation calls to allow odd dimensions" into main
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 2c68cef..9f9860b 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -40,6 +40,21 @@
 
 __BEGIN_DECLS
 
+/*
+ * Note: The following enum values were incorrect and have been updated:
+ * enum                                                        old value                        updated value
+ * ACAMERA_CONTROL_SETTINGS_OVERRIDE                           ACAMERA_CONTROL_START + 49       ACAMERA_CONTROL_START + 52;
+ * ACAMERA_CONTROL_AVAILABLE_SETTINGS_OVERRIDES                ACAMERA_CONTROL_START + 50       ACAMERA_CONTROL_START + 53;
+ * ACAMERA_CONTROL_AUTOFRAMING                                 ACAMERA_CONTROL_START + 52       ACAMERA_CONTROL_START + 55;
+ * ACAMERA_CONTROL_AUTOFRAMING_AVAILABLE                       ACAMERA_CONTROL_START + 53       ACAMERA_CONTROL_START + 56;
+ * ACAMERA_CONTROL_AUTOFRAMING_STATE                           ACAMERA_CONTROL_START + 54       ACAMERA_CONTROL_START + 57;
+ * ACAMERA_CONTROL_LOW_LIGHT_BOOST_INFO_LUMINANCE_RANGE        ACAMERA_CONTROL_START + 55       ACAMERA_CONTROL_START + 58;
+ * ACAMERA_CONTROL_LOW_LIGHT_BOOST_STATE                       ACAMERA_CONTROL_START + 56       ACAMERA_CONTROL_START + 59;
+
+ * ACAMERA_SCALER_AVAILABLE_STREAM_USE_CASES                   ACAMERA_SCALER_START + 25        ACAMERA_SCALER_START + 26;
+ * ACAMERA_SCALER_CROP_REGION                                  ACAMERA_SCALER_START + 26        ACAMERA_SCALER_START + 27;
+ */
+
 
 typedef enum acamera_metadata_section {
     ACAMERA_COLOR_CORRECTION,
@@ -2147,7 +2162,7 @@
      * </ul>
      */
     ACAMERA_CONTROL_SETTINGS_OVERRIDE =                         // int32 (acamera_metadata_enum_android_control_settings_override_t)
-            ACAMERA_CONTROL_START + 49,
+            ACAMERA_CONTROL_START + 52,
     /**
      * <p>List of available settings overrides supported by the camera device that can
      * be used to speed up certain controls.</p>
@@ -2173,7 +2188,7 @@
      * @see ACAMERA_CONTROL_SETTINGS_OVERRIDE
      */
     ACAMERA_CONTROL_AVAILABLE_SETTINGS_OVERRIDES =              // int32[n]
-            ACAMERA_CONTROL_START + 50,
+            ACAMERA_CONTROL_START + 53,
     /**
      * <p>Automatic crop, pan and zoom to keep objects in the center of the frame.</p>
      *
@@ -2200,7 +2215,7 @@
      * @see ACAMERA_SCALER_CROP_REGION
      */
     ACAMERA_CONTROL_AUTOFRAMING =                               // byte (acamera_metadata_enum_android_control_autoframing_t)
-            ACAMERA_CONTROL_START + 52,
+            ACAMERA_CONTROL_START + 55,
     /**
      * <p>Whether the camera device supports ACAMERA_CONTROL_AUTOFRAMING.</p>
      *
@@ -2216,7 +2231,7 @@
      * <p>Will be <code>false</code> if auto-framing is not available.</p>
      */
     ACAMERA_CONTROL_AUTOFRAMING_AVAILABLE =                     // byte (acamera_metadata_enum_android_control_autoframing_available_t)
-            ACAMERA_CONTROL_START + 53,
+            ACAMERA_CONTROL_START + 56,
     /**
      * <p>Current state of auto-framing.</p>
      *
@@ -2243,7 +2258,7 @@
      * @see ACAMERA_CONTROL_AUTOFRAMING_AVAILABLE
      */
     ACAMERA_CONTROL_AUTOFRAMING_STATE =                         // byte (acamera_metadata_enum_android_control_autoframing_state_t)
-            ACAMERA_CONTROL_START + 54,
+            ACAMERA_CONTROL_START + 57,
     /**
      * <p>The operating luminance range of low light boost measured in lux (lx).</p>
      *
@@ -2256,7 +2271,7 @@
      *
      */
     ACAMERA_CONTROL_LOW_LIGHT_BOOST_INFO_LUMINANCE_RANGE =      // float[2]
-            ACAMERA_CONTROL_START + 55,
+            ACAMERA_CONTROL_START + 58,
     /**
      * <p>Current state of the low light boost AE mode.</p>
      *
@@ -2276,7 +2291,7 @@
      * 'ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY.</p>
      */
     ACAMERA_CONTROL_LOW_LIGHT_BOOST_STATE =                     // byte (acamera_metadata_enum_android_control_low_light_boost_state_t)
-            ACAMERA_CONTROL_START + 56,
+            ACAMERA_CONTROL_START + 59,
     ACAMERA_CONTROL_END,
 
     /**
@@ -4669,7 +4684,7 @@
      * application should leave stream use cases within the session as DEFAULT.</p>
      */
     ACAMERA_SCALER_AVAILABLE_STREAM_USE_CASES =                 // int64[n] (acamera_metadata_enum_android_scaler_available_stream_use_cases_t)
-            ACAMERA_SCALER_START + 25,
+            ACAMERA_SCALER_START + 26,
     /**
      * <p>The region of the sensor that corresponds to the RAW read out for this
      * capture when the stream use case of a RAW stream is set to CROPPED_RAW.</p>
@@ -4722,7 +4737,7 @@
      * @see ACAMERA_STATISTICS_HOT_PIXEL_MAP
      */
     ACAMERA_SCALER_RAW_CROP_REGION =                            // int32[4]
-            ACAMERA_SCALER_START + 26,
+            ACAMERA_SCALER_START + 27,
     ACAMERA_SCALER_END,
 
     /**
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index 2a8ebc6..ce56d87 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -569,7 +569,19 @@
 status_t StreamOutHalAidl::setVolume(float left, float right) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    return statusTFromBinderStatus(mStream->setHwVolume({left, right}));
+    size_t channelCount = audio_channel_out_mask_from_count(mConfig.channel_mask);
+    if (channelCount == 0) channelCount = 2;
+    std::vector<float> volumes(channelCount);
+    if (channelCount == 1) {
+        volumes[0] = (left + right) / 2;
+    } else {
+        volumes[0] = left;
+        volumes[1] = right;
+        for (size_t i = 2; i < channelCount; ++i) {
+            volumes[i] = (left + right) / 2;
+        }
+    }
+    return statusTFromBinderStatus(mStream->setHwVolume(volumes));
 }
 
 status_t StreamOutHalAidl::selectPresentation(int presentationId, int programId) {
@@ -866,7 +878,9 @@
 status_t StreamInHalAidl::setGain(float gain) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    return statusTFromBinderStatus(mStream->setHwGain({gain}));
+    const size_t channelCount = audio_channel_count_from_in_mask(mConfig.channel_mask);
+    std::vector<float> gains(channelCount != 0 ? channelCount : 1, gain);
+    return statusTFromBinderStatus(mStream->setHwGain(gains));
 }
 
 status_t StreamInHalAidl::read(void *buffer, size_t bytes, size_t *read) {
diff --git a/media/libstagefright/TEST_MAPPING b/media/libstagefright/TEST_MAPPING
index dd6da15..b7efbce 100644
--- a/media/libstagefright/TEST_MAPPING
+++ b/media/libstagefright/TEST_MAPPING
@@ -20,7 +20,6 @@
         {
           "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
         },
-        // TODO: b/149314419
         {
           "exclude-filter": "android.media.audio.cts.AudioPlaybackCaptureTest"
         },
diff --git a/media/module/extractors/fuzzers/Android.bp b/media/module/extractors/fuzzers/Android.bp
index d096d63..7a49d8e 100644
--- a/media/module/extractors/fuzzers/Android.bp
+++ b/media/module/extractors/fuzzers/Android.bp
@@ -134,6 +134,8 @@
     ],
 
     dictionary: "mp4_extractor_fuzzer.dict",
+
+    corpus: ["corpus_mp4/*"],
 }
 
 cc_fuzz {
@@ -202,7 +204,6 @@
         "ogg_extractor_fuzzer.cpp",
     ],
 
-
     static_libs: [
         "libstagefright_metadatautils",
         "libvorbisidec",
diff --git a/media/module/extractors/fuzzers/corpus_mp4/164a5bad5340b262316f93932c4160813657e1e0 b/media/module/extractors/fuzzers/corpus_mp4/164a5bad5340b262316f93932c4160813657e1e0
new file mode 100644
index 0000000..c17251b
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/164a5bad5340b262316f93932c4160813657e1e0
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/24f242f3b30fd5c2ff0f9aebed4375a3ab5cdceb b/media/module/extractors/fuzzers/corpus_mp4/24f242f3b30fd5c2ff0f9aebed4375a3ab5cdceb
new file mode 100644
index 0000000..16907fd
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/24f242f3b30fd5c2ff0f9aebed4375a3ab5cdceb
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/2a017927fdab79a8cc3b0bb75224cb44f4c1b35b b/media/module/extractors/fuzzers/corpus_mp4/2a017927fdab79a8cc3b0bb75224cb44f4c1b35b
new file mode 100644
index 0000000..2ec7881
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/2a017927fdab79a8cc3b0bb75224cb44f4c1b35b
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/58b3155e64ac16e4e6c68b68257871bcd769b92f b/media/module/extractors/fuzzers/corpus_mp4/58b3155e64ac16e4e6c68b68257871bcd769b92f
new file mode 100644
index 0000000..cd1fdcc
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/58b3155e64ac16e4e6c68b68257871bcd769b92f
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/64093d4da00ba406310c7679cd8b37562e6344b5 b/media/module/extractors/fuzzers/corpus_mp4/64093d4da00ba406310c7679cd8b37562e6344b5
new file mode 100644
index 0000000..f1ea812
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/64093d4da00ba406310c7679cd8b37562e6344b5
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/7355066d4975de07e9b6d0e9907c896eeb90577a b/media/module/extractors/fuzzers/corpus_mp4/7355066d4975de07e9b6d0e9907c896eeb90577a
new file mode 100644
index 0000000..c5d3eb2
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/7355066d4975de07e9b6d0e9907c896eeb90577a
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/7a48b0237581c794097a15add08517b3c6dc0aa2 b/media/module/extractors/fuzzers/corpus_mp4/7a48b0237581c794097a15add08517b3c6dc0aa2
new file mode 100644
index 0000000..1f6c29d
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/7a48b0237581c794097a15add08517b3c6dc0aa2
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/8706f07041a0cf828a7b40d727533d6c732b5ebc b/media/module/extractors/fuzzers/corpus_mp4/8706f07041a0cf828a7b40d727533d6c732b5ebc
new file mode 100644
index 0000000..40d639d
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/8706f07041a0cf828a7b40d727533d6c732b5ebc
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/911a46d40d60b9a806dbdc70799048df2f546615 b/media/module/extractors/fuzzers/corpus_mp4/911a46d40d60b9a806dbdc70799048df2f546615
new file mode 100644
index 0000000..2056348
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/911a46d40d60b9a806dbdc70799048df2f546615
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/97b1d0e78525c793574cce3e66f86564c2a10271 b/media/module/extractors/fuzzers/corpus_mp4/97b1d0e78525c793574cce3e66f86564c2a10271
new file mode 100644
index 0000000..f50d4f4
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/97b1d0e78525c793574cce3e66f86564c2a10271
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/d52e7095534fdf1f040b10a80df4cbc069a97a4e b/media/module/extractors/fuzzers/corpus_mp4/d52e7095534fdf1f040b10a80df4cbc069a97a4e
new file mode 100644
index 0000000..25ea55b
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/d52e7095534fdf1f040b10a80df4cbc069a97a4e
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/ec6bd6069f74a2f6e92442f88efb29288ad6f456 b/media/module/extractors/fuzzers/corpus_mp4/ec6bd6069f74a2f6e92442f88efb29288ad6f456
new file mode 100644
index 0000000..62d259b
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/ec6bd6069f74a2f6e92442f88efb29288ad6f456
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/faa22bcb745206340d5d411b498a3868d2b1feec b/media/module/extractors/fuzzers/corpus_mp4/faa22bcb745206340d5d411b498a3868d2b1feec
new file mode 100644
index 0000000..d649632
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/faa22bcb745206340d5d411b498a3868d2b1feec
Binary files differ
diff --git a/media/module/extractors/fuzzers/mp4_extractor_fuzzer.dict b/media/module/extractors/fuzzers/mp4_extractor_fuzzer.dict
index 3683649..b48c854 100644
--- a/media/module/extractors/fuzzers/mp4_extractor_fuzzer.dict
+++ b/media/module/extractors/fuzzers/mp4_extractor_fuzzer.dict
@@ -246,3 +246,4 @@
 kw245="iso5"
 kw246="resv"
 kw247="iso6"
+kw248="clap"
diff --git a/media/module/extractors/mkv/MatroskaExtractor.cpp b/media/module/extractors/mkv/MatroskaExtractor.cpp
index 6900341..a328ab9 100644
--- a/media/module/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/module/extractors/mkv/MatroskaExtractor.cpp
@@ -1769,6 +1769,30 @@
 
 }
 
+status_t MatroskaExtractor::synthesizeVP9(TrackInfo* trackInfo, size_t index) {
+    BlockIterator iter(this, trackInfo->mTrackNum, index);
+    if (iter.eos()) {
+        return ERROR_MALFORMED;
+    }
+
+    const mkvparser::Block* block = iter.block();
+    if (block->GetFrameCount() <= 0) {
+        return ERROR_MALFORMED;
+    }
+
+    const mkvparser::Block::Frame& frame = block->GetFrame(0);
+    auto tmpData = heapbuffer<unsigned char>(frame.len);
+    long n = frame.Read(mReader, tmpData.get());
+    if (n != 0) {
+        return ERROR_MALFORMED;
+    }
+
+    if (!MakeVP9CodecSpecificData(trackInfo->mMeta, tmpData.get(), frame.len)) {
+        return ERROR_MALFORMED;
+    }
+
+    return OK;
+}
 
 static inline bool isValidInt32ColourValue(long long value) {
     return value != mkvparser::Colour::kValueNotPresent
@@ -2002,6 +2026,8 @@
                       // specified in http://www.webmproject.org/vp9/profiles/.
                       AMediaFormat_setBuffer(meta,
                              AMEDIAFORMAT_KEY_CSD_0, codecPrivate, codecPrivateSize);
+                    } else {
+                        isSetCsdFrom1stFrame = true;
                     }
                 } else if (!strcmp("V_AV1", codecID)) {
                     AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_AV1);
@@ -2254,6 +2280,14 @@
                 mTracks.pop();
                 continue;
             }
+        } else if ((!strcmp("V_VP9", codecID) && codecPrivateSize == 0) ||
+                   (!strcmp(mimetype, MEDIA_MIMETYPE_VIDEO_VP9) && isSetCsdFrom1stFrame)) {
+            // Attempt to recover from VP9 track without codec private data
+            err = synthesizeVP9(trackInfo, n);
+            if (err != OK) {
+                mTracks.pop();
+                continue;
+            }
         }
         // the TrackInfo owns the metadata now
         meta = nullptr;
diff --git a/media/module/extractors/mkv/include/MatroskaExtractor.h b/media/module/extractors/mkv/include/MatroskaExtractor.h
index 99fad17..2e4d955 100644
--- a/media/module/extractors/mkv/include/MatroskaExtractor.h
+++ b/media/module/extractors/mkv/include/MatroskaExtractor.h
@@ -95,6 +95,7 @@
     status_t synthesizeAVCC(TrackInfo *trackInfo, size_t index);
     status_t synthesizeMPEG2(TrackInfo *trackInfo, size_t index);
     status_t synthesizeMPEG4(TrackInfo *trackInfo, size_t index);
+    status_t synthesizeVP9(TrackInfo* trackInfo, size_t index);
     status_t initTrackInfo(
             const mkvparser::Track *track,
             AMediaFormat *meta,
diff --git a/media/module/metadatautils/MetaDataUtils.cpp b/media/module/metadatautils/MetaDataUtils.cpp
index db60f04..e5854b6 100644
--- a/media/module/metadatautils/MetaDataUtils.cpp
+++ b/media/module/metadatautils/MetaDataUtils.cpp
@@ -81,6 +81,124 @@
     return true;
 }
 
+// The param data contains the first frame data, starting with the uncompressed frame
+// header. This uncompressed header (refer section 6.2 of the VP9 bitstream spec) is
+// used to parse profile, bitdepth and subsampling.
+bool MakeVP9CodecSpecificData(AMediaFormat* meta, const uint8_t* data, size_t size) {
+    if (meta == nullptr || data == nullptr || size == 0) {
+        return false;
+    }
+
+    ABitReader bits(data, size);
+
+    // First 2 bits of the uncompressed header should be the frame_marker.
+    if (bits.getBits(2) != 0b10) {
+        return false;
+    }
+
+    int32_t profileLowBit = bits.getBits(1);
+    int32_t profileHighBit = bits.getBits(1);
+    int32_t profile = profileHighBit * 2 + profileLowBit;
+
+    // One reserved '0' bit if profile is 3.
+    if (profile == 3 && bits.getBits(1) != 0) {
+        return false;
+    }
+
+    // If show_existing_frame is set, we get no more data. Since this is
+    // expected to be the first frame, we can return false which will cascade
+    // into ERROR_MALFORMED.
+    if (bits.getBits(1)) {
+        return false;
+    }
+
+    // This should be the first frame, so expect a KEY_FRAME.
+    // if (frame_type != KEY_FRAME)
+    if (bits.getBits(1) != 0) {
+        return false;
+    }
+
+    // Upto 7 bits could be read till now, which were guaranteed to be available
+    // since size > 0. Check for bits available before reading them from now on.
+    if (bits.numBitsLeft() < 26) {
+        return false;
+    }
+    // Discard show_frame and error_resilient_mode.
+    bits.skipBits(2);
+
+    // Check for sync code.
+    if (bits.getBits(24) != 0x498342) {
+        return false;
+    }
+
+    int32_t bitDepth;
+    if (profile >= 2) {
+        if (bits.numBitsLeft() < 1) {
+            return false;
+        }
+        bitDepth = bits.getBits(1) ? 12 : 10;
+    } else {
+        bitDepth = 8;
+    }
+
+    uint32_t colorspace;
+    if (!bits.getBitsGraceful(3, &colorspace)) {
+        return false;
+    }
+
+    int32_t chromaSubsampling = -1;
+    if (colorspace != 7 /*SRGB*/) {
+        // Skip yuv_range_flag
+        if (!bits.skipBits(1)) {
+            return false;
+        }
+        // Check for subsampling only for profiles 1 and 3.
+        if (profile == 1 || profile == 3) {
+            uint32_t ss_x;
+            uint32_t ss_y;
+            if (bits.getBitsGraceful(1, &ss_x) && bits.getBitsGraceful(1, &ss_y)) {
+                chromaSubsampling = ss_x << 1 & ss_y;
+            } else {
+                return false;
+            }
+        } else  {
+            chromaSubsampling = 3;
+        }
+    } else {
+        if (profile == 1 || profile == 3) {
+            chromaSubsampling = 0;
+        }
+    }
+
+    int32_t csdSize = 6;
+    if (chromaSubsampling != -1) {
+        csdSize += 3;
+    }
+
+    // Create VP9 Codec Feature Metadata (CodecPrivate) that can be parsed
+    // https://www.webmproject.org/docs/container/#vp9-codec-feature-metadata-codecprivate
+    sp<ABuffer> csd = sp<ABuffer>::make(csdSize);
+    uint8_t* csdData = csd->data();
+
+    *csdData++ = 0x01 /* FEATURE PROFILE */;
+    *csdData++ = 0x01 /* length */;
+    *csdData++ = profile;
+
+    *csdData++ = 0x03 /* FEATURE BITDEPTH */;
+    *csdData++ = 0x01 /* length */;
+    *csdData++ = bitDepth;
+
+    // csdSize more than 6 means chroma subsampling data was found.
+    if (csdSize > 6) {
+        *csdData++ = 0x04 /* FEATURE SUBSAMPLING */;
+        *csdData++ = 0x01 /* length */;
+        *csdData++ = chromaSubsampling;
+    }
+
+    AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CSD_0, csd->data(), csd->size());
+    return true;
+}
+
 bool MakeAACCodecSpecificData(MetaDataBase &meta, const uint8_t *data, size_t size) {
     if (data == nullptr || size < 7) {
         return false;
diff --git a/media/module/metadatautils/include/media/stagefright/MetaDataUtils.h b/media/module/metadatautils/include/media/stagefright/MetaDataUtils.h
index dcaf27f..69cf21a 100644
--- a/media/module/metadatautils/include/media/stagefright/MetaDataUtils.h
+++ b/media/module/metadatautils/include/media/stagefright/MetaDataUtils.h
@@ -38,6 +38,8 @@
 void parseVorbisComment(
         AMediaFormat *fileMeta, const char *comment, size_t commentLength);
 
+bool MakeVP9CodecSpecificData(AMediaFormat* meta, const uint8_t* data, size_t size);
+
 }  // namespace android
 
 #endif  // META_DATA_UTILS_H_