Merge "C2Fuzzer: fix memory leak in Codec2Fuzzer::decodeFrames"
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..a7614d2
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,13 @@
+BasedOnStyle: Google
+Standard: Cpp11
+AccessModifierOffset: -2
+AllowShortFunctionsOnASingleLine: Inline
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IncludeBlocks: Preserve
+IndentWidth: 4
+ContinuationIndentWidth: 8
+PointerAlignment: Left
+TabWidth: 4
+UseTab: Never
diff --git a/camera/OWNERS b/camera/OWNERS
index d6b95da..47d1d19 100644
--- a/camera/OWNERS
+++ b/camera/OWNERS
@@ -2,7 +2,7 @@
etalvala@google.com
jchowdhary@google.com
shuzhenwang@google.com
-yinchiayeh@google.com
+ruchamk@google.com
# backup owner
cychen@google.com
zhijunhe@google.com
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index a82a61d..5ce7241 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -65,7 +65,7 @@
],
static_libs: [
- "resourcemanager_aidl_interface-ndk_platform",
+ "resourcemanager_aidl_interface-ndk",
],
export_shared_lib_headers: [
diff --git a/drm/libmediadrm/fuzzer/Android.bp b/drm/libmediadrm/fuzzer/Android.bp
index 2b04702..9faed3a 100644
--- a/drm/libmediadrm/fuzzer/Android.bp
+++ b/drm/libmediadrm/fuzzer/Android.bp
@@ -35,7 +35,7 @@
static_libs: [
"libmediadrm",
"liblog",
- "resourcemanager_aidl_interface-ndk_platform",
+ "resourcemanager_aidl_interface-ndk",
],
header_libs: [
"libmedia_headers",
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
index 60d6b44..81f4679 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
@@ -228,7 +228,6 @@
const std::shared_ptr<IntfImpl> &intfImpl)
: SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
mIntf(intfImpl),
- mDecHandle(nullptr),
mOutputBuffer{},
mInitialized(false) {
}
@@ -243,13 +242,9 @@
}
c2_status_t C2SoftMpeg4Dec::onStop() {
- if (mDecHandle) {
- if (mInitialized) {
- PVCleanUpVideoDecoder(mDecHandle);
- mInitialized = false;
- }
- delete mDecHandle;
- mDecHandle = nullptr;
+ if (mInitialized) {
+ PVCleanUpVideoDecoder(&mVideoDecControls);
+ mInitialized = false;
}
for (int32_t i = 0; i < kNumOutputBuffers; ++i) {
if (mOutputBuffer[i]) {
@@ -279,7 +274,7 @@
c2_status_t C2SoftMpeg4Dec::onFlush_sm() {
if (mInitialized) {
- if (PV_TRUE != PVResetVideoDecoder(mDecHandle)) {
+ if (PV_TRUE != PVResetVideoDecoder(&mVideoDecControls)) {
return C2_CORRUPTED;
}
}
@@ -294,14 +289,8 @@
#else
mIsMpeg4 = false;
#endif
- if (!mDecHandle) {
- mDecHandle = new tagvideoDecControls;
- }
- if (!mDecHandle) {
- ALOGE("mDecHandle is null");
- return NO_MEMORY;
- }
- memset(mDecHandle, 0, sizeof(tagvideoDecControls));
+
+ memset(&mVideoDecControls, 0, sizeof(tagvideoDecControls));
/* TODO: bring these values to 352 and 288. It cannot be done as of now
* because, h263 doesn't seem to allow port reconfiguration. In OMX, the
@@ -357,10 +346,6 @@
}
c2_status_t C2SoftMpeg4Dec::ensureDecoderState(const std::shared_ptr<C2BlockPool> &pool) {
- if (!mDecHandle) {
- ALOGE("not supposed to be here, invalid decoder context");
- return C2_CORRUPTED;
- }
mOutputBufferSize = align(mIntf->getMaxWidth(), 16) * align(mIntf->getMaxHeight(), 16) * 3 / 2;
for (int32_t i = 0; i < kNumOutputBuffers; ++i) {
@@ -391,10 +376,10 @@
bool C2SoftMpeg4Dec::handleResChange(const std::unique_ptr<C2Work> &work) {
uint32_t disp_width, disp_height;
- PVGetVideoDimensions(mDecHandle, (int32 *)&disp_width, (int32 *)&disp_height);
+ PVGetVideoDimensions(&mVideoDecControls, (int32 *)&disp_width, (int32 *)&disp_height);
uint32_t buf_width, buf_height;
- PVGetBufferDimensions(mDecHandle, (int32 *)&buf_width, (int32 *)&buf_height);
+ PVGetBufferDimensions(&mVideoDecControls, (int32 *)&buf_width, (int32 *)&buf_height);
CHECK_LE(disp_width, buf_width);
CHECK_LE(disp_height, buf_height);
@@ -415,13 +400,14 @@
}
if (!mIsMpeg4) {
- PVCleanUpVideoDecoder(mDecHandle);
+ PVCleanUpVideoDecoder(&mVideoDecControls);
uint8_t *vol_data[1]{};
int32_t vol_size = 0;
if (!PVInitVideoDecoder(
- mDecHandle, vol_data, &vol_size, 1, mIntf->getMaxWidth(), mIntf->getMaxHeight(), H263_MODE)) {
+ &mVideoDecControls, vol_data, &vol_size, 1, mIntf->getMaxWidth(),
+ mIntf->getMaxHeight(), H263_MODE)) {
ALOGE("Error in PVInitVideoDecoder H263_MODE while resChanged was set to true");
mSignalledError = true;
work->result = C2_CORRUPTED;
@@ -511,7 +497,7 @@
uint32_t *start_code = (uint32_t *)bitstream;
bool volHeader = *start_code == 0xB0010000;
if (volHeader) {
- PVCleanUpVideoDecoder(mDecHandle);
+ PVCleanUpVideoDecoder(&mVideoDecControls);
mInitialized = false;
}
@@ -526,7 +512,7 @@
}
MP4DecodingMode mode = (mIsMpeg4) ? MPEG4_MODE : H263_MODE;
if (!PVInitVideoDecoder(
- mDecHandle, vol_data, &vol_size, 1,
+ &mVideoDecControls, vol_data, &vol_size, 1,
mIntf->getMaxWidth(), mIntf->getMaxHeight(), mode)) {
ALOGE("PVInitVideoDecoder failed. Unsupported content?");
mSignalledError = true;
@@ -534,7 +520,7 @@
return;
}
mInitialized = true;
- MP4DecodingMode actualMode = PVGetDecBitstreamMode(mDecHandle);
+ MP4DecodingMode actualMode = PVGetDecBitstreamMode(&mVideoDecControls);
if (mode != actualMode) {
ALOGE("Decoded mode not same as actual mode of the decoder");
mSignalledError = true;
@@ -542,7 +528,7 @@
return;
}
- PVSetPostProcType(mDecHandle, 0);
+ PVSetPostProcType(&mVideoDecControls, 0);
if (handleResChange(work)) {
ALOGI("Setting width and height");
C2StreamPictureSizeInfo::output size(0u, mWidth, mHeight);
@@ -579,7 +565,7 @@
return;
}
- uint32_t yFrameSize = sizeof(uint8) * mDecHandle->size;
+ uint32_t yFrameSize = sizeof(uint8) * mVideoDecControls.size;
if (mOutputBufferSize < yFrameSize * 3 / 2){
ALOGE("Too small output buffer: %zu bytes", mOutputBufferSize);
mSignalledError = true;
@@ -588,7 +574,7 @@
}
if (!mFramesConfigured) {
- PVSetReferenceYUV(mDecHandle,mOutputBuffer[1]);
+ PVSetReferenceYUV(&mVideoDecControls,mOutputBuffer[1]);
mFramesConfigured = true;
}
@@ -599,7 +585,7 @@
uint8_t *bitstreamTmp = bitstream;
uint32_t timestamp = workIndex;
if (PVDecodeVopHeader(
- mDecHandle, &bitstreamTmp, ×tamp, &tmpInSize,
+ &mVideoDecControls, &bitstreamTmp, ×tamp, &tmpInSize,
&header_info, &useExtTimestamp,
mOutputBuffer[mNumSamplesOutput & 1]) != PV_TRUE) {
ALOGE("failed to decode vop header.");
@@ -631,7 +617,7 @@
continue;
}
- if (PVDecodeVopBody(mDecHandle, &tmpInSize) != PV_TRUE) {
+ if (PVDecodeVopBody(&mVideoDecControls, &tmpInSize) != PV_TRUE) {
ALOGE("failed to decode video frame.");
mSignalledError = true;
work->result = C2_CORRUPTED;
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.h b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.h
index 716a095..fed04c9 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.h
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.h
@@ -19,8 +19,8 @@
#include <SimpleC2Component.h>
+#include <mp4dec_api.h>
-struct tagvideoDecControls;
namespace android {
@@ -54,7 +54,7 @@
bool handleResChange(const std::unique_ptr<C2Work> &work);
std::shared_ptr<IntfImpl> mIntf;
- tagvideoDecControls *mDecHandle;
+ tagvideoDecControls mVideoDecControls;
std::shared_ptr<C2GraphicBlock> mOutBlock;
uint8_t *mOutputBuffer[kNumOutputBuffers];
size_t mOutputBufferSize;
diff --git a/media/codec2/components/vpx/C2SoftVpxDec.cpp b/media/codec2/components/vpx/C2SoftVpxDec.cpp
index 2953d90..45e2ca8 100644
--- a/media/codec2/components/vpx/C2SoftVpxDec.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxDec.cpp
@@ -149,8 +149,16 @@
#else
addParameter(
DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
- .withConstValue(new C2StreamProfileLevelInfo::input(0u,
- C2Config::PROFILE_UNUSED, C2Config::LEVEL_UNUSED))
+ .withDefault(new C2StreamProfileLevelInfo::input(0u,
+ C2Config::PROFILE_VP8_0, C2Config::LEVEL_UNUSED))
+ .withFields({
+ C2F(mProfileLevel, profile).equalTo(
+ PROFILE_VP8_0
+ ),
+ C2F(mProfileLevel, level).equalTo(
+ LEVEL_UNUSED),
+ })
+ .withSetter(ProfileLevelSetter, mSize)
.build());
#endif
diff --git a/media/codec2/components/vpx/C2SoftVpxEnc.h b/media/codec2/components/vpx/C2SoftVpxEnc.h
index c98b802..926b2e9 100644
--- a/media/codec2/components/vpx/C2SoftVpxEnc.h
+++ b/media/codec2/components/vpx/C2SoftVpxEnc.h
@@ -324,21 +324,35 @@
.withConstValue(new C2StreamIntraRefreshTuning::output(
0u, C2Config::INTRA_REFRESH_DISABLED, 0.))
.build());
-
+#ifdef VP9
addParameter(
- DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
- .withDefault(new C2StreamProfileLevelInfo::output(
- 0u, PROFILE_VP9_0, LEVEL_VP9_4_1))
- .withFields({
- C2F(mProfileLevel, profile).equalTo(
- PROFILE_VP9_0
- ),
- C2F(mProfileLevel, level).equalTo(
- LEVEL_VP9_4_1),
- })
- .withSetter(ProfileLevelSetter)
- .build());
-
+ DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
+ .withDefault(new C2StreamProfileLevelInfo::output(
+ 0u, PROFILE_VP9_0, LEVEL_VP9_4_1))
+ .withFields({
+ C2F(mProfileLevel, profile).equalTo(
+ PROFILE_VP9_0
+ ),
+ C2F(mProfileLevel, level).equalTo(
+ LEVEL_VP9_4_1),
+ })
+ .withSetter(ProfileLevelSetter)
+ .build());
+#else
+ addParameter(
+ DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
+ .withDefault(new C2StreamProfileLevelInfo::output(
+ 0u, PROFILE_VP8_0, LEVEL_UNUSED))
+ .withFields({
+ C2F(mProfileLevel, profile).equalTo(
+ PROFILE_VP8_0
+ ),
+ C2F(mProfileLevel, level).equalTo(
+ LEVEL_UNUSED),
+ })
+ .withSetter(ProfileLevelSetter)
+ .build());
+#endif
addParameter(
DefineParam(mRequestSync, C2_PARAMKEY_REQUEST_SYNC_FRAME)
.withDefault(new C2StreamRequestSyncFrameTuning::output(0u, C2_FALSE))
diff --git a/media/codec2/hidl/1.0/vts/.clang-format b/media/codec2/hidl/1.0/vts/.clang-format
deleted file mode 120000
index 136279c..0000000
--- a/media/codec2/hidl/1.0/vts/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../../build/soong/scripts/system-clang-format
\ No newline at end of file
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
index c487fa3..1dc037a 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
@@ -81,6 +81,7 @@
mEos = false;
mCsd = false;
mFramesReceived = 0;
+ mEncoderFrameSize = 0;
mWorkResult = C2_OK;
mOutputSize = 0u;
getInputMaxBufSize();
@@ -146,6 +147,7 @@
uint32_t mFramesReceived;
int32_t mInputMaxBufSize;
uint64_t mOutputSize;
+ uint32_t mEncoderFrameSize;
std::list<uint64_t> mFlushedIndices;
C2BlockPool::local_id_t mBlockPoolId;
@@ -304,20 +306,21 @@
c2_status_t c2err = mComponent->query({}, {C2StreamAudioFrameSizeInfo::input::PARAM_TYPE},
C2_DONT_BLOCK, &queried);
size_t offset = sizeof(C2Param);
- uint32_t maxInputSize = 0;
if (c2err == C2_OK && queried.size()) {
C2Param* param = queried[0].get();
- maxInputSize = *(uint32_t*)((uint8_t*)param + offset);
+ mEncoderFrameSize = *(uint32_t*)((uint8_t*)param + offset);
+ if (mEncoderFrameSize) {
+ *samplesPerFrame = mEncoderFrameSize;
+ return C2_OK;
+ }
}
- if (0 == maxInputSize) {
- c2err = mComponent->query({}, {C2StreamMaxBufferSizeInfo::input::PARAM_TYPE}, C2_DONT_BLOCK,
- &queried);
- if (c2err != C2_OK || queried.size() == 0) return c2err;
+ c2err = mComponent->query({}, {C2StreamMaxBufferSizeInfo::input::PARAM_TYPE}, C2_DONT_BLOCK,
+ &queried);
+ if (c2err != C2_OK || queried.size() == 0) return c2err;
- C2Param* param = queried[0].get();
- maxInputSize = *(uint32_t*)((uint8_t*)param + offset);
- }
+ C2Param* param = queried[0].get();
+ uint32_t maxInputSize = *(uint32_t*)((uint8_t*)param + offset);
*samplesPerFrame = std::min((maxInputSize / (nChannels * 2)), kMaxSamplesPerFrame);
return C2_OK;
@@ -450,10 +453,13 @@
ALOGV("EncodeTest");
if (mDisableTest) GTEST_SKIP() << "Test is disabled";
bool signalEOS = std::get<2>(GetParam());
- // Ratio w.r.t to mInputMaxBufSize
- int32_t inputMaxBufRatio = std::get<3>(GetParam());
- mSamplesPerFrame = ((mInputMaxBufSize / inputMaxBufRatio) / (mNumChannels * 2));
-
+ // Set samples per frame based on inputMaxBufRatio if component does not
+ // advertise supported frame size
+ if (!mEncoderFrameSize) {
+ // Ratio w.r.t to mInputMaxBufSize
+ int32_t inputMaxBufRatio = std::get<3>(GetParam());
+ mSamplesPerFrame = ((mInputMaxBufSize / inputMaxBufRatio) / (mNumChannels * 2));
+ }
ALOGV("signalEOS %d mInputMaxBufSize %d mSamplesPerFrame %d", signalEOS, mInputMaxBufSize,
mSamplesPerFrame);
diff --git a/media/libeffects/preprocessing/.clang-format b/media/libeffects/preprocessing/.clang-format
deleted file mode 120000
index f1b4f69..0000000
--- a/media/libeffects/preprocessing/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../build/soong/scripts/system-clang-format
\ No newline at end of file
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 6214f5e..8115880 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -394,11 +394,11 @@
],
static_libs: [
- "resourcemanager_aidl_interface-ndk_platform",
+ "resourcemanager_aidl_interface-ndk",
],
export_static_lib_headers: [
- "resourcemanager_aidl_interface-ndk_platform",
+ "resourcemanager_aidl_interface-ndk",
],
export_include_dirs: [
diff --git a/media/libmediaplayerservice/tests/Android.bp b/media/libmediaplayerservice/tests/Android.bp
index 98626fd..99202b8 100644
--- a/media/libmediaplayerservice/tests/Android.bp
+++ b/media/libmediaplayerservice/tests/Android.bp
@@ -30,7 +30,7 @@
],
static_libs: [
- "resourcemanager_aidl_interface-ndk_platform",
+ "resourcemanager_aidl_interface-ndk",
],
include_dirs: [
diff --git a/media/libmediatranscoding/Android.bp b/media/libmediatranscoding/Android.bp
index 9375e4e..058d0c0 100644
--- a/media/libmediatranscoding/Android.bp
+++ b/media/libmediatranscoding/Android.bp
@@ -58,7 +58,7 @@
export_include_dirs: ["include"],
static_libs: [
- "mediatranscoding_aidl_interface-ndk_platform",
+ "mediatranscoding_aidl_interface-ndk",
],
cflags: [
diff --git a/media/libmediatranscoding/tests/Android.bp b/media/libmediatranscoding/tests/Android.bp
index 17a43df..80a055e 100644
--- a/media/libmediatranscoding/tests/Android.bp
+++ b/media/libmediatranscoding/tests/Android.bp
@@ -25,7 +25,7 @@
],
static_libs: [
- "mediatranscoding_aidl_interface-ndk_platform",
+ "mediatranscoding_aidl_interface-ndk",
],
cflags: [
diff --git a/media/libstagefright/httplive/Android.bp b/media/libstagefright/httplive/Android.bp
index 0b0acbf..7acf735 100644
--- a/media/libstagefright/httplive/Android.bp
+++ b/media/libstagefright/httplive/Android.bp
@@ -29,7 +29,6 @@
],
include_dirs: [
- "frameworks/av/media/libstagefright",
"frameworks/native/include/media/openmax",
],
@@ -65,6 +64,8 @@
header_libs: [
"libbase_headers",
+ "libstagefright_headers",
+ "libstagefright_httplive_headers",
],
static_libs: [
@@ -74,3 +75,8 @@
],
}
+
+cc_library_headers {
+ name: "libstagefright_httplive_headers",
+ export_include_dirs: ["."],
+}
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 3bad015..0d7cadd 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -23,7 +23,7 @@
#include "M3UParser.h"
#include "PlaylistFetcher.h"
-#include "mpeg2ts/AnotherPacketSource.h"
+#include <AnotherPacketSource.h>
#include <cutils/properties.h>
#include <media/MediaHTTPService.h>
diff --git a/media/libstagefright/httplive/LiveSession.h b/media/libstagefright/httplive/LiveSession.h
index 7a6d487..ceea41d 100644
--- a/media/libstagefright/httplive/LiveSession.h
+++ b/media/libstagefright/httplive/LiveSession.h
@@ -24,7 +24,7 @@
#include <utils/String8.h>
-#include "mpeg2ts/ATSParser.h"
+#include <ATSParser.h>
namespace android {
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index b23aa8a..907b326 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -24,9 +24,9 @@
#include "HTTPDownloader.h"
#include "LiveSession.h"
#include "M3UParser.h"
-#include "include/ID3.h"
-#include "mpeg2ts/AnotherPacketSource.h"
-#include "mpeg2ts/HlsSampleDecryptor.h"
+#include <ID3.h>
+#include <AnotherPacketSource.h>
+#include <HlsSampleDecryptor.h>
#include <datasource/DataURISource.h>
#include <media/stagefright/foundation/ABitReader.h>
diff --git a/media/libstagefright/httplive/PlaylistFetcher.h b/media/libstagefright/httplive/PlaylistFetcher.h
index 5d3f9c1..2e28164 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.h
+++ b/media/libstagefright/httplive/PlaylistFetcher.h
@@ -21,7 +21,7 @@
#include <media/stagefright/foundation/AHandler.h>
#include <openssl/aes.h>
-#include "mpeg2ts/ATSParser.h"
+#include <ATSParser.h>
#include "LiveSession.h"
namespace android {
diff --git a/media/libstagefright/httplive/fuzzer/Android.bp b/media/libstagefright/httplive/fuzzer/Android.bp
new file mode 100644
index 0000000..14097b0
--- /dev/null
+++ b/media/libstagefright/httplive/fuzzer/Android.bp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libstagefright_httplive_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_media_libstagefright_httplive_license",
+ ],
+}
+
+cc_fuzz {
+ name: "httplive_fuzzer",
+ srcs: [
+ "httplive_fuzzer.cpp",
+ ],
+ static_libs: [
+ "libstagefright_httplive",
+ "libstagefright_id3",
+ "libstagefright_metadatautils",
+ "libstagefright_mpeg2support",
+ "liblog",
+ "libcutils",
+ "libdatasource",
+ "libmedia",
+ "libstagefright",
+ "libutils",
+ ],
+ header_libs: [
+ "libbase_headers",
+ "libstagefright_foundation_headers",
+ "libstagefright_headers",
+ "libstagefright_httplive_headers",
+ ],
+ shared_libs: [
+ "libcrypto",
+ "libstagefright_foundation",
+ "libhidlbase",
+ "libhidlmemory",
+ "android.hidl.allocator@1.0",
+ ],
+ corpus: ["corpus/*"],
+ dictionary: "httplive_fuzzer.dict",
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
diff --git a/media/libstagefright/httplive/fuzzer/README.md b/media/libstagefright/httplive/fuzzer/README.md
new file mode 100644
index 0000000..3a64ea4
--- /dev/null
+++ b/media/libstagefright/httplive/fuzzer/README.md
@@ -0,0 +1,56 @@
+# Fuzzer for libstagefright_httplive
+
+## Plugin Design Considerations
+The fuzzer plugin for libstagefright_httplive is designed based on the understanding of the library and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data.Also, several .m3u8 files are hand-crafted and added to the corpus directory to increase the code coverage. This ensures more code paths are reached by the fuzzer.
+
+libstagefright_httplive supports the following parameters:
+1. Final Result (parameter name: `finalResult`)
+2. Flags (parameter name: `flags`)
+3. Time Us (parameter name: `timeUs`)
+4. Track Index (parameter name: `trackIndex`)
+5. Index (parameter name: `index`)
+6. Select (parameter name: `select`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `finalResult` | `-34` to `-1` | Value obtained from FuzzedDataProvider|
+| `flags` | `0` to `1` | Value obtained from FuzzedDataProvider|
+| `timeUs` | `0` to `10000000` | Value obtained from FuzzedDataProvider|
+| `trackIndex` | `UINT32_MIN` to `UINT32_MAX` | Value obtained from FuzzedDataProvider|
+| `index` | `UINT32_MIN` to `UINT32_MAX` | Value obtained from FuzzedDataProvider|
+| `select` | `True` to `False` | Value obtained from FuzzedDataProvider|
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin feeds the entire input data to the httplive module.
+This ensures that the plugin tolerates any kind of input (empty, huge,
+malformed, etc) and doesnt `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build httplive_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+ $ mm -j$(nproc) httplive_fuzzer
+```
+#### Steps to run
+To run on device
+```
+ $ adb push $ANDROID_PRODUCT_OUT/data/fuzz/$(TARGET_ARCH)/lib /data/fuzz/$(TARGET_ARCH)/lib
+ $ adb push $ANDROID_PRODUCT_OUT/data/fuzz/$(TARGET_ARCH)/httplive_fuzzer /data/fuzz/$(TARGET_ARCH)/httplive_fuzzer
+ $ adb shell /data/fuzz/${TARGET_ARCH}/httplive_fuzzer/httplive_fuzzer /data/fuzz/${TARGET_ARCH}/httplive_fuzzer/corpus
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/media/libstagefright/httplive/fuzzer/corpus/crypt.key b/media/libstagefright/httplive/fuzzer/corpus/crypt.key
new file mode 100644
index 0000000..f9d5d7f
--- /dev/null
+++ b/media/libstagefright/httplive/fuzzer/corpus/crypt.key
@@ -0,0 +1,2 @@
+Û
+ÏüÐ5Ð_xïHÎ3
diff --git a/media/libstagefright/httplive/fuzzer/corpus/encrypted.m3u8 b/media/libstagefright/httplive/fuzzer/corpus/encrypted.m3u8
new file mode 100644
index 0000000..32b0eac
--- /dev/null
+++ b/media/libstagefright/httplive/fuzzer/corpus/encrypted.m3u8
@@ -0,0 +1,12 @@
+#EXTM3U
+#EXT-X-TARGETDURATION:10
+#EXT-X-ALLOW-CACHE:YES
+#EXT-X-PLAYLIST-TYPE:VOD
+#EXT-X-VERSION:3
+#EXT-X-MEDIA-SEQUENCE:1
+#EXT-X-KEY:METHOD=AES-128,URI="../../fuzz/arm64/httplive_fuzzer/corpus/crypt.key"
+#EXTINF:10.000,
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence1.ts
+#EXTINF:5.092,
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence1.ts
+#EXT-X-ENDLIST
diff --git a/media/libstagefright/httplive/fuzzer/corpus/hls.m3u8 b/media/libstagefright/httplive/fuzzer/corpus/hls.m3u8
new file mode 100644
index 0000000..9338e04
--- /dev/null
+++ b/media/libstagefright/httplive/fuzzer/corpus/hls.m3u8
@@ -0,0 +1,8 @@
+#EXTM3U
+#EXT-X-TARGETDURATION:10
+#EXT-X-MEDIA-SEQUENCE:0
+#EXTINF:10, no desc
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence1.ts
+#EXTINF:10, no desc
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence2.ts
+#EXT-X-ENDLIST
diff --git a/media/libstagefright/httplive/fuzzer/corpus/index1.m3u8 b/media/libstagefright/httplive/fuzzer/corpus/index1.m3u8
new file mode 100644
index 0000000..e1eff58
--- /dev/null
+++ b/media/libstagefright/httplive/fuzzer/corpus/index1.m3u8
@@ -0,0 +1,14 @@
+#EXTM3U
+#EXT-X-VERSION:4
+#EXT-X-TARGETDURATION:5
+#EXT-X-KEY:METHOD=NONE
+#EXT-X-DISCONTINUITY-SEQUENCE:0
+#EXT-X-PLAYLIST-TYPE:VOD
+#EXTINF:5,
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence0.ts
+#EXT-X-DISCONTINUITY
+#EXTINF:5,
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence1.ts
+#EXTINF:5,
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence2.ts
+#EXT-X-ENDLIST
diff --git a/media/libstagefright/httplive/fuzzer/corpus/index2.m3u8 b/media/libstagefright/httplive/fuzzer/corpus/index2.m3u8
new file mode 100644
index 0000000..37a0189
--- /dev/null
+++ b/media/libstagefright/httplive/fuzzer/corpus/index2.m3u8
@@ -0,0 +1,6 @@
+#EXTM3U
+#EXT-X-INDEPENDENT-SEGMENTS
+#EXT-X-STREAM-INF:CLOSED-CAPTIONS=NONE,BANDWIDTH=165340,RESOLUTION=256x144,CODECS="mp4a.40.5,avc1.42c00b"
+https://non.existentsite.com/test-doesnt-dereference-these-paths/prog_index.m3u8
+#EXT-X-STREAM-INF:CLOSED-CAPTIONS=NONE,BANDWIDTH=344388,RESOLUTION=426x240,CODECS="mp4a.40.5,avc1.4d4015"
+https://non.existentsite.com/test-doesnt-dereference-these-paths/prog_index1.m3u8
diff --git a/media/libstagefright/httplive/fuzzer/corpus/index3.m3u8 b/media/libstagefright/httplive/fuzzer/corpus/index3.m3u8
new file mode 100644
index 0000000..1b7f489
--- /dev/null
+++ b/media/libstagefright/httplive/fuzzer/corpus/index3.m3u8
@@ -0,0 +1,13 @@
+#EXTM3U
+#EXT-X-VERSION:4
+#EXT-X-TARGETDURATION:5
+#EXT-X-KEY:METHOD=AES-128,URI="https://demo.unified-streaming.com/video/tears-of-steel/aes.key",IV=0X99b74007b6254e4bd1c6e03631cad15b
+#EXT-X-PLAYLIST-TYPE:VOD
+#EXTINF:5,
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence1.ts
+#EXT-X-DISCONTINUITY
+#EXTINF:5,
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence2.ts
+#EXTINF:5,
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence3.ts
+#EXT-X-ENDLIST
diff --git a/media/libstagefright/httplive/fuzzer/corpus/index4.m3u8 b/media/libstagefright/httplive/fuzzer/corpus/index4.m3u8
new file mode 100644
index 0000000..89ba37c
--- /dev/null
+++ b/media/libstagefright/httplive/fuzzer/corpus/index4.m3u8
@@ -0,0 +1,15 @@
+#EXTM3U
+#EXT-X-VERSION:4
+#EXT-X-TARGETDURATION:5
+#EXT-X-KEY:METHOD=SAMPLE-AES,URI="data:text/plain;charset=utf-8,a4cd9995a1aa91e1",IV=0X99b74007b6254e4bd1c6e03631cad15b
+#EXT-X-DISCONTINUITY-SEQUENCE:0
+#EXT-X-PLAYLIST-TYPE:VOD
+#EXT-X-DISCONTINUITY
+#EXTINF:5,
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence0.ts
+#EXTINF:5,
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence1.ts
+#EXT-X-DISCONTINUITY
+#EXTINF:5,
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence2.ts
+#EXT-X-ENDLIST
diff --git a/media/libstagefright/httplive/fuzzer/corpus/index5.m3u8 b/media/libstagefright/httplive/fuzzer/corpus/index5.m3u8
new file mode 100644
index 0000000..2120de4
--- /dev/null
+++ b/media/libstagefright/httplive/fuzzer/corpus/index5.m3u8
@@ -0,0 +1,14 @@
+#EXTM3U
+#EXT-X-TARGETDURATION:11
+#EXT-X-KEY:METHOD=NONE
+#EXT-X-MEDIA-SEQUENCE:0
+#EXT-X-VERSION:4
+#EXTINF:10.0,
+#EXT-X-BYTERANGE:10@0
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence1.ts
+#EXTINF:10.0,
+#EXT-X-BYTERANGE:20@10
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence1.ts
+#EXTINF:10.0,
+#EXT-X-BYTERANGE:80
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence1.ts
diff --git a/media/libstagefright/httplive/fuzzer/corpus/index6.m3u8 b/media/libstagefright/httplive/fuzzer/corpus/index6.m3u8
new file mode 100644
index 0000000..588368a
--- /dev/null
+++ b/media/libstagefright/httplive/fuzzer/corpus/index6.m3u8
@@ -0,0 +1,12 @@
+#EXTM3U
+#EXT-X-VERSION:4
+#EXT-X-TARGETDURATION:5
+#EXT-X-KEY:METHOD=AES-128,URI="data:text/plain;charset=utf-8,a4cd9995a1aa91e1",IV=0x30303030303030303030303030303030
+#EXT-X-PLAYLIST-TYPE:VOD
+#EXTINF:5,
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence1.ts
+#EXTINF:5,
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence2.ts
+#EXTINF:5,
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence3.ts
+#EXT-X-ENDLIST
diff --git a/media/libstagefright/httplive/fuzzer/corpus/index7.m3u8 b/media/libstagefright/httplive/fuzzer/corpus/index7.m3u8
new file mode 100644
index 0000000..b09948e
--- /dev/null
+++ b/media/libstagefright/httplive/fuzzer/corpus/index7.m3u8
@@ -0,0 +1,46 @@
+#EXTM3U
+#EXT-X-VERSION:4
+## Created with Unified Streaming Platform (version=1.11.3-24438)
+#EXT-X-SESSION-KEY:METHOD=AES-128,URI="https://demo.unified-streaming.com/video/tears-of-steel/aes.key"
+
+# AUDIO groups
+#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-aacl-64",LANGUAGE="en",NAME="English",DEFAULT=YES,AUTOSELECT=YES,CHANNELS="2"
+#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-aacl-128",LANGUAGE="en",NAME="English",DEFAULT=YES,AUTOSELECT=YES,CHANNELS="2"
+
+# SUBTITLES groups
+#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="textstream",LANGUAGE="en",NAME="English",DEFAULT=YES,AUTOSELECT=YES,URI="tears-of-steel-aes-textstream_eng=1000.m3u8"
+#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="textstream",LANGUAGE="ru",NAME="Russian",AUTOSELECT=YES,URI="tears-of-steel-aes-textstream_rus=1000.m3u8"
+
+# variants
+#EXT-X-STREAM-INF:BANDWIDTH=494000,CODECS="mp4a.40.2,avc1.42C00D",RESOLUTION=224x100,FRAME-RATE=24,AUDIO="audio-aacl-64",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
+tears-of-steel-aes-audio_eng=64008-video_eng=401000.m3u8
+#EXT-X-STREAM-INF:BANDWIDTH=933000,CODECS="mp4a.40.2,avc1.42C016",RESOLUTION=448x200,FRAME-RATE=24,AUDIO="audio-aacl-128",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
+tears-of-steel-aes-audio_eng=128002-video_eng=751000.m3u8
+#EXT-X-STREAM-INF:BANDWIDTH=1198000,CODECS="mp4a.40.2,avc1.4D401F",RESOLUTION=784x350,FRAME-RATE=24,AUDIO="audio-aacl-128",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
+tears-of-steel-aes-audio_eng=128002-video_eng=1001000.m3u8
+#EXT-X-STREAM-INF:BANDWIDTH=1728000,CODECS="mp4a.40.2,avc1.640028",RESOLUTION=1680x750,FRAME-RATE=24,VIDEO-RANGE=SDR,AUDIO="audio-aacl-128",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
+tears-of-steel-aes-audio_eng=128002-video_eng=1501000.m3u8
+#EXT-X-STREAM-INF:BANDWIDTH=2469000,CODECS="mp4a.40.2,avc1.640028",RESOLUTION=1680x750,FRAME-RATE=24,VIDEO-RANGE=SDR,AUDIO="audio-aacl-128",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
+tears-of-steel-aes-audio_eng=128002-video_eng=2200000.m3u8
+
+# variants
+#EXT-X-STREAM-INF:BANDWIDTH=1025000,CODECS="mp4a.40.2,hvc1.1.6.L150.90",RESOLUTION=1680x750,FRAME-RATE=24,VIDEO-RANGE=SDR,AUDIO="audio-aacl-64",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
+tears-of-steel-aes-audio_eng=64008-video_eng_1=902000.m3u8
+#EXT-X-STREAM-INF:BANDWIDTH=1368000,CODECS="mp4a.40.2,hvc1.1.6.L150.90",RESOLUTION=2576x1150,FRAME-RATE=24,VIDEO-RANGE=SDR,AUDIO="audio-aacl-128",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
+tears-of-steel-aes-audio_eng=128002-video_eng_1=1161000.m3u8
+#EXT-X-STREAM-INF:BANDWIDTH=1815000,CODECS="mp4a.40.2,hvc1.1.6.L150.90",RESOLUTION=3360x1500,FRAME-RATE=24,VIDEO-RANGE=SDR,AUDIO="audio-aacl-128",SUBTITLES="textstream",CLOSED-CAPTIONS=NONE
+tears-of-steel-aes-audio_eng=128002-video_eng_1=1583000.m3u8
+
+# variants
+#EXT-X-STREAM-INF:BANDWIDTH=69000,CODECS="mp4a.40.2",AUDIO="audio-aacl-64",SUBTITLES="textstream"
+tears-of-steel-aes-audio_eng=64008.m3u8
+#EXT-X-STREAM-INF:BANDWIDTH=137000,CODECS="mp4a.40.2",AUDIO="audio-aacl-128",SUBTITLES="textstream"
+tears-of-steel-aes-audio_eng=128002.m3u8
+
+# keyframes
+#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=54000,CODECS="avc1.42C00D",RESOLUTION=224x100,URI="keyframes/tears-of-steel-aes-video_eng=401000.m3u8"
+#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=100000,CODECS="avc1.42C016",RESOLUTION=448x200,URI="keyframes/tears-of-steel-aes-video_eng=751000.m3u8"
+#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=133000,CODECS="avc1.4D401F",RESOLUTION=784x350,URI="keyframes/tears-of-steel-aes-video_eng=1001000.m3u8"
+#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=120000,CODECS="hvc1.1.6.L150.90",RESOLUTION=1680x750,VIDEO-RANGE=SDR,URI="keyframes/tears-of-steel-aes-video_eng_1=902000.m3u8"
+#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=154000,CODECS="hvc1.1.6.L150.90",RESOLUTION=2576x1150,VIDEO-RANGE=SDR,URI="keyframes/tears-of-steel-aes-video_eng_1=1161000.m3u8"
+#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=210000,CODECS="hvc1.1.6.L150.90",RESOLUTION=3360x1500,VIDEO-RANGE=SDR,URI="keyframes/tears-of-steel-aes-video_eng_1=1583000.m3u8"
diff --git a/media/libstagefright/httplive/fuzzer/corpus/index8.m3u8 b/media/libstagefright/httplive/fuzzer/corpus/index8.m3u8
new file mode 100644
index 0000000..353d589
--- /dev/null
+++ b/media/libstagefright/httplive/fuzzer/corpus/index8.m3u8
@@ -0,0 +1,13 @@
+#EXTM3U
+#EXT-X-VERSION:5
+
+#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="English stereo",LANGUAGE="en",AUTOSELECT=YES,URI="../../fuzz/arm64/httplive_fuzzer/index1.m3u8"
+
+#EXT-X-STREAM-INF:BANDWIDTH=628000,CODECS="avc1.42c00d,mp4a.40.2",RESOLUTION=320x180,AUDIO="audio"
+../../fuzz/arm64/httplive_fuzzer/index1.m3u8
+#EXT-X-STREAM-INF:BANDWIDTH=928000,CODECS="avc1.42c00d,mp4a.40.2",RESOLUTION=480x270,AUDIO="audio"
+../../fuzz/arm64/httplive_fuzzer/index2.m3u8
+#EXT-X-STREAM-INF:BANDWIDTH=1728000,CODECS="avc1.42c00d,mp4a.40.2",RESOLUTION=640x360,AUDIO="audio"
+../../fuzz/arm64/httplive_fuzzer/index3.m3u8
+#EXT-X-STREAM-INF:BANDWIDTH=2528000,CODECS="avc1.42c00d,mp4a.40.2",RESOLUTION=960x540,AUDIO="audio"
+../../fuzz/arm64/httplive_fuzzer/index1.m3u8
diff --git a/media/libstagefright/httplive/fuzzer/corpus/prog_index.m3u8 b/media/libstagefright/httplive/fuzzer/corpus/prog_index.m3u8
new file mode 100644
index 0000000..eb88422
--- /dev/null
+++ b/media/libstagefright/httplive/fuzzer/corpus/prog_index.m3u8
@@ -0,0 +1,17 @@
+#EXTM3U
+#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",LANGUAGE="eng",NAME="English",AUTOSELECT=YES,DEFAULT=YES,URI="corpus/index1.m3u8"
+#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",LANGUAGE="fre",NAME="Français",AUTOSELECT=YES,DEFAULT=NO,URI="corpus/index1.m3u8"
+#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",LANGUAGE="sp",NAME="Espanol",AUTOSELECT=YES,DEFAULT=NO,URI="corpus/index1.m3u8"
+#EXT-X-VERSION:4
+#EXT-X-TARGETDURATION:5
+#EXT-X-KEY:METHOD=NONE
+#EXT-X-DISCONTINUITY-SEQUENCE:0
+#EXT-X-PLAYLIST-TYPE:VOD
+#EXTINF:5,
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence1.ts
+#EXT-X-DISCONTINUITY
+#EXTINF:5,
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence1.ts
+#EXTINF:5,
+https://non.existentsite.com/test-doesnt-dereference-these-paths/fileSequence1.ts
+#EXT-X-ENDLIST
diff --git a/media/libstagefright/httplive/fuzzer/httplive_fuzzer.cpp b/media/libstagefright/httplive/fuzzer/httplive_fuzzer.cpp
new file mode 100644
index 0000000..aa777b3
--- /dev/null
+++ b/media/libstagefright/httplive/fuzzer/httplive_fuzzer.cpp
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#include <fstream>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <LiveDataSource.h>
+#include <LiveSession.h>
+#include <media/MediaHTTPConnection.h>
+#include <media/MediaHTTPService.h>
+#include <media/mediaplayer_common.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/ALooperRoster.h>
+#include <string>
+#include <utils/Log.h>
+
+using namespace std;
+using namespace android;
+
+constexpr char kFileNamePrefix[] = "/data/local/tmp/httplive-";
+constexpr char kFileNameSuffix[] = ".m3u8";
+constexpr char kFileUrlPrefix[] = "file://";
+constexpr int64_t kOffSet = 0;
+constexpr int32_t kReadyMarkMs = 5000;
+constexpr int32_t kPrepareMarkMs = 1500;
+constexpr int32_t kErrorNoMax = -1;
+constexpr int32_t kErrorNoMin = -34;
+constexpr int32_t kMaxTimeUs = 1000;
+constexpr int32_t kRandomStringLength = 64;
+constexpr int32_t kRangeMin = 0;
+constexpr int32_t kRangeMax = 1000;
+
+constexpr LiveSession::StreamType kValidStreamType[] = {
+ LiveSession::STREAMTYPE_AUDIO, LiveSession::STREAMTYPE_VIDEO,
+ LiveSession::STREAMTYPE_SUBTITLES, LiveSession::STREAMTYPE_METADATA};
+
+constexpr MediaSource::ReadOptions::SeekMode kValidSeekMode[] = {
+ MediaSource::ReadOptions::SeekMode::SEEK_PREVIOUS_SYNC,
+ MediaSource::ReadOptions::SeekMode::SEEK_NEXT_SYNC,
+ MediaSource::ReadOptions::SeekMode::SEEK_CLOSEST_SYNC,
+ MediaSource::ReadOptions::SeekMode::SEEK_CLOSEST,
+ MediaSource::ReadOptions::SeekMode::SEEK_FRAME_INDEX};
+
+constexpr media_track_type kValidMediaTrackType[] = {
+ MEDIA_TRACK_TYPE_UNKNOWN, MEDIA_TRACK_TYPE_VIDEO,
+ MEDIA_TRACK_TYPE_AUDIO, MEDIA_TRACK_TYPE_TIMEDTEXT,
+ MEDIA_TRACK_TYPE_SUBTITLE, MEDIA_TRACK_TYPE_METADATA};
+
+struct TestAHandler : public AHandler {
+public:
+ TestAHandler(std::function<void()> signalEosFunction)
+ : mSignalEosFunction(signalEosFunction) {}
+ virtual ~TestAHandler() {}
+
+protected:
+ void onMessageReceived(const sp<AMessage> &msg) override {
+ int32_t what = -1;
+ msg->findInt32("what", &what);
+ switch (what) {
+ case LiveSession::kWhatError:
+ case LiveSession::kWhatPrepared:
+ case LiveSession::kWhatPreparationFailed: {
+ mSignalEosFunction();
+ break;
+ }
+ }
+ return;
+ }
+
+private:
+ std::function<void()> mSignalEosFunction;
+};
+
+struct TestMediaHTTPConnection : public MediaHTTPConnection {
+public:
+ TestMediaHTTPConnection() {}
+ virtual ~TestMediaHTTPConnection() {}
+
+ virtual bool connect(const char * /*uri*/,
+ const KeyedVector<String8, String8> * /*headers*/) {
+ return true;
+ }
+
+ virtual void disconnect() { return; }
+
+ virtual ssize_t readAt(off64_t /*offset*/, void * /*data*/, size_t size) {
+ return size;
+ }
+
+ virtual off64_t getSize() { return 0; }
+ virtual status_t getMIMEType(String8 * /*mimeType*/) { return NO_ERROR; }
+ virtual status_t getUri(String8 * /*uri*/) { return NO_ERROR; }
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(TestMediaHTTPConnection);
+};
+
+struct TestMediaHTTPService : public MediaHTTPService {
+public:
+ TestMediaHTTPService() {}
+ ~TestMediaHTTPService(){};
+
+ virtual sp<MediaHTTPConnection> makeHTTPConnection() {
+ mediaHTTPConnection = sp<TestMediaHTTPConnection>::make();
+ return mediaHTTPConnection;
+ }
+
+private:
+ sp<TestMediaHTTPConnection> mediaHTTPConnection = nullptr;
+ DISALLOW_EVIL_CONSTRUCTORS(TestMediaHTTPService);
+};
+
+class HttpLiveFuzzer {
+public:
+ void process(const uint8_t *data, size_t size);
+ void deInitLiveSession();
+ ~HttpLiveFuzzer() { deInitLiveSession(); }
+
+private:
+ void invokeLiveDataSource();
+ void createM3U8File(const uint8_t *data, size_t size);
+ void initLiveDataSource();
+ void invokeLiveSession();
+ void initLiveSession();
+ void invokeDequeueAccessUnit();
+ void invokeConnectAsync();
+ void invokeSeekTo();
+ void invokeGetConfig();
+ void signalEos();
+ string generateFileName();
+ sp<LiveDataSource> mLiveDataSource = nullptr;
+ sp<LiveSession> mLiveSession = nullptr;
+ sp<ALooper> mLiveLooper = nullptr;
+ sp<TestMediaHTTPService> httpService = nullptr;
+ sp<TestAHandler> mHandler = nullptr;
+ FuzzedDataProvider *mFDP = nullptr;
+ bool mEosReached = false;
+ std::mutex mDownloadCompleteMutex;
+ std::condition_variable mConditionalVariable;
+};
+
+string HttpLiveFuzzer::generateFileName() {
+ return kFileNamePrefix + to_string(getpid()) + kFileNameSuffix;
+}
+
+void HttpLiveFuzzer::createM3U8File(const uint8_t *data, size_t size) {
+ ofstream m3u8File;
+ string currentFileName = generateFileName();
+ m3u8File.open(currentFileName, ios::out | ios::binary);
+ m3u8File.write((char *)data, size);
+ m3u8File.close();
+}
+
+void HttpLiveFuzzer::initLiveDataSource() {
+ mLiveDataSource = sp<LiveDataSource>::make();
+}
+
+void HttpLiveFuzzer::invokeLiveDataSource() {
+ initLiveDataSource();
+ size_t size = mFDP->ConsumeIntegralInRange<size_t>(kRangeMin, kRangeMax);
+ sp<ABuffer> buffer = new ABuffer(size);
+ mLiveDataSource->queueBuffer(buffer);
+ uint8_t *data = new uint8_t[size];
+ mLiveDataSource->readAtNonBlocking(kOffSet, data, size);
+ int32_t finalResult = mFDP->ConsumeIntegralInRange(kErrorNoMin, kErrorNoMax);
+ mLiveDataSource->queueEOS(finalResult);
+ mLiveDataSource->reset();
+ mLiveDataSource->countQueuedBuffers();
+ mLiveDataSource->initCheck();
+ delete[] data;
+}
+
+void HttpLiveFuzzer::initLiveSession() {
+ ALooperRoster looperRoster;
+ mHandler =
+ sp<TestAHandler>::make(std::bind(&HttpLiveFuzzer::signalEos, this));
+ mLiveLooper = sp<ALooper>::make();
+ mLiveLooper->setName("http live");
+ mLiveLooper->start();
+ sp<AMessage> notify = sp<AMessage>::make(0, mHandler);
+ httpService = new TestMediaHTTPService();
+ uint32_t flags = mFDP->ConsumeIntegral<uint32_t>();
+ mLiveSession = sp<LiveSession>::make(notify, flags, httpService);
+ mLiveLooper->registerHandler(mLiveSession);
+ looperRoster.registerHandler(mLiveLooper, mHandler);
+}
+
+void HttpLiveFuzzer::invokeDequeueAccessUnit() {
+ LiveSession::StreamType stream = mFDP->PickValueInArray(kValidStreamType);
+ sp<ABuffer> buffer;
+ mLiveSession->dequeueAccessUnit(stream, &buffer);
+}
+
+void HttpLiveFuzzer::invokeSeekTo() {
+ int64_t timeUs = mFDP->ConsumeIntegralInRange<int64_t>(0, kMaxTimeUs);
+ MediaSource::ReadOptions::SeekMode mode =
+ mFDP->PickValueInArray(kValidSeekMode);
+ mLiveSession->seekTo(timeUs, mode);
+}
+
+void HttpLiveFuzzer::invokeGetConfig() {
+ mLiveSession->getTrackCount();
+ size_t trackIndex = mFDP->ConsumeIntegral<size_t>();
+ mLiveSession->getTrackInfo(trackIndex);
+ media_track_type type = mFDP->PickValueInArray(kValidMediaTrackType);
+ mLiveSession->getSelectedTrack(type);
+ sp<MetaData> meta;
+ LiveSession::StreamType stream = mFDP->PickValueInArray(kValidStreamType);
+ mLiveSession->getStreamFormatMeta(stream, &meta);
+ mLiveSession->getKeyForStream(stream);
+ if (stream != LiveSession::STREAMTYPE_SUBTITLES) {
+ mLiveSession->getSourceTypeForStream(stream);
+ }
+}
+
+void HttpLiveFuzzer::invokeConnectAsync() {
+ string currentFileName = generateFileName();
+ string url = kFileUrlPrefix + currentFileName;
+ string str_1 = mFDP->ConsumeRandomLengthString(kRandomStringLength);
+ string str_2 = mFDP->ConsumeRandomLengthString(kRandomStringLength);
+
+ KeyedVector<String8, String8> headers;
+ headers.add(String8(str_1.c_str()), String8(str_2.c_str()));
+ mLiveSession->connectAsync(url.c_str(), &headers);
+}
+
+void HttpLiveFuzzer::invokeLiveSession() {
+ initLiveSession();
+ BufferingSettings bufferingSettings;
+ bufferingSettings.mInitialMarkMs = kPrepareMarkMs;
+ bufferingSettings.mResumePlaybackMarkMs = kReadyMarkMs;
+ mLiveSession->setBufferingSettings(bufferingSettings);
+ invokeConnectAsync();
+ std::unique_lock waitForDownloadComplete(mDownloadCompleteMutex);
+ mConditionalVariable.wait(waitForDownloadComplete,
+ [this] { return mEosReached; });
+ if (mLiveSession->isSeekable()) {
+ invokeSeekTo();
+ }
+ invokeDequeueAccessUnit();
+ size_t index = mFDP->ConsumeIntegral<size_t>();
+ bool select = mFDP->ConsumeBool();
+ mLiveSession->selectTrack(index, select);
+ mLiveSession->hasDynamicDuration();
+ int64_t firstTimeUs =
+ mFDP->ConsumeIntegralInRange<int64_t>(kRangeMin, kRangeMax);
+ int64_t timeUs = mFDP->ConsumeIntegralInRange<int64_t>(kRangeMin, kRangeMax);
+ int32_t discontinuitySeq = mFDP->ConsumeIntegral<int32_t>();
+ mLiveSession->calculateMediaTimeUs(firstTimeUs, timeUs, discontinuitySeq);
+ invokeGetConfig();
+}
+
+void HttpLiveFuzzer::process(const uint8_t *data, size_t size) {
+ mFDP = new FuzzedDataProvider(data, size);
+ createM3U8File(data, size);
+ invokeLiveDataSource();
+ invokeLiveSession();
+ delete mFDP;
+}
+
+void HttpLiveFuzzer::deInitLiveSession() {
+ if (mLiveSession != nullptr) {
+ mLiveSession->disconnect();
+ mLiveLooper->unregisterHandler(mLiveSession->id());
+ mLiveLooper->stop();
+ }
+ mLiveSession.clear();
+ mLiveLooper.clear();
+}
+
+void HttpLiveFuzzer::signalEos() {
+ mEosReached = true;
+ {
+ std::lock_guard<std::mutex> waitForDownloadComplete(mDownloadCompleteMutex);
+ }
+ mConditionalVariable.notify_one();
+ return;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ HttpLiveFuzzer httpliveFuzzer;
+ httpliveFuzzer.process(data, size);
+ return 0;
+}
diff --git a/media/libstagefright/httplive/fuzzer/httplive_fuzzer.dict b/media/libstagefright/httplive/fuzzer/httplive_fuzzer.dict
new file mode 100644
index 0000000..703cc7e
--- /dev/null
+++ b/media/libstagefright/httplive/fuzzer/httplive_fuzzer.dict
@@ -0,0 +1,15 @@
+#m3u8-Tags
+kw1="#EXTM3U"
+kw2="#EXT-X-VERSION:"
+kw3="#EXT-X-TARGETDURATION:"
+kw4="#EXT-X-PLAYLIST-TYPE:"
+kw5="#EXTINF:"
+kw6="#EXT-X-ENDLIST"
+kw7="#EXT-X-MEDIA-SEQUENCE:"
+kw8="#EXT-X-KEY:METHOD=NONE"
+kw9="#EXT-X-DISCONTINUITY:"
+kw10="#EXT-X-DISCONTINUITY-SEQUENCE:0"
+kw11="#EXT-X-STREAM-INF:BANDWIDTH="
+kw12="#EXT-X-STREAM-INF:CODECS="
+kw13="#EXT-X-BYTERANGE:"
+kw14="#EXT-X-MEDIA"
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index 74acdda..0bd342a 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -467,14 +467,16 @@
if (err == -ECONNRESET) {
// socket failure, this stream is dead, Jim.
- sp<AMessage> notify = it->mNotifyMsg->dup();
- notify->setInt32("rtcp-event", 1);
- notify->setInt32("payload-type", 400);
- notify->setInt32("feedback-type", 1);
- notify->setInt32("sender", it->mSources.valueAt(0)->getSelfID());
- notify->post();
+ for (size_t i = 0; i < it->mSources.size(); ++i) {
+ sp<AMessage> notify = it->mNotifyMsg->dup();
+ notify->setInt32("rtcp-event", 1);
+ notify->setInt32("payload-type", 400);
+ notify->setInt32("feedback-type", 1);
+ notify->setInt32("sender", it->mSources.valueAt(i)->getSelfID());
+ notify->post();
- ALOGW("failed to receive RTP/RTCP datagram.");
+ ALOGW("failed to receive RTP/RTCP datagram.");
+ }
it = mStreams.erase(it);
continue;
}
@@ -506,8 +508,6 @@
if (n != (ssize_t)buffer->size()) {
ALOGW("failed to send RTCP TMMBR (%s).",
n >= 0 ? "connection gone" : strerror(errno));
-
- it = mStreams.erase(it);
continue;
}
}
@@ -558,8 +558,6 @@
if (n != (ssize_t)buffer->size()) {
ALOGW("failed to send RTCP receiver report (%s).",
n >= 0 ? "connection gone" : strerror(errno));
-
- it = mStreams.erase(it);
continue;
}
@@ -619,7 +617,14 @@
} while (nbytes < 0 && errno == EINTR);
if (nbytes <= 0) {
- return -ECONNRESET;
+ ALOGW("failed to recv rtp packet. cause=%s", strerror(errno));
+ // ECONNREFUSED may happen in next recvfrom() calling if one of
+ // outgoing packet can not be delivered to remote by using sendto()
+ if (errno == ECONNREFUSED) {
+ return -ECONNREFUSED;
+ } else {
+ return -ECONNRESET;
+ }
}
buffer->setRange(0, nbytes);
@@ -663,6 +668,10 @@
pRemoteRTCPAddr, sizeSockSt);
} while (n < 0 && errno == EINTR);
+ if (n < 0) {
+ ALOGW("failed to send rtcp packet. cause=%s", strerror(errno));
+ }
+
return n;
}
diff --git a/services/mediatranscoding/Android.bp b/services/mediatranscoding/Android.bp
index a895071..6c390c8 100644
--- a/services/mediatranscoding/Android.bp
+++ b/services/mediatranscoding/Android.bp
@@ -32,7 +32,7 @@
],
static_libs: [
- "mediatranscoding_aidl_interface-ndk_platform",
+ "mediatranscoding_aidl_interface-ndk",
],
cflags: [
@@ -60,7 +60,7 @@
],
static_libs: [
- "mediatranscoding_aidl_interface-ndk_platform",
+ "mediatranscoding_aidl_interface-ndk",
],
init_rc: ["mediatranscoding.rc"],
diff --git a/services/mediatranscoding/tests/Android.bp b/services/mediatranscoding/tests/Android.bp
index a856c05..9b18d43 100644
--- a/services/mediatranscoding/tests/Android.bp
+++ b/services/mediatranscoding/tests/Android.bp
@@ -34,7 +34,7 @@
],
static_libs: [
- "mediatranscoding_aidl_interface-ndk_platform",
+ "mediatranscoding_aidl_interface-ndk",
],
}