Merge "liboboe: initial checkin of the Oboe header files"
diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp
index 8fe1dd4..76dbb78 100644
--- a/cmds/stagefright/sf2.cpp
+++ b/cmds/stagefright/sf2.cpp
@@ -230,7 +230,8 @@
mCodec->signalResume();
(new AMessage(kWhatSeek, this))->post(5000000ll);
- } else if (what == CodecBase::kWhatShutdownCompleted) {
+ } else if (what == CodecBase::kWhatStopCompleted ||
+ what == CodecBase::kWhatReleaseCompleted) {
mDecodeLooper->unregisterHandler(mCodec->id());
if (mDecodeLooper != looper()) {
diff --git a/include/drm/drm_framework_common.h b/include/drm/drm_framework_common.h
index 0750406..d75f71c 100644
--- a/include/drm/drm_framework_common.h
+++ b/include/drm/drm_framework_common.h
@@ -234,10 +234,6 @@
* POSIX based Decrypt API set for container based DRM
*/
static const int CONTAINER_BASED = 0x02;
- /**
- * Decrypt API for Widevine streams
- */
- static const int WV_BASED = 0x3;
};
/**
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index edcca64..99ef59f 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -23,6 +23,8 @@
#include <utils/KeyedVector.h>
#include <system/audio.h>
+#include <media/IMediaSource.h>
+
// Fwd decl to make sure everyone agrees that the scope of struct sockaddr_in is
// global, and not in android::
struct sockaddr_in;
@@ -38,6 +40,8 @@
struct AudioPlaybackRate;
struct AVSyncSettings;
+typedef IMediaSource::ReadOptions::SeekMode MediaPlayerSeekMode;
+
class IMediaPlayer: public IInterface
{
public:
@@ -65,14 +69,9 @@
virtual status_t setSyncSettings(const AVSyncSettings& sync, float videoFpsHint) = 0;
virtual status_t getSyncSettings(AVSyncSettings* sync /* nonnull */,
float* videoFps /* nonnull */) = 0;
- // When |precise| is true, it's required that the first rendered media position after seekTo
- // is precisely at |msec|, up to rounding error of granuality, e.g., video frame interval or
- // audio length of decoding buffer. In this case, it might take a little long time to finish
- // seekTo.
- // When |precise| is false, |msec| is a hint to the mediaplayer which will try its best to
- // fulfill the request, but it's not guaranteed. This option could result in fast finish of
- // seekTo.
- virtual status_t seekTo(int msec, bool precise = false) = 0;
+ virtual status_t seekTo(
+ int msec,
+ MediaPlayerSeekMode mode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC) = 0;
virtual status_t getCurrentPosition(int* msec) = 0;
virtual status_t getDuration(int* msec) = 0;
virtual status_t reset() = 0;
diff --git a/include/media/MediaDefs.h b/include/media/MediaDefs.h
index 5f2a32d..0682413 100644
--- a/include/media/MediaDefs.h
+++ b/include/media/MediaDefs.h
@@ -59,8 +59,6 @@
extern const char *MEDIA_MIMETYPE_CONTAINER_AVI;
extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG2PS;
-extern const char *MEDIA_MIMETYPE_CONTAINER_WVM;
-
extern const char *MEDIA_MIMETYPE_TEXT_3GPP;
extern const char *MEDIA_MIMETYPE_TEXT_SUBRIP;
extern const char *MEDIA_MIMETYPE_TEXT_VTT;
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index b488159..4e4878a 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -205,7 +205,8 @@
*videoFps = -1.f;
return OK;
}
- virtual status_t seekTo(int msec, bool precise = false) = 0;
+ virtual status_t seekTo(
+ int msec, MediaPlayerSeekMode mode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC) = 0;
virtual status_t getCurrentPosition(int *msec) = 0;
virtual status_t getDuration(int *msec) = 0;
virtual status_t reset() = 0;
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index c556f0a..be34d02 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -233,7 +233,9 @@
float* videoFps /* nonnull */);
status_t getVideoWidth(int *w);
status_t getVideoHeight(int *h);
- status_t seekTo(int msec, bool precise = false);
+ status_t seekTo(
+ int msec,
+ MediaPlayerSeekMode mode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC);
status_t getCurrentPosition(int *msec);
status_t getDuration(int *msec);
status_t reset();
@@ -257,7 +259,7 @@
private:
void clear_l();
- status_t seekTo_l(int msec, bool precise);
+ status_t seekTo_l(int msec, MediaPlayerSeekMode mode);
status_t prepareAsync_l();
status_t getDuration_l(int *msec);
status_t attachNewPlayer(const sp<IMediaPlayer>& player);
@@ -274,9 +276,9 @@
void* mCookie;
media_player_states mCurrentState;
int mCurrentPosition;
- bool mCurrentSeekPrecise;
+ MediaPlayerSeekMode mCurrentSeekMode;
int mSeekPosition;
- int mSeekPrecise;
+ MediaPlayerSeekMode mSeekMode;
bool mPrepareSync;
status_t mPrepareStatus;
audio_stream_type_t mStreamType;
diff --git a/include/media/stagefright/CodecBase.h b/include/media/stagefright/CodecBase.h
index d8c43a4..39a9089 100644
--- a/include/media/stagefright/CodecBase.h
+++ b/include/media/stagefright/CodecBase.h
@@ -43,7 +43,8 @@
kWhatFillThisBuffer = 'fill',
kWhatDrainThisBuffer = 'drai',
kWhatEOS = 'eos ',
- kWhatShutdownCompleted = 'scom',
+ kWhatStopCompleted = 'scom',
+ kWhatReleaseCompleted = 'rcom',
kWhatFlushCompleted = 'fcom',
kWhatError = 'erro',
kWhatComponentAllocated = 'cAll',
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index 89def5d..b0243ec 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -151,8 +151,6 @@
status_t getOutputFormat(sp<AMessage> *format) const;
status_t getInputFormat(sp<AMessage> *format) const;
- status_t getWidevineLegacyBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const;
-
status_t getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const;
status_t getOutputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const;
diff --git a/include/media/stagefright/NuMediaExtractor.h b/include/media/stagefright/NuMediaExtractor.h
index 03e2185..a8aca5a 100644
--- a/include/media/stagefright/NuMediaExtractor.h
+++ b/include/media/stagefright/NuMediaExtractor.h
@@ -108,7 +108,6 @@
sp<DataSource> mDataSource;
sp<IMediaExtractor> mImpl;
- bool mIsWidevineExtractor;
Vector<TrackInfo> mSelectedTracks;
int64_t mTotalBitrate; // in bits/sec
diff --git a/include/media/stagefright/foundation/Flagged.h b/include/media/stagefright/foundation/Flagged.h
new file mode 100644
index 0000000..bf0afbf
--- /dev/null
+++ b/include/media/stagefright/foundation/Flagged.h
@@ -0,0 +1,513 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef STAGEFRIGHT_FOUNDATION_FLAGGED_H_
+#define STAGEFRIGHT_FOUNDATION_FLAGGED_H_
+
+#include <media/stagefright/foundation/TypeTraits.h>
+
+namespace android {
+
+/**
+ * Flagged<T, Flag> is basically a specialized std::pair<Flag, T> that automatically optimizes out
+ * the flag if the wrapped type T is already flagged and we can combine the outer and inner flags.
+ *
+ * Flags can be queried/manipulated via flags() an setFlags(Flags). The wrapped value can be
+ * accessed via get(). This template is meant to be inherited by other utility/wrapper classes
+ * that need to store integral information along with the value.
+ *
+ * Users must specify the used bits (MASK) in the flags. Flag getters and setters will enforce this
+ * mask. _Flagged_helper::minMask<Flag> is provided to easily calculate a mask for a max value.
+ *
+ * E.g. adding a safe flag can be achieved like this:
+ *
+ *
+ * enum SafeFlags : uint32_t {
+ * kUnsafe,
+ * kSafe,
+ * kSafeMask = _Flagged_helper::minMask(kSafe),
+ * };
+ * typedef Flagged<int32_t, SafeFlags, kSafeMask> safeInt32;
+ *
+ * safeInt32 a;
+ * a.setFlags(kSafe);
+ * a.get() = 15;
+ * EXPECT_EQ(a.flags(), kSafe);
+ * EXPECT_EQ(a.get(), 15);
+ *
+ *
+ * Flagged also supports lazy or calculated wrapping of already flagged types. Lazy wrapping is
+ * provided automatically (flags are automatically shared if possible, e.g. mask is shifted
+ * automatically to not overlap with used bits of the wrapped type's flags, and fall back to
+ * unshared version of the template.):
+ *
+ * enum OriginFlags : uint32_t {
+ * kUnknown,
+ * kConst,
+ * kCalculated,
+ * kComponent,
+ * kApplication,
+ * kFile,
+ * kBinder,
+ * kOriginMask = _Flagged_helper::minMask(kBinder),
+ * };
+ * typedef Flagged<safeInt32, OriginFlags, kOriginMask>
+ * trackedSafeInt32;
+ *
+ * static_assert(sizeof(trackedSafeInt32) == sizeof(safeInt32), "");
+ *
+ * trackedSafeInt32 b(kConst, kSafe, 1);
+ * EXPECT_EQ(b.flags(), kConst);
+ * EXPECT_EQ(b.get().flags(), kSafe);
+ * EXPECT_EQ(b.get().get(), 1);
+ * b.setFlags(kCalculated);
+ * b.get().setFlags(overflow ? kUnsafe : kSafe);
+ *
+ * One can also choose to share some flag-bits with the wrapped class:
+ *
+ * enum ValidatedFlags : uint32_t {
+ * kUnsafeV = kUnsafe,
+ * kSafeV = kSafe,
+ * kValidated = kSafe | 2,
+ * kSharedMaskV = kSafeMask,
+ * kValidatedMask = _Flagged_helper::minMask(kValidated),
+ * };
+ * typedef Flagged<safeInt32, ValidatedFlags, kValidatedMask, kSharedMaskV> validatedInt32;
+ *
+ * validatedInt32 v(kUnsafeV, kSafe, 10);
+ * EXPECT_EQ(v.flags(), kUnsafeV);
+ * EXPECT_EQ(v.get().flags(), kUnsafe); // !kUnsafeV overrides kSafe
+ * EXPECT_EQ(v.get().get(), 10);
+ * v.setFlags(kValidated);
+ * EXPECT_EQ(v.flags(), kValidated);
+ * EXPECT_EQ(v.get().flags(), kSafe);
+ * v.get().setFlags(kUnsafe);
+ * EXPECT_EQ(v.flags(), 2); // NOTE: sharing masks with enums allows strange situations to occur
+ */
+
+/**
+ * Helper class for Flagged support. Encapsulates common utilities used by all
+ * templated classes.
+ */
+struct _Flagged_helper {
+ /**
+ * Calculates the value with a given number of top-most bits set.
+ *
+ * This method may be called with a signed flag.
+ *
+ * \param num number of bits to set. This must be between 0 and the number of bits in Flag.
+ *
+ * \return the value where only the given number of top-most bits are set.
+ */
+ template<typename Flag>
+ static constexpr Flag topBits(int num) {
+ return Flag(num > 0 ?
+ ~((Flag(1) << (sizeof(Flag) * 8 - is_signed_integral<Flag>::value - num)) - 1) :
+ 0);
+ }
+
+ /**
+ * Calculates the minimum mask required to cover a value. Used with the maximum enum value for
+ * an unsigned flag.
+ *
+ * \param maxValue maximum value to cover
+ * \param shift DO NO USE. used internally
+ *
+ * \return mask that can be used that covers the maximum value.
+ */
+ template<typename Flag>
+ static constexpr Flag minMask(Flag maxValue, int shift=sizeof(Flag) * 4) {
+ static_assert(is_unsigned_integral<Flag>::value,
+ "this method only makes sense for unsigned flags");
+ return shift ? minMask<Flag>(Flag(maxValue | (maxValue >> shift)), shift >> 1) : maxValue;
+ }
+
+ /**
+ * Returns a value left-shifted by an argument as a potential constexpr.
+ *
+ * This method helps around the C-language limitation, when left-shift of a negative value with
+ * even 0 cannot be a constexpr.
+ *
+ * \param value value to shift
+ * \param shift amount of shift
+ * \returns the shifted value as an integral type
+ */
+ template<typename Flag, typename IntFlag = typename underlying_integral_type<Flag>::type>
+ static constexpr IntFlag lshift(Flag value, int shift) {
+ return shift ? value << shift : value;
+ }
+
+private:
+
+ /**
+ * Determines whether mask can be combined with base-mask for a given left shift.
+ *
+ * \param mask desired mask
+ * \param baseMask mask used by T or 0 if T is not flagged by Flag
+ * \param sharedMask desired shared mask (if this is non-0, this must be mask & baseMask)
+ * \param shift desired left shift to be used for mask
+ * \param baseShift left shift used by T or 0 if T is not flagged by Flag
+ * \param effectiveMask effective mask used by T or 0 if T is not flagged by Flag
+ *
+ * \return bool whether mask can be combined with baseMask using the desired values.
+ */
+ template<typename Flag, typename IntFlag=typename underlying_integral_type<Flag>::type>
+ static constexpr bool canCombine(
+ Flag mask, IntFlag baseMask, Flag sharedMask, int shift,
+ int baseShift, IntFlag effectiveMask) {
+ return
+ // verify that shift is valid and mask can be shifted
+ shift >= 0 && (mask & topBits<Flag>(shift)) == 0 &&
+
+ // verify that base mask is part of effective mask (sanity check on arguments)
+ (baseMask & ~(effectiveMask >> baseShift)) == 0 &&
+
+ // if sharing masks, shift must be the base's shift.
+ // verify that shared mask is the overlap of base mask and mask
+ (sharedMask ?
+ ((sharedMask ^ (baseMask & mask)) == 0 &&
+ shift == baseShift) :
+
+
+ // otherwise, verify that there is no overlap between mask and base's effective mask
+ (mask & (effectiveMask >> shift)) == 0);
+ }
+
+
+ /**
+ * Calculates the minimum (left) shift required to combine a mask with the mask of an
+ * underlying type (T, also flagged by Flag).
+ *
+ * \param mask desired mask
+ * \param baseMask mask used by T or 0 if T is not flagged by Flag
+ * \param sharedMask desired shared mask (if this is non-0, this must be mask & baseMask)
+ * \param baseShift left shift used by T
+ * \param effectiveMask effective mask used by T
+ *
+ * \return a non-negative minimum left shift value if mask can be combined with baseMask,
+ * or -1 if the masks cannot be combined. -2 if the input is invalid.
+ */
+ template<typename Flag,
+ typename IntFlag = typename underlying_integral_type<Flag>::type>
+ static constexpr int getShift(
+ Flag mask, IntFlag baseMask, Flag sharedMask, int baseShift, IntFlag effectiveMask) {
+ return
+ // baseMask must be part of the effective mask
+ (baseMask & ~(effectiveMask >> baseShift)) ? -2 :
+
+ // if sharing masks, shift must be base's shift. verify that shared mask is part of
+ // base mask and mask, and that desired mask still fits with base's shift value
+ sharedMask ?
+ (canCombine(mask, baseMask, sharedMask, baseShift /* shift */,
+ baseShift, effectiveMask) ? baseShift : -1) :
+
+ // otherwise, see if 0-shift works
+ ((mask & effectiveMask) == 0) ? 0 :
+
+ // otherwise, verify that mask can be shifted up
+ ((mask & topBits<Flag>(1)) || (mask < 0)) ? -1 :
+
+ incShift(getShift(Flag(mask << 1), baseMask /* unused */, sharedMask /* 0 */,
+ baseShift /* unused */, effectiveMask));
+ }
+
+ /**
+ * Helper method that increments a non-negative (shift) value.
+ *
+ * This method is used to make it easier to create a constexpr for getShift.
+ *
+ * \param shift (shift) value to increment
+ *
+ * \return original shift if it was negative; otherwise, the shift incremented by one.
+ */
+ static constexpr int incShift(int shift) {
+ return shift + (shift >= 0);
+ }
+
+#ifdef FRIEND_TEST
+ FRIEND_TEST(FlaggedTest, _Flagged_helper_Test);
+#endif
+
+public:
+ /**
+ * Base class for all Flagged<T, Flag> classes.
+ *
+ * \note flagged types do not have a member variable for the mask used by the type. As such,
+ * they should be be cast to this base class.
+ *
+ * \todo can we replace this base class check with a static member check to remove possibility
+ * of cast?
+ */
+ template<typename Flag>
+ struct base {};
+
+ /**
+ * Type support utility that retrieves the mask of a class (T) if it is a type flagged by
+ * Flag (e.g. Flagged<T, Flag>).
+ *
+ * \note This retrieves 0 if T is a flagged class, that is not flagged by Flag or an equivalent
+ * underlying type.
+ *
+ * Generic implementation for a non-flagged class.
+ */
+ template<
+ typename T, typename Flag,
+ bool=std::is_base_of<base<typename underlying_integral_type<Flag>::type>, T>::value>
+ struct mask_of {
+ using IntFlag = typename underlying_integral_type<Flag>::type;
+ static constexpr IntFlag value = Flag(0); ///< mask of a potentially flagged class
+ static constexpr int shift = 0; ///<left shift of flags in a potentially flagged class
+ static constexpr IntFlag effective_value = IntFlag(0); ///<effective mask of flagged class
+ };
+
+ /**
+ * Type support utility that calculates the minimum (left) shift required to combine a mask
+ * with the mask of an underlying type T also flagged by Flag.
+ *
+ * \note if T is not flagged, not flagged by Flag, or the masks cannot be combined due to
+ * incorrect sharing or the flags not having enough bits, the minimum is -1.
+ *
+ * \param MASK desired mask
+ * \param SHARED_MASK desired shared mask (if this is non-0, T must be an type flagged by
+ * Flag with a mask that has exactly these bits common with MASK)
+ */
+ template<typename T, typename Flag, Flag MASK, Flag SHARED_MASK>
+ struct min_shift {
+ /// minimum (left) shift required, or -1 if masks cannot be combined
+ static constexpr int value =
+ getShift(MASK, mask_of<T, Flag>::value, SHARED_MASK,
+ mask_of<T, Flag>::shift, mask_of<T, Flag>::effective_value);
+ };
+
+ /**
+ * Type support utility that calculates whether the flags of T can be combined with MASK.
+ *
+ * \param MASK desired mask
+ * \param SHARED_MASK desired shared mask (if this is non-0, T MUST be an type flagged by
+ * Flag with a mask that has exactly these bits common with MASK)
+ */
+ template<
+ typename T, typename Flag, Flag MASK,
+ Flag SHARED_MASK=Flag(0),
+ int SHIFT=min_shift<T, Flag, MASK, SHARED_MASK>::value>
+ struct can_combine {
+ using IntFlag = typename underlying_integral_type<Flag>::type;
+ /// true if this mask can be combined with T's existing flag. false otherwise.
+ static constexpr bool value =
+ std::is_base_of<base<IntFlag>, T>::value
+ && canCombine(MASK, mask_of<T, Flag>::value, SHARED_MASK, SHIFT,
+ mask_of<T, Flag>::shift, mask_of<T, Flag>::effective_value);
+ };
+};
+
+/**
+ * Template specialization for the case when T is flagged by Flag or a compatible type.
+ */
+template<typename T, typename Flag>
+struct _Flagged_helper::mask_of<T, Flag, true> {
+ using IntType = typename underlying_integral_type<Flag>::type;
+ static constexpr IntType value = T::sFlagMask;
+ static constexpr int shift = T::sFlagShift;
+ static constexpr IntType effective_value = T::sEffectiveMask;
+};
+
+/**
+ * Main Flagged template that adds flags to an object of another type (in essence, creates a pair)
+ *
+ * Flag must be an integral type (enums are allowed).
+ *
+ * \note We could make SHARED_MASK be a boolean as it must be either 0 or MASK & base's mask, but we
+ * want it to be spelled out for safety.
+ *
+ * \param T type of object wrapped
+ * \param Flag type of flag
+ * \param MASK mask for the bits used in flag (before any shift)
+ * \param SHARED_MASK optional mask to be shared with T (if this is not zero, SHIFT must be 0, and
+ * it must equal to MASK & T's mask)
+ * \param SHIFT optional left shift for MASK to combine with T's mask (or -1, if masks should not
+ * be combined.)
+ */
+template<
+ typename T, typename Flag, Flag MASK, Flag SHARED_MASK=(Flag)0,
+ int SHIFT=_Flagged_helper::min_shift<T, Flag, MASK, SHARED_MASK>::value,
+ typename IntFlag=typename underlying_integral_type<Flag>::type,
+ bool=_Flagged_helper::can_combine<T, IntFlag, MASK, SHARED_MASK, SHIFT>::value>
+class Flagged : public _Flagged_helper::base<IntFlag> {
+ static_assert(SHARED_MASK == 0,
+ "shared mask can only be used with common flag types "
+ "and must be part of mask and mask of base type");
+ static_assert((_Flagged_helper::topBits<Flag>(SHIFT) & MASK) == 0, "SHIFT overflows MASK");
+
+ static constexpr Flag sFlagMask = MASK; ///< the mask
+ static constexpr int sFlagShift = SHIFT > 0 ? SHIFT : 0; ///< the left shift applied to flags
+
+ friend struct _Flagged_helper;
+#ifdef FRIEND_TEST
+ static constexpr bool sFlagCombined = false;
+ FRIEND_TEST(FlaggedTest, _Flagged_helper_Test);
+#endif
+
+ T mValue; ///< wrapped value
+ IntFlag mFlags; ///< flags
+
+protected:
+ /// The effective combined mask used by this class and any wrapped classes if the flags are
+ /// combined.
+ static constexpr IntFlag sEffectiveMask = _Flagged_helper::lshift(MASK, sFlagShift);
+
+ /**
+ * Helper method used by subsequent flagged wrappers to query flags. Returns the
+ * flags for a particular mask and left shift.
+ *
+ * \param mask bitmask to use
+ * \param shift left shifts to use
+ *
+ * \return the requested flags
+ */
+ inline constexpr IntFlag getFlagsHelper(IntFlag mask, int shift) const {
+ return (mFlags >> shift) & mask;
+ }
+
+ /**
+ * Helper method used by subsequent flagged wrappers to apply combined flags. Sets the flags
+ * in the bitmask using a particulare left shift.
+ *
+ * \param mask bitmask to use
+ * \param shift left shifts to use
+ * \param flags flags to update (any flags within the bitmask are updated to their value in this
+ * argument)
+ */
+ inline void setFlagsHelper(IntFlag mask, int shift, IntFlag flags) {
+ mFlags = Flag((mFlags & ~(mask << shift)) | ((flags & mask) << shift));
+ }
+
+public:
+ /**
+ * Wrapper around base class constructor. These take the flags as their first
+ * argument and pass the rest of the arguments to the base class constructor.
+ *
+ * \param flags initial flags
+ */
+ template<typename ...Args>
+ constexpr Flagged(Flag flags, Args... args)
+ : mValue(std::forward<Args>(args)...),
+ mFlags(Flag(_Flagged_helper::lshift(flags & sFlagMask, sFlagShift))) { }
+
+ /** Gets the wrapped value as const. */
+ inline constexpr const T &get() const { return mValue; }
+
+ /** Gets the wrapped value. */
+ inline T &get() { return mValue; }
+
+ /** Gets the flags. */
+ constexpr Flag flags() const {
+ return Flag(getFlagsHelper(sFlagMask, sFlagShift));
+ }
+
+ /** Sets the flags. */
+ void setFlags(Flag flags) {
+ setFlagsHelper(sFlagMask, sFlagShift, flags);
+ }
+};
+
+/*
+ * TRICKY: we cannot implement the specialization as:
+ *
+ * class Flagged : base<Flag> {
+ * T value;
+ * };
+ *
+ * Because T also inherits from base<Flag> and this runs into a compiler bug where
+ * sizeof(Flagged) > sizeof(T).
+ *
+ * Instead, we must inherit directly from the wrapped class
+ *
+ */
+#if 0
+template<
+ typename T, typename Flag, Flag MASK, Flag SHARED_MASK, int SHIFT>
+class Flagged<T, Flag, MASK, SHARED_MASK, SHIFT, true> : public _Flagged_helper::base<Flag> {
+private:
+ T mValue;
+};
+#else
+/**
+ * Specialization for the case when T is derived from Flagged<U, Flag> and flags can be combined.
+ */
+template<
+ typename T, typename Flag, Flag MASK, Flag SHARED_MASK, int SHIFT, typename IntFlag>
+class Flagged<T, Flag, MASK, SHARED_MASK, SHIFT, IntFlag, true> : private T {
+ static_assert(is_integral_or_enum<Flag>::value, "flag must be integer or enum");
+
+ static_assert(SHARED_MASK == 0 || SHIFT == 0, "cannot overlap masks when using SHIFT");
+ static_assert((SHARED_MASK & ~MASK) == 0, "shared mask must be part of the mask");
+ static_assert((SHARED_MASK & ~T::sEffectiveMask) == 0,
+ "shared mask must be part of the base mask");
+ static_assert(SHARED_MASK == 0 || (~SHARED_MASK & (MASK & T::sEffectiveMask)) == 0,
+ "mask and base mask can only overlap in shared mask");
+
+ static constexpr Flag sFlagMask = MASK; ///< the mask
+ static constexpr int sFlagShift = SHIFT; ///< the left shift applied to the flags
+
+#ifdef FRIEND_TEST
+ const static bool sFlagCombined = true;
+ FRIEND_TEST(FlaggedTest, _Flagged_helper_Test);
+#endif
+
+protected:
+ /// The effective combined mask used by this class and any wrapped classes if the flags are
+ /// combined.
+ static constexpr IntFlag sEffectiveMask = Flag((MASK << SHIFT) | T::sEffectiveMask);
+ friend struct _Flagged_helper;
+
+public:
+ /**
+ * Wrapper around base class constructor. These take the flags as their first
+ * argument and pass the rest of the arguments to the base class constructor.
+ *
+ * \param flags initial flags
+ */
+ template<typename ...Args>
+ constexpr Flagged(Flag flags, Args... args)
+ : T(std::forward<Args>(args)...) {
+ // we construct the base class first and apply the flags afterwards as
+ // base class may not have a constructor that takes flags even if it is derived from
+ // Flagged<U, Flag>
+ setFlags(flags);
+ }
+
+ /** Gets the wrapped value as const. */
+ inline constexpr T &get() const { return *this; }
+
+ /** Gets the wrapped value. */
+ inline T &get() { return *this; }
+
+ /** Gets the flags. */
+ Flag constexpr flags() const {
+ return Flag(this->getFlagsHelper(sFlagMask, sFlagShift));
+ }
+
+ /** Sets the flags. */
+ void setFlags(Flag flags) {
+ this->setFlagsHelper(sFlagMask, sFlagShift, flags);
+ }
+};
+#endif
+
+} // namespace android
+
+#endif // STAGEFRIGHT_FOUNDATION_FLAGGED_H_
+
diff --git a/include/media/stagefright/foundation/TypeTraits.h b/include/media/stagefright/foundation/TypeTraits.h
new file mode 100644
index 0000000..2eaec35
--- /dev/null
+++ b/include/media/stagefright/foundation/TypeTraits.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef STAGEFRIGHT_FOUNDATION_TYPE_TRAITS_H_
+#define STAGEFRIGHT_FOUNDATION_TYPE_TRAITS_H_
+
+#include <type_traits>
+
+namespace android {
+
+/**
+ * std::is_signed, is_unsigned and is_integral does not consider enums even though the standard
+ * considers them integral. Create modified versions of these here. Also create a wrapper around
+ * std::underlying_type that does not require checking if the type is an enum.
+ */
+
+/**
+ * Type support utility class to check if a type is an integral type or an enum.
+ */
+template<typename T>
+struct is_integral_or_enum
+ : std::integral_constant<bool, std::is_integral<T>::value || std::is_enum<T>::value> { };
+
+/**
+ * Type support utility class to get the underlying std::is_integral supported type for a type.
+ * This returns the underlying type for enums, and the same type for types covered by
+ * std::is_integral.
+ *
+ * This is also used as a conditional to return an alternate type if the template param is not
+ * an integral or enum type (as in underlying_integral_type<T, TypeIfNotEnumOrIntegral>::type).
+ */
+template<typename T,
+ typename U=typename std::enable_if<is_integral_or_enum<T>::value>::type,
+ bool=std::is_enum<T>::value,
+ bool=std::is_integral<T>::value>
+struct underlying_integral_type {
+ static_assert(!std::is_enum<T>::value, "T should not be enum here");
+ static_assert(!std::is_integral<T>::value, "T should not be integral here");
+ typedef U type;
+};
+
+/** Specialization for enums. */
+template<typename T, typename U>
+struct underlying_integral_type<T, U, true, false> {
+ static_assert(std::is_enum<T>::value, "T should be enum here");
+ static_assert(!std::is_integral<T>::value, "T should not be integral here");
+ typedef typename std::underlying_type<T>::type type;
+};
+
+/** Specialization for non-enum std-integral types. */
+template<typename T, typename U>
+struct underlying_integral_type<T, U, false, true> {
+ static_assert(!std::is_enum<T>::value, "T should not be enum here");
+ static_assert(std::is_integral<T>::value, "T should be integral here");
+ typedef T type;
+};
+
+/**
+ * Type support utility class to check if the underlying integral type is signed.
+ */
+template<typename T>
+struct is_signed_integral
+ : std::integral_constant<bool, std::is_signed<
+ typename underlying_integral_type<T, unsigned>::type>::value> { };
+
+/**
+ * Type support utility class to check if the underlying integral type is unsigned.
+ */
+template<typename T>
+struct is_unsigned_integral
+ : std::integral_constant<bool, std::is_unsigned<
+ typename underlying_integral_type<T, signed>::type>::value> {
+};
+
+} // namespace android
+
+#endif // STAGEFRIGHT_FOUNDATION_TYPE_TRAITS_H_
+
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index 41b6988..dda2570 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -246,12 +246,12 @@
return reply.readInt32();
}
- status_t seekTo(int msec, bool precise)
+ status_t seekTo(int msec, MediaPlayerSeekMode mode)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
data.writeInt32(msec);
- data.writeBool(precise);
+ data.writeInt32(mode);
remote()->transact(SEEK_TO, data, &reply);
return reply.readInt32();
}
@@ -575,8 +575,8 @@
case SEEK_TO: {
CHECK_INTERFACE(IMediaPlayer, data, reply);
int msec = data.readInt32();
- bool precise = data.readBool();
- reply->writeInt32(seekTo(msec, precise));
+ MediaPlayerSeekMode mode = (MediaPlayerSeekMode)data.readInt32();
+ reply->writeInt32(seekTo(msec, mode));
return NO_ERROR;
} break;
case GET_CURRENT_POSITION: {
diff --git a/media/libmedia/MediaDefs.cpp b/media/libmedia/MediaDefs.cpp
index a2110c9..2ae71f7 100644
--- a/media/libmedia/MediaDefs.cpp
+++ b/media/libmedia/MediaDefs.cpp
@@ -57,8 +57,6 @@
const char *MEDIA_MIMETYPE_CONTAINER_AVI = "video/avi";
const char *MEDIA_MIMETYPE_CONTAINER_MPEG2PS = "video/mp2p";
-const char *MEDIA_MIMETYPE_CONTAINER_WVM = "video/wvm";
-
const char *MEDIA_MIMETYPE_TEXT_3GPP = "text/3gpp-tt";
const char *MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
const char *MEDIA_MIMETYPE_TEXT_VTT = "text/vtt";
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 846a24c..699172b 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -55,9 +55,9 @@
mStreamType = AUDIO_STREAM_MUSIC;
mAudioAttributesParcel = NULL;
mCurrentPosition = -1;
- mCurrentSeekPrecise = false;
+ mCurrentSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
mSeekPosition = -1;
- mSeekPrecise = false;
+ mSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
mCurrentState = MEDIA_PLAYER_IDLE;
mPrepareSync = false;
mPrepareStatus = NO_ERROR;
@@ -102,9 +102,9 @@
void MediaPlayer::clear_l()
{
mCurrentPosition = -1;
- mCurrentSeekPrecise = false;
+ mCurrentSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
mSeekPosition = -1;
- mSeekPrecise = false;
+ mSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
mVideoWidth = mVideoHeight = 0;
mRetransmitEndpointValid = false;
}
@@ -512,9 +512,9 @@
return getDuration_l(msec);
}
-status_t MediaPlayer::seekTo_l(int msec, bool precise)
+status_t MediaPlayer::seekTo_l(int msec, MediaPlayerSeekMode mode)
{
- ALOGV("seekTo (%d, %d)", msec, precise);
+ ALOGV("seekTo (%d, %d)", msec, mode);
if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED |
MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) {
if ( msec < 0 ) {
@@ -541,14 +541,14 @@
// cache duration
mCurrentPosition = msec;
- mCurrentSeekPrecise = precise;
+ mCurrentSeekMode = mode;
if (mSeekPosition < 0) {
mSeekPosition = msec;
- mSeekPrecise = precise;
- return mPlayer->seekTo(msec, precise);
+ mSeekMode = mode;
+ return mPlayer->seekTo(msec, mode);
}
else {
- ALOGV("Seek in progress - queue up seekTo[%d, %d]", msec, precise);
+ ALOGV("Seek in progress - queue up seekTo[%d, %d]", msec, mode);
return NO_ERROR;
}
}
@@ -557,11 +557,11 @@
return INVALID_OPERATION;
}
-status_t MediaPlayer::seekTo(int msec, bool precise)
+status_t MediaPlayer::seekTo(int msec, MediaPlayerSeekMode mode)
{
mLockThreadId = getThreadId();
Mutex::Autolock _l(mLock);
- status_t result = seekTo_l(msec, precise);
+ status_t result = seekTo_l(msec, mode);
mLockThreadId = 0;
return result;
@@ -875,16 +875,16 @@
break;
case MEDIA_SEEK_COMPLETE:
ALOGV("Received seek complete");
- if (mSeekPosition != mCurrentPosition || (!mSeekPrecise && mCurrentSeekPrecise)) {
- ALOGV("Executing queued seekTo(%d, %d)", mCurrentPosition, mCurrentSeekPrecise);
+ if (mSeekPosition != mCurrentPosition || (mSeekMode != mCurrentSeekMode)) {
+ ALOGV("Executing queued seekTo(%d, %d)", mCurrentPosition, mCurrentSeekMode);
mSeekPosition = -1;
- mSeekPrecise = false;
- seekTo_l(mCurrentPosition, mCurrentSeekPrecise);
+ mSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
+ seekTo_l(mCurrentPosition, mCurrentSeekMode);
}
else {
ALOGV("All seeks complete - return to regularly scheduled program");
mCurrentPosition = mSeekPosition = -1;
- mCurrentSeekPrecise = mSeekPrecise = false;
+ mCurrentSeekMode = mSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
}
break;
case MEDIA_BUFFERING_UPDATE:
diff --git a/media/libmediaplayerservice/ActivityManager.cpp b/media/libmediaplayerservice/ActivityManager.cpp
index 60a209f..0e6cf7b 100644
--- a/media/libmediaplayerservice/ActivityManager.cpp
+++ b/media/libmediaplayerservice/ActivityManager.cpp
@@ -24,7 +24,7 @@
namespace android {
-const uint32_t OPEN_CONTENT_URI_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 4;
+const uint32_t OPEN_CONTENT_URI_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION;
// Perform ContentProvider.openFile() on the given URI, returning
// the resulting native file descriptor. Returns < 0 on error.
diff --git a/media/libmediaplayerservice/MediaPlayerFactory.cpp b/media/libmediaplayerservice/MediaPlayerFactory.cpp
index 605c710..0a9f791 100644
--- a/media/libmediaplayerservice/MediaPlayerFactory.cpp
+++ b/media/libmediaplayerservice/MediaPlayerFactory.cpp
@@ -26,7 +26,6 @@
#include <media/stagefright/foundation/ADebug.h>
#include <utils/Errors.h>
#include <utils/misc.h>
-#include <../libstagefright/include/WVMExtractor.h>
#include "MediaPlayerFactory.h"
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 3ff9d98..6e163d9 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1121,12 +1121,12 @@
return OK;
}
-status_t MediaPlayerService::Client::seekTo(int msec, bool precise)
+status_t MediaPlayerService::Client::seekTo(int msec, MediaPlayerSeekMode mode)
{
- ALOGV("[%d] seekTo(%d)", mConnId, msec);
+ ALOGV("[%d] seekTo(%d, %d)", mConnId, msec, mode);
sp<MediaPlayerBase> p = getPlayer();
if (p == 0) return UNKNOWN_ERROR;
- return p->seekTo(msec, precise);
+ return p->seekTo(msec, mode);
}
status_t MediaPlayerService::Client::reset()
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index ef82b48..a4ea37f 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -298,7 +298,9 @@
virtual status_t setSyncSettings(const AVSyncSettings& rate, float videoFpsHint);
virtual status_t getSyncSettings(AVSyncSettings* rate /* nonnull */,
float* videoFps /* nonnull */);
- virtual status_t seekTo(int msec, bool precise = false);
+ virtual status_t seekTo(
+ int msec,
+ MediaPlayerSeekMode mode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC);
virtual status_t getCurrentPosition(int* msec);
virtual status_t getDuration(int* msec);
virtual status_t reset();
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 94ceae4..49c221b 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -369,9 +369,13 @@
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("media.camera"));
- mCameraDeathListener = new ServiceDeathNotifier(binder, listener,
- MediaPlayerService::CAMERA_PROCESS_DEATH);
- binder->linkToDeath(mCameraDeathListener);
+
+ // If the device does not have a camera, do not create a death listener for it.
+ if (binder != NULL) {
+ mCameraDeathListener = new ServiceDeathNotifier(binder, listener,
+ MediaPlayerService::CAMERA_PROCESS_DEATH);
+ binder->linkToDeath(mCameraDeathListener);
+ }
binder = sm->getService(String16("media.codec"));
mCodecDeathListener = new ServiceDeathNotifier(binder, listener,
diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h
index c0d6a59..11fddf6 100644
--- a/media/libmediaplayerservice/TestPlayerStub.h
+++ b/media/libmediaplayerservice/TestPlayerStub.h
@@ -87,7 +87,11 @@
virtual status_t stop() {return mPlayer->stop();}
virtual status_t pause() {return mPlayer->pause();}
virtual bool isPlaying() {return mPlayer->isPlaying();}
- virtual status_t seekTo(int msec, bool precise = false) {return mPlayer->seekTo(msec, precise);}
+ virtual status_t seekTo(
+ int msec,
+ MediaPlayerSeekMode mode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC) {
+ return mPlayer->seekTo(msec, mode);
+ }
virtual status_t getCurrentPosition(int *p) {
return mPlayer->getCurrentPosition(p);
}
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index cdbc2f8..cf1f84b 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -35,7 +35,6 @@
#include <media/stagefright/Utils.h>
#include "../../libstagefright/include/DRMExtractor.h"
#include "../../libstagefright/include/NuCachedSource2.h"
-#include "../../libstagefright/include/WVMExtractor.h"
#include "../../libstagefright/include/HTTPBase.h"
namespace android {
@@ -59,7 +58,6 @@
mFetchTimedTextDataGeneration(0),
mDurationUs(-1ll),
mAudioIsVorbis(false),
- mIsWidevine(false),
mIsSecure(false),
mIsStreaming(false),
mUIDValid(uidValid),
@@ -141,44 +139,9 @@
status_t NuPlayer::GenericSource::initFromDataSource() {
sp<IMediaExtractor> extractor;
- String8 mimeType;
- float confidence;
- sp<AMessage> dummy;
- bool isWidevineStreaming = false;
-
CHECK(mDataSource != NULL);
- if (mIsWidevine) {
- isWidevineStreaming = SniffWVM(
- mDataSource, &mimeType, &confidence, &dummy);
- if (!isWidevineStreaming ||
- strcasecmp(
- mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
- ALOGE("unsupported widevine mime: %s", mimeType.string());
- return UNKNOWN_ERROR;
- }
- } else if (mIsStreaming) {
- if (!mDataSource->sniff(&mimeType, &confidence, &dummy)) {
- return UNKNOWN_ERROR;
- }
- isWidevineStreaming = !strcasecmp(
- mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM);
- }
-
- if (isWidevineStreaming) {
- // we don't want cached source for widevine streaming.
- mCachedSource.clear();
- mDataSource = mHttpSource;
- mWVMExtractor = new WVMExtractor(mDataSource);
- mWVMExtractor->setAdaptiveStreamingMode(true);
- if (mUIDValid) {
- mWVMExtractor->setUID(mUID);
- }
- extractor = mWVMExtractor;
- } else {
- extractor = MediaExtractor::Create(mDataSource,
- mimeType.isEmpty() ? NULL : mimeType.string());
- }
+ extractor = MediaExtractor::Create(mDataSource, NULL);
if (extractor == NULL) {
return UNKNOWN_ERROR;
@@ -194,17 +157,6 @@
if (mFileMeta->findInt64(kKeyDuration, &duration)) {
mDurationUs = duration;
}
-
- if (!mIsWidevine) {
- // Check mime to see if we actually have a widevine source.
- // If the data source is not URL-type (eg. file source), we
- // won't be able to tell until now.
- const char *fileMime;
- if (mFileMeta->findCString(kKeyMIMEType, &fileMime)
- && !strncasecmp(fileMime, "video/wvm", 9)) {
- mIsWidevine = true;
- }
- }
}
int32_t totalBitrate = 0;
@@ -296,6 +248,9 @@
// Widevine sources might re-initialize crypto when starting, if we delay
// this to start(), all data buffered during prepare would be wasted.
// (We don't actually start reading until start().)
+ //
+ // TODO: this logic may no longer be relevant after the removal of widevine
+ // support
if (mAudioTrack.mSource != NULL && mAudioTrack.mSource->start() != OK) {
ALOGE("failed to start audio track!");
return UNKNOWN_ERROR;
@@ -378,11 +333,8 @@
if (!mUri.empty()) {
const char* uri = mUri.c_str();
String8 contentType;
- mIsWidevine = !strncasecmp(uri, "widevine://", 11);
- if (!strncasecmp("http://", uri, 7)
- || !strncasecmp("https://", uri, 8)
- || mIsWidevine) {
+ if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
mHttpSource = DataSource::CreateMediaHTTP(mHTTPService);
if (mHttpSource == NULL) {
ALOGE("Failed to create http source!");
@@ -395,8 +347,6 @@
mHTTPService, uri, &mUriHeaders, &contentType,
static_cast<HTTPBase *>(mHttpSource.get()));
} else {
- mIsWidevine = false;
-
mDataSource = new FileSource(mFd, mOffset, mLength);
mFd = -1;
}
@@ -412,13 +362,9 @@
mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
}
- // For widevine or other cached streaming cases, we need to wait for
- // enough buffering before reporting prepared.
- // Note that even when URL doesn't start with widevine://, mIsWidevine
- // could still be set to true later, if the streaming or file source
- // is sniffed to be widevine. We don't want to buffer for file source
- // in that case, so must check the flag now.
- mIsStreaming = (mIsWidevine || mCachedSource != NULL);
+ // For cached streaming cases, we need to wait for enough
+ // buffering before reporting prepared.
+ mIsStreaming = (mCachedSource != NULL);
// init extractor from data source
status_t err = initFromDataSource();
@@ -450,6 +396,9 @@
if (mIsSecure) {
// secure decoders must be instantiated before starting widevine source
+ //
+ // TODO: mIsSecure and FLAG_SECURE may be obsolete, revisit after
+ // removing widevine
sp<AMessage> reply = new AMessage(kWhatSecureDecodersInstantiated, this);
notifyInstantiateSecureDecoders(reply);
} else {
@@ -476,7 +425,7 @@
if (mIsStreaming) {
if (mBufferingMonitorLooper == NULL) {
- mBufferingMonitor->prepare(mCachedSource, mWVMExtractor, mDurationUs, mBitrate,
+ mBufferingMonitor->prepare(mCachedSource, mDurationUs, mBitrate,
mIsStreaming);
mBufferingMonitorLooper = new ALooper;
@@ -536,12 +485,6 @@
// nothing to do, just account for DRM playback status
setDrmPlaybackStatusIfNeeded(Playback::STOP, 0);
mStarted = false;
- if (mIsWidevine || mIsSecure) {
- // For widevine or secure sources we need to prevent any further reads.
- sp<AMessage> msg = new AMessage(kWhatStopWidevine, this);
- sp<AMessage> response;
- (void) msg->postAndAwaitResponse(&response);
- }
}
void NuPlayer::GenericSource::pause() {
@@ -665,8 +608,10 @@
} else {
timeUs = mVideoLastDequeueTimeUs;
}
- readBuffer(trackType, timeUs, false /* precise */, &actualTimeUs, formatChange);
- readBuffer(counterpartType, -1, false /* precise */, NULL, !formatChange);
+ readBuffer(trackType, timeUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
+ &actualTimeUs, formatChange);
+ readBuffer(counterpartType, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
+ NULL, !formatChange);
ALOGV("timeUs %lld actualTimeUs %lld", (long long)timeUs, (long long)actualTimeUs);
break;
@@ -717,20 +662,6 @@
break;
}
- case kWhatStopWidevine:
- {
- // mStopRead is only used for Widevine to prevent the video source
- // from being read while the associated video decoder is shutting down.
- mStopRead = true;
- if (mVideoTrack.mSource != NULL) {
- mVideoTrack.mPackets->clear();
- }
- sp<AMessage> response = new AMessage;
- sp<AReplyToken> replyID;
- CHECK(msg->senderAwaitsResponse(&replyID));
- response->postReply(replyID);
- break;
- }
default:
Source::onMessageReceived(msg);
break;
@@ -759,7 +690,7 @@
CHECK(msg->findInt64("timeUs", &timeUs));
int64_t subTimeUs;
- readBuffer(type, timeUs, false /* precise */, &subTimeUs);
+ readBuffer(type, timeUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &subTimeUs);
int64_t delayUs = subTimeUs - timeUs;
if (msg->what() == kWhatFetchSubtitleData) {
@@ -790,7 +721,7 @@
}
int64_t nextSubTimeUs;
- readBuffer(type, -1, false /* precise */, &nextSubTimeUs);
+ readBuffer(type, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &nextSubTimeUs);
sp<ABuffer> buffer;
status_t dequeueStatus = packets->dequeueAccessUnit(&buffer);
@@ -886,11 +817,6 @@
return -EWOULDBLOCK;
}
- if (mIsWidevine && !audio) {
- // try to read a buffer as we may not have been able to the last time
- postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
- }
-
status_t finalResult;
if (!track->mPackets->hasBufferAvailable(&finalResult)) {
if (finalResult == OK) {
@@ -1186,10 +1112,10 @@
return INVALID_OPERATION;
}
-status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs, bool precise) {
+status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
sp<AMessage> msg = new AMessage(kWhatSeek, this);
msg->setInt64("seekTimeUs", seekTimeUs);
- msg->setInt32("precise", precise);
+ msg->setInt32("mode", mode);
sp<AMessage> response;
status_t err = msg->postAndAwaitResponse(&response);
@@ -1202,12 +1128,12 @@
void NuPlayer::GenericSource::onSeek(const sp<AMessage>& msg) {
int64_t seekTimeUs;
- int32_t precise;
+ int32_t mode;
CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
- CHECK(msg->findInt32("precise", &precise));
+ CHECK(msg->findInt32("mode", &mode));
sp<AMessage> response = new AMessage;
- status_t err = doSeek(seekTimeUs, precise);
+ status_t err = doSeek(seekTimeUs, (MediaPlayerSeekMode)mode);
response->setInt32("err", err);
sp<AReplyToken> replyID;
@@ -1215,19 +1141,22 @@
response->postReply(replyID);
}
-status_t NuPlayer::GenericSource::doSeek(int64_t seekTimeUs, bool precise) {
+status_t NuPlayer::GenericSource::doSeek(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
mBufferingMonitor->updateDequeuedBufferTime(-1ll);
// If the Widevine source is stopped, do not attempt to read any
// more buffers.
+ //
+ // TODO: revisit after widevine is removed. May be able to
+ // combine mStopRead with mStarted.
if (mStopRead) {
return INVALID_OPERATION;
}
if (mVideoTrack.mSource != NULL) {
int64_t actualTimeUs;
- readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, precise, &actualTimeUs);
+ readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, mode, &actualTimeUs);
- if (!precise) {
+ if (mode != MediaPlayerSeekMode::SEEK_CLOSEST) {
seekTimeUs = actualTimeUs;
}
mVideoLastDequeueTimeUs = actualTimeUs;
@@ -1361,9 +1290,12 @@
}
void NuPlayer::GenericSource::readBuffer(
- media_track_type trackType, int64_t seekTimeUs, bool precise,
+ media_track_type trackType, int64_t seekTimeUs, MediaPlayerSeekMode mode,
int64_t *actualTimeUs, bool formatChange) {
// Do not read data if Widevine source is stopped
+ //
+ // TODO: revisit after widevine is removed. May be able to
+ // combine mStopRead with mStarted.
if (mStopRead) {
return;
}
@@ -1372,19 +1304,11 @@
switch (trackType) {
case MEDIA_TRACK_TYPE_VIDEO:
track = &mVideoTrack;
- if (mIsWidevine) {
- maxBuffers = 2;
- } else {
- maxBuffers = 8; // too large of a number may influence seeks
- }
+ maxBuffers = 8; // too large of a number may influence seeks
break;
case MEDIA_TRACK_TYPE_AUDIO:
track = &mAudioTrack;
- if (mIsWidevine) {
- maxBuffers = 8;
- } else {
- maxBuffers = 64;
- }
+ maxBuffers = 64;
break;
case MEDIA_TRACK_TYPE_SUBTITLE:
track = &mSubtitleTrack;
@@ -1408,13 +1332,13 @@
bool seeking = false;
if (seekTimeUs >= 0) {
- options.setSeekTo(seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
+ options.setSeekTo(seekTimeUs, mode);
seeking = true;
}
- const bool couldReadMultiple = (!mIsWidevine && track->mSource->supportReadMultiple());
+ const bool couldReadMultiple = (track->mSource->supportReadMultiple());
- if (mIsWidevine || couldReadMultiple) {
+ if (couldReadMultiple) {
options.setNonBlocking();
}
@@ -1461,7 +1385,8 @@
}
if (seeking && buffer != nullptr) {
sp<AMessage> meta = buffer->meta();
- if (meta != nullptr && precise && seekTimeUs > timeUs) {
+ if (meta != nullptr && mode == MediaPlayerSeekMode::SEEK_CLOSEST
+ && seekTimeUs > timeUs) {
sp<AMessage> extra = new AMessage;
extra->setInt64("resume-at-mediaTimeUs", seekTimeUs);
meta->setMessage("extra", extra);
@@ -1535,17 +1460,16 @@
void NuPlayer::GenericSource::BufferingMonitor::prepare(
const sp<NuCachedSource2> &cachedSource,
- const sp<WVMExtractor> &wvmExtractor,
int64_t durationUs,
int64_t bitrate,
bool isStreaming) {
Mutex::Autolock _l(mLock);
- prepare_l(cachedSource, wvmExtractor, durationUs, bitrate, isStreaming);
+ prepare_l(cachedSource, durationUs, bitrate, isStreaming);
}
void NuPlayer::GenericSource::BufferingMonitor::stop() {
Mutex::Autolock _l(mLock);
- prepare_l(NULL /* cachedSource */, NULL /* wvmExtractor */, -1 /* durationUs */,
+ prepare_l(NULL /* cachedSource */, -1 /* durationUs */,
-1 /* bitrate */, false /* isStreaming */);
}
@@ -1600,22 +1524,17 @@
void NuPlayer::GenericSource::BufferingMonitor::prepare_l(
const sp<NuCachedSource2> &cachedSource,
- const sp<WVMExtractor> &wvmExtractor,
int64_t durationUs,
int64_t bitrate,
bool isStreaming) {
- ALOGW_IF(wvmExtractor != NULL && cachedSource != NULL,
- "WVMExtractor and NuCachedSource are both present when "
- "BufferingMonitor::prepare_l is called, ignore NuCachedSource");
mCachedSource = cachedSource;
- mWVMExtractor = wvmExtractor;
mDurationUs = durationUs;
mBitrate = bitrate;
mIsStreaming = isStreaming;
mAudioTimeUs = 0;
mVideoTimeUs = 0;
- mPrepareBuffering = (cachedSource != NULL || wvmExtractor != NULL);
+ mPrepareBuffering = (cachedSource != NULL);
cancelPollBuffering_l();
mOffloadAudio = false;
mFirstDequeuedBufferRealUs = -1ll;
@@ -1699,9 +1618,7 @@
int32_t kbps = 0;
status_t err = UNKNOWN_ERROR;
- if (mWVMExtractor != NULL) {
- err = mWVMExtractor->getEstimatedBandwidthKbps(&kbps);
- } else if (mCachedSource != NULL) {
+ if (mCachedSource != NULL) {
err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
}
@@ -1741,10 +1658,7 @@
int64_t cachedDurationUs = -1ll;
ssize_t cachedDataRemaining = -1;
- if (mWVMExtractor != NULL) {
- cachedDurationUs =
- mWVMExtractor->getCachedDurationUs(&finalStatus);
- } else if (mCachedSource != NULL) {
+ if (mCachedSource != NULL) {
cachedDataRemaining =
mCachedSource->approxDataRemaining(&finalStatus);
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index 368d11c..38d8616 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -37,7 +37,6 @@
struct MediaSource;
class MediaBuffer;
struct NuCachedSource2;
-class WVMExtractor;
struct NuPlayer::GenericSource : public NuPlayer::Source {
GenericSource(const sp<AMessage> ¬ify, bool uidValid, uid_t uid);
@@ -71,7 +70,9 @@
virtual sp<AMessage> getTrackInfo(size_t trackIndex) const;
virtual ssize_t getSelectedTrack(media_track_type type) const;
virtual status_t selectTrack(size_t trackIndex, bool select, int64_t timeUs);
- virtual status_t seekTo(int64_t seekTimeUs, bool precise = false) override;
+ virtual status_t seekTo(
+ int64_t seekTimeUs,
+ MediaPlayerSeekMode mode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC) override;
virtual status_t setBuffers(bool audio, Vector<MediaBuffer *> &buffers);
@@ -101,7 +102,6 @@
kWhatSelectTrack,
kWhatSeek,
kWhatReadBuffer,
- kWhatStopWidevine,
kWhatStart,
kWhatResume,
kWhatSecureDecodersInstantiated,
@@ -121,7 +121,6 @@
// Set up state.
void prepare(const sp<NuCachedSource2> &cachedSource,
- const sp<WVMExtractor> &wvmExtractor,
int64_t durationUs,
int64_t bitrate,
bool isStreaming);
@@ -155,7 +154,6 @@
sp<AMessage> mNotify;
sp<NuCachedSource2> mCachedSource;
- sp<WVMExtractor> mWVMExtractor;
int64_t mDurationUs;
int64_t mBitrate;
bool mIsStreaming;
@@ -175,7 +173,6 @@
int64_t mlastDequeuedBufferMediaUs;
void prepare_l(const sp<NuCachedSource2> &cachedSource,
- const sp<WVMExtractor> &wvmExtractor,
int64_t durationUs,
int64_t bitrate,
bool isStreaming);
@@ -204,7 +201,6 @@
int32_t mFetchTimedTextDataGeneration;
int64_t mDurationUs;
bool mAudioIsVorbis;
- bool mIsWidevine;
bool mIsSecure;
bool mIsStreaming;
bool mUIDValid;
@@ -219,7 +215,6 @@
sp<DataSource> mDataSource;
sp<NuCachedSource2> mCachedSource;
sp<DataSource> mHttpSource;
- sp<WVMExtractor> mWVMExtractor;
sp<MetaData> mFileMeta;
DrmManagerClient *mDrmManagerClient;
sp<DecryptHandle> mDecryptHandle;
@@ -258,7 +253,7 @@
status_t doSelectTrack(size_t trackIndex, bool select, int64_t timeUs);
void onSeek(const sp<AMessage>& msg);
- status_t doSeek(int64_t seekTimeUs, bool precise);
+ status_t doSeek(int64_t seekTimeUs, MediaPlayerSeekMode mode);
void onPrepareAsync();
@@ -280,14 +275,15 @@
void postReadBuffer(media_track_type trackType);
void onReadBuffer(const sp<AMessage>& msg);
- // |precise| is a modifier of |seekTimeUs|.
- // When |precise| is true, the buffer read shall include an item indicating skipping
- // rendering all buffers with timestamp earlier than |seekTimeUs|.
- // When |precise| is false, the buffer read will not include the item as above in order
+ // When |mode| is MediaPlayerSeekMode::SEEK_CLOSEST, the buffer read shall
+ // include an item indicating skipping rendering all buffers with timestamp
+ // earlier than |seekTimeUs|.
+ // For other modes, the buffer read will not include the item as above in order
// to facilitate fast seek operation.
void readBuffer(
media_track_type trackType,
- int64_t seekTimeUs = -1ll, bool precise = false,
+ int64_t seekTimeUs = -1ll,
+ MediaPlayerSeekMode mode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC,
int64_t *actualTimeUs = NULL, bool formatChange = false);
void queueDiscontinuityIfNeeded(
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
index 1a6a233..51bfad4 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -214,8 +214,8 @@
return (err == OK || err == BAD_VALUE) ? (status_t)OK : err;
}
-status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs, bool precise) {
- return mLiveSession->seekTo(seekTimeUs, precise);
+status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
+ return mLiveSession->seekTo(seekTimeUs, mode);
}
void NuPlayer::HTTPLiveSource::pollForRawData(
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
index 16c3c37..45fc8c1 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
@@ -47,7 +47,9 @@
virtual sp<AMessage> getTrackInfo(size_t trackIndex) const;
virtual ssize_t getSelectedTrack(media_track_type /* type */) const;
virtual status_t selectTrack(size_t trackIndex, bool select, int64_t timeUs);
- virtual status_t seekTo(int64_t seekTimeUs, bool precise = false) override;
+ virtual status_t seekTo(
+ int64_t seekTimeUs,
+ MediaPlayerSeekMode mode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC) override;
protected:
virtual ~HTTPLiveSource();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 90b7b7f..1476206 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -70,18 +70,18 @@
};
struct NuPlayer::SeekAction : public Action {
- explicit SeekAction(int64_t seekTimeUs, bool precise)
+ explicit SeekAction(int64_t seekTimeUs, MediaPlayerSeekMode mode)
: mSeekTimeUs(seekTimeUs),
- mPrecise(precise) {
+ mMode(mode) {
}
virtual void execute(NuPlayer *player) {
- player->performSeek(mSeekTimeUs, mPrecise);
+ player->performSeek(mSeekTimeUs, mMode);
}
private:
int64_t mSeekTimeUs;
- bool mPrecise;
+ MediaPlayerSeekMode mMode;
DISALLOW_EVIL_CONSTRUCTORS(SeekAction);
};
@@ -263,9 +263,6 @@
} else {
sp<GenericSource> genericSource =
new GenericSource(notify, mUIDValid, mUID);
- // Don't set FLAG_SECURE on mSourceFlags here for widevine.
- // The correct flags will be updated in Source::kWhatFlagsChanged
- // handler when GenericSource is prepared.
status_t err = genericSource->setDataSource(httpService, url, headers);
@@ -422,10 +419,10 @@
(new AMessage(kWhatReset, this))->post();
}
-void NuPlayer::seekToAsync(int64_t seekTimeUs, bool precise, bool needNotify) {
+void NuPlayer::seekToAsync(int64_t seekTimeUs, MediaPlayerSeekMode mode, bool needNotify) {
sp<AMessage> msg = new AMessage(kWhatSeek, this);
msg->setInt64("seekTimeUs", seekTimeUs);
- msg->setInt32("precise", precise);
+ msg->setInt32("mode", mode);
msg->setInt32("needNotify", needNotify);
msg->post();
}
@@ -684,7 +681,8 @@
int64_t currentPositionUs = 0;
if (getCurrentPosition(¤tPositionUs) == OK) {
mDeferredActions.push_back(
- new SeekAction(currentPositionUs, false /* precise */));
+ new SeekAction(currentPositionUs,
+ MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */));
}
}
@@ -1200,14 +1198,14 @@
case kWhatSeek:
{
int64_t seekTimeUs;
- int32_t precise;
+ int32_t mode;
int32_t needNotify;
CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
- CHECK(msg->findInt32("precise", &precise));
+ CHECK(msg->findInt32("mode", &mode));
CHECK(msg->findInt32("needNotify", &needNotify));
- ALOGV("kWhatSeek seekTimeUs=%lld us, precise=%d, needNotify=%d",
- (long long)seekTimeUs, precise, needNotify);
+ ALOGV("kWhatSeek seekTimeUs=%lld us, mode=%d, needNotify=%d",
+ (long long)seekTimeUs, mode, needNotify);
if (!mStarted) {
// Seek before the player is started. In order to preview video,
@@ -1215,7 +1213,7 @@
// only once if needed. After the player is started, any seek
// operation will go through normal path.
// Audio-only cases are handled separately.
- onStart(seekTimeUs, precise);
+ onStart(seekTimeUs, (MediaPlayerSeekMode)mode);
if (mStarted) {
onPause();
mPausedByClient = true;
@@ -1231,7 +1229,7 @@
FLUSH_CMD_FLUSH /* video */));
mDeferredActions.push_back(
- new SeekAction(seekTimeUs, precise));
+ new SeekAction(seekTimeUs, (MediaPlayerSeekMode)mode));
// After a flush without shutdown, decoder is paused.
// Don't resume it until source seek is done, otherwise it could
@@ -1320,13 +1318,13 @@
return OK;
}
-void NuPlayer::onStart(int64_t startPositionUs, bool precise) {
+void NuPlayer::onStart(int64_t startPositionUs, MediaPlayerSeekMode mode) {
if (!mSourceStarted) {
mSourceStarted = true;
mSource->start();
}
if (startPositionUs > 0) {
- performSeek(startPositionUs, precise);
+ performSeek(startPositionUs, mode);
if (mSource->getFormat(false /* audio */) == NULL) {
return;
}
@@ -1542,7 +1540,7 @@
mRenderer->flush(false /* audio */, false /* notifyComplete */);
}
- performSeek(currentPositionUs, false /* precise */);
+ performSeek(currentPositionUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */);
if (forceNonOffload) {
mRenderer->signalDisableOffloadAudio();
@@ -1670,29 +1668,6 @@
(*decoder)->init();
(*decoder)->configure(format);
- // allocate buffers to decrypt widevine source buffers
- if (!audio && (mSourceFlags & Source::FLAG_SECURE)) {
- Vector<sp<MediaCodecBuffer> > inputBufs;
- CHECK_EQ((*decoder)->getInputBuffers(&inputBufs), (status_t)OK);
-
- Vector<MediaBuffer *> mediaBufs;
- for (size_t i = 0; i < inputBufs.size(); i++) {
- const sp<MediaCodecBuffer> &buffer = inputBufs[i];
- MediaBuffer *mbuf = new MediaBuffer(buffer->data(), buffer->size());
- mediaBufs.push(mbuf);
- }
-
- status_t err = mSource->setBuffers(audio, mediaBufs);
- if (err != OK) {
- for (size_t i = 0; i < mediaBufs.size(); ++i) {
- mediaBufs[i]->release();
- }
- mediaBufs.clear();
- ALOGE("Secure source didn't support secure mediaBufs.");
- return err;
- }
- }
-
if (!audio) {
sp<AMessage> params = new AMessage();
float rate = getFrameRate();
@@ -1999,9 +1974,9 @@
}
}
-void NuPlayer::performSeek(int64_t seekTimeUs, bool precise) {
- ALOGV("performSeek seekTimeUs=%lld us (%.2f secs), precise=%d",
- (long long)seekTimeUs, seekTimeUs / 1E6, precise);
+void NuPlayer::performSeek(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
+ ALOGV("performSeek seekTimeUs=%lld us (%.2f secs), mode=%d",
+ (long long)seekTimeUs, seekTimeUs / 1E6, mode);
if (mSource == NULL) {
// This happens when reset occurs right before the loop mode
@@ -2012,7 +1987,7 @@
return;
}
mPreviousSeekTimeUs = seekTimeUs;
- mSource->seekTo(seekTimeUs, precise);
+ mSource->seekTo(seekTimeUs, mode);
++mTimedTextGeneration;
// everything's flushed, continue playback.
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 3ae2ada..c8b0102 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -70,7 +70,10 @@
// Will notify the driver through "notifySeekComplete" once finished
// and needNotify is true.
- void seekToAsync(int64_t seekTimeUs, bool precise = false, bool needNotify = false);
+ void seekToAsync(
+ int64_t seekTimeUs,
+ MediaPlayerSeekMode mode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC,
+ bool needNotify = false);
status_t setVideoScalingMode(int32_t mode);
status_t getTrackInfo(Parcel* reply) const;
@@ -245,7 +248,9 @@
void handleFlushComplete(bool audio, bool isDecoder);
void finishFlushIfPossible();
- void onStart(int64_t startPositionUs = -1, bool precise = false);
+ void onStart(
+ int64_t startPositionUs = -1,
+ MediaPlayerSeekMode mode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC);
void onResume();
void onPause();
@@ -263,7 +268,7 @@
void processDeferredActions();
- void performSeek(int64_t seekTimeUs, bool precise);
+ void performSeek(int64_t seekTimeUs, MediaPlayerSeekMode mode);
void performDecoderFlush(FlushCommand audio, FlushCommand video);
void performReset();
void performScanSources();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index d2452af..e1d426a 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -411,17 +411,7 @@
}
void NuPlayer::Decoder::onSetRenderer(const sp<Renderer> &renderer) {
- bool hadNoRenderer = (mRenderer == NULL);
mRenderer = renderer;
- if (hadNoRenderer && mRenderer != NULL) {
- // this means that the widevine legacy source is ready
- onRequestInputBuffers();
- }
-}
-
-void NuPlayer::Decoder::onGetInputBuffers(
- Vector<sp<MediaCodecBuffer> > *dstBuffers) {
- CHECK_EQ((status_t)OK, mCodec->getWidevineLegacyBuffers(dstBuffers));
}
void NuPlayer::Decoder::onResume(bool notifyComplete) {
@@ -518,9 +508,7 @@
* returns true if we should request more data
*/
bool NuPlayer::Decoder::doRequestBuffers() {
- // mRenderer is only NULL if we have a legacy widevine source that
- // is not yet ready. In this case we must not fetch input.
- if (isDiscontinuityPending() || mRenderer == NULL) {
+ if (isDiscontinuityPending()) {
return false;
}
status_t err = OK;
@@ -878,40 +866,6 @@
bool hasBuffer = msg->findBuffer("buffer", &buffer);
bool needsCopy = true;
- // handle widevine classic source - that fills an arbitrary input buffer
- MediaBuffer *mediaBuffer = NULL;
- if (hasBuffer) {
- mediaBuffer = (MediaBuffer *)(buffer->getMediaBufferBase());
- if (mediaBuffer != NULL) {
- // likely filled another buffer than we requested: adjust buffer index
- size_t ix;
- for (ix = 0; ix < mInputBuffers.size(); ix++) {
- const sp<MediaCodecBuffer> &buf = mInputBuffers[ix];
- if (buf->data() == mediaBuffer->data()) {
- // all input buffers are dequeued on start, hence the check
- if (!mInputBufferIsDequeued[ix]) {
- ALOGV("[%s] received MediaBuffer for #%zu instead of #%zu",
- mComponentName.c_str(), ix, bufferIx);
- mediaBuffer->release();
- return false;
- }
-
- // TRICKY: need buffer for the metadata, so instead, set
- // codecBuffer to the same (though incorrect) buffer to
- // avoid a memcpy into the codecBuffer
- codecBuffer = new MediaCodecBuffer(codecBuffer->format(), buffer);
- codecBuffer->setRange(
- mediaBuffer->range_offset(),
- mediaBuffer->range_length());
- bufferIx = ix;
- needsCopy = false;
- break;
- }
- }
- CHECK(ix < mInputBuffers.size());
- }
- }
-
if (buffer == NULL /* includes !hasBuffer */) {
int32_t streamErr = ERROR_END_OF_STREAM;
CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
@@ -981,18 +935,11 @@
timeUs,
flags);
if (err != OK) {
- if (mediaBuffer != NULL) {
- mediaBuffer->release();
- }
ALOGE("Failed to queue input buffer for %s (err=%d)",
mComponentName.c_str(), err);
handleError(err);
} else {
mInputBufferIsDequeued.editItemAt(bufferIx) = false;
- if (mediaBuffer != NULL) {
- CHECK(mMediaBuffers[bufferIx] == NULL);
- mMediaBuffers.editItemAt(bufferIx) = mediaBuffer;
- }
}
}
return true;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
index a576ae5..fcf601b 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
@@ -47,7 +47,6 @@
virtual void onConfigure(const sp<AMessage> &format);
virtual void onSetParameters(const sp<AMessage> ¶ms);
virtual void onSetRenderer(const sp<Renderer> &renderer);
- virtual void onGetInputBuffers(Vector<sp<MediaCodecBuffer> > *dstBuffers);
virtual void onResume(bool notifyComplete);
virtual void onFlush();
virtual void onShutdown(bool notifyComplete);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp
index 9c007ae..1210dc9 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp
@@ -92,14 +92,6 @@
PostAndAwaitResponse(msg, &response);
}
-status_t NuPlayer::DecoderBase::getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
- sp<AMessage> msg = new AMessage(kWhatGetInputBuffers, this);
- msg->setPointer("buffers", buffers);
-
- sp<AMessage> response;
- return PostAndAwaitResponse(msg, &response);
-}
-
void NuPlayer::DecoderBase::signalFlush() {
(new AMessage(kWhatFlush, this))->post();
}
@@ -166,20 +158,6 @@
break;
}
- case kWhatGetInputBuffers:
- {
- sp<AReplyToken> replyID;
- CHECK(msg->senderAwaitsResponse(&replyID));
-
- Vector<sp<MediaCodecBuffer> > *dstBuffers;
- CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
-
- onGetInputBuffers(dstBuffers);
-
- (new AMessage)->postReply(replyID);
- break;
- }
-
case kWhatRequestInputBuffers:
{
mRequestInputBuffersPending = false;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h
index 6f4ead6..6811903 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h
@@ -43,7 +43,6 @@
void setRenderer(const sp<Renderer> &renderer);
virtual status_t setVideoSurface(const sp<Surface> &) { return INVALID_OPERATION; }
- status_t getInputBuffers(Vector<sp<MediaCodecBuffer> > *dstBuffers) const;
void signalFlush();
void signalResume(bool notifyComplete);
void initiateShutdown();
@@ -71,7 +70,6 @@
virtual void onConfigure(const sp<AMessage> &format) = 0;
virtual void onSetParameters(const sp<AMessage> ¶ms) = 0;
virtual void onSetRenderer(const sp<Renderer> &renderer) = 0;
- virtual void onGetInputBuffers(Vector<sp<MediaCodecBuffer> > *dstBuffers) = 0;
virtual void onResume(bool notifyComplete) = 0;
virtual void onFlush() = 0;
virtual void onShutdown(bool notifyComplete) = 0;
@@ -91,7 +89,6 @@
kWhatSetParameters = 'setP',
kWhatSetRenderer = 'setR',
kWhatPause = 'paus',
- kWhatGetInputBuffers = 'gInB',
kWhatRequestInputBuffers = 'reqB',
kWhatFlush = 'flus',
kWhatShutdown = 'shuD',
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
index e4767ff..cb668e4 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
@@ -93,11 +93,6 @@
"ignoring request to change renderer");
}
-void NuPlayer::DecoderPassThrough::onGetInputBuffers(
- Vector<sp<MediaCodecBuffer> > * /* dstBuffers */) {
- ALOGE("onGetInputBuffers() called unexpectedly");
-}
-
bool NuPlayer::DecoderPassThrough::isStaleReply(const sp<AMessage> &msg) {
int32_t generation;
CHECK(msg->findInt32("generation", &generation));
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
index 9af25ff..173387a 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
@@ -38,7 +38,6 @@
virtual void onConfigure(const sp<AMessage> &format);
virtual void onSetParameters(const sp<AMessage> ¶ms);
virtual void onSetRenderer(const sp<Renderer> &renderer);
- virtual void onGetInputBuffers(Vector<sp<MediaCodecBuffer> > *dstBuffers);
virtual void onResume(bool notifyComplete);
virtual void onFlush();
virtual void onShutdown(bool notifyComplete);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 7f287e3..3efa54c 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -208,7 +208,8 @@
mAtEOS = false;
mState = STATE_STOPPED_AND_PREPARING;
mIsAsyncPrepare = false;
- mPlayer->seekToAsync(0, false /* precise */, true /* needNotify */);
+ mPlayer->seekToAsync(0, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
+ true /* needNotify */);
while (mState == STATE_STOPPED_AND_PREPARING) {
mCondition.wait(mLock);
}
@@ -233,7 +234,8 @@
mAtEOS = false;
mState = STATE_STOPPED_AND_PREPARING;
mIsAsyncPrepare = true;
- mPlayer->seekToAsync(0, false /* precise */, true /* needNotify */);
+ mPlayer->seekToAsync(0, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
+ true /* needNotify */);
return OK;
default:
return INVALID_OPERATION;
@@ -382,8 +384,8 @@
return mPlayer->getSyncSettings(sync, videoFps);
}
-status_t NuPlayerDriver::seekTo(int msec, bool precise) {
- ALOGD("seekTo(%p) (%d ms, %d) at state %d", this, msec, precise, mState);
+status_t NuPlayerDriver::seekTo(int msec, MediaPlayerSeekMode mode) {
+ ALOGD("seekTo(%p) (%d ms, %d) at state %d", this, msec, mode, mState);
Mutex::Autolock autoLock(mLock);
int64_t seekTimeUs = msec * 1000ll;
@@ -398,7 +400,7 @@
mSeekInProgress = true;
// seeks can take a while, so we essentially paused
notifyListener_l(MEDIA_PAUSED);
- mPlayer->seekToAsync(seekTimeUs, precise, true /* needNotify */);
+ mPlayer->seekToAsync(seekTimeUs, mode, true /* needNotify */);
break;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 034b3f9..317b34c 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -53,7 +53,8 @@
virtual status_t getPlaybackSettings(AudioPlaybackRate *rate);
virtual status_t setSyncSettings(const AVSyncSettings &sync, float videoFpsHint);
virtual status_t getSyncSettings(AVSyncSettings *sync, float *videoFps);
- virtual status_t seekTo(int msec, bool precise = false);
+ virtual status_t seekTo(
+ int msec, MediaPlayerSeekMode mode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC);
virtual status_t getCurrentPosition(int *msec);
virtual status_t getDuration(int *msec);
virtual status_t reset();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index fe4fc63..5197167 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -104,8 +104,9 @@
return INVALID_OPERATION;
}
- // Refer to comment of seekTo in IMediaPlayer.h for meaning of |precise|.
- virtual status_t seekTo(int64_t /* seekTimeUs */, bool /* precise */ = false) {
+ virtual status_t seekTo(
+ int64_t /* seekTimeUs */,
+ MediaPlayerSeekMode /* mode */ = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC) {
return INVALID_OPERATION;
}
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index f430f03..fb1f31a 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -279,11 +279,11 @@
return OK;
}
-status_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs, bool precise) {
+status_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
sp<AMessage> msg = new AMessage(kWhatPerformSeek, this);
msg->setInt32("generation", ++mSeekGeneration);
msg->setInt64("timeUs", seekTimeUs);
- msg->setInt32("precise", precise);
+ msg->setInt32("mode", mode);
sp<AMessage> response;
status_t err = msg->postAndAwaitResponse(&response);
@@ -466,12 +466,12 @@
}
int64_t seekTimeUs;
- int32_t precise;
+ int32_t mode;
CHECK(msg->findInt64("timeUs", &seekTimeUs));
- CHECK(msg->findInt32("precise", &precise));
+ CHECK(msg->findInt32("mode", &mode));
- // TODO: add "precise" to performSeek.
- performSeek(seekTimeUs);
+ // TODO: add "mode" to performSeek.
+ performSeek(seekTimeUs/*, (MediaPlayerSeekMode)mode */);
return;
} else if (msg->what() == kWhatPollBuffering) {
onPollBuffering();
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/RTSPSource.h
index b2962ed6..363f8bb 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.h
@@ -49,7 +49,9 @@
virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
virtual status_t getDuration(int64_t *durationUs);
- virtual status_t seekTo(int64_t seekTimeUs, bool precise = false) override;
+ virtual status_t seekTo(
+ int64_t seekTimeUs,
+ MediaPlayerSeekMode mode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC) override;
void onMessageReceived(const sp<AMessage> &msg);
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index cf0a031..21c90f0 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1201,6 +1201,10 @@
info.mDequeuedAt = mDequeueCounter;
info.mData = new MediaCodecBuffer(mOutputFormat, new ABuffer(bufferSize));
+
+ // Initialize fence fd to -1 to avoid warning in freeBuffer().
+ ((VideoNativeMetadata *)info.mData->base())->nFenceFd = -1;
+
info.mCodecData = info.mData;
err = mOMXNode->useBuffer(kPortIndexOutput, OMXBuffer::sPreset, &info.mBufferID);
@@ -1836,11 +1840,8 @@
inputFormat->setInt32("adaptive-playback", true);
}
}
- // Fall back to legacy mode (use fixed ANWBuffer)
- err = setPortMode(kPortIndexOutput, IOMX::kPortModePresetANWBuffer);
- if (err != OK) {
- return err;
- }
+ // allow failure
+ err = OK;
} else {
ALOGV("[%s] setPortMode on output to %s succeeded",
mComponentName.c_str(), asString(IOMX::kPortModeDynamicANWBuffer));
@@ -1873,6 +1874,12 @@
if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) {
usingSwRenderer = true;
haveNativeWindow = false;
+ (void)setPortMode(kPortIndexOutput, IOMX::kPortModePresetByteBuffer);
+ } else if (haveNativeWindow && !storingMetadataInDecodedBuffers()) {
+ err = setPortMode(kPortIndexOutput, IOMX::kPortModePresetANWBuffer);
+ if (err != OK) {
+ return err;
+ }
}
if (encoder) {
@@ -1887,10 +1894,8 @@
if (haveNativeWindow) {
mNativeWindow = static_cast<Surface *>(obj.get());
- }
- // fallback for devices that do not handle flex-YUV for native buffers
- if (haveNativeWindow) {
+ // fallback for devices that do not handle flex-YUV for native buffers
int32_t requestedColorFormat = OMX_COLOR_FormatUnused;
if (msg->findInt32("color-format", &requestedColorFormat) &&
requestedColorFormat == OMX_COLOR_FormatYUV420Flexible) {
@@ -5258,7 +5263,7 @@
ALOGE_IF("[%s] failed to release codec instance: err=%d",
mCodec->mComponentName.c_str(), err);
sp<AMessage> notify = mCodec->mNotify->dup();
- notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
+ notify->setInt32("what", CodecBase::kWhatReleaseCompleted);
notify->post();
break;
}
@@ -6147,7 +6152,8 @@
"cannot keep component allocated on shutdown in Uninitialized state");
sp<AMessage> notify = mCodec->mNotify->dup();
- notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
+ notify->setInt32("what", keepComponentAllocated ?
+ CodecBase::kWhatStopCompleted : CodecBase::kWhatReleaseCompleted);
notify->post();
handled = true;
@@ -6344,7 +6350,8 @@
if (mCodec->mExplicitShutdown) {
sp<AMessage> notify = mCodec->mNotify->dup();
- notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
+ notify->setInt32("what", keepComponentAllocated ?
+ CodecBase::kWhatStopCompleted : CodecBase::kWhatReleaseCompleted);
notify->post();
mCodec->mExplicitShutdown = false;
}
@@ -7346,8 +7353,7 @@
case kWhatShutdown:
{
- // We're already doing that...
-
+ mCodec->deferMessage(msg);
handled = true;
break;
}
@@ -7456,8 +7462,7 @@
switch (msg->what()) {
case kWhatShutdown:
{
- // We're already doing that...
-
+ mCodec->deferMessage(msg);
handled = true;
break;
}
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 5e921e3..9e3b35a 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -59,7 +59,6 @@
VBRISeeker.cpp \
VideoFrameScheduler.cpp \
WAVExtractor.cpp \
- WVMExtractor.cpp \
XINGSeeker.cpp \
avc_utils.cpp \
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 163a527..c78f1e9 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -31,7 +31,6 @@
#include "include/NuCachedSource2.h"
#include "include/OggExtractor.h"
#include "include/WAVExtractor.h"
-#include "include/WVMExtractor.h"
#include "matroska/MatroskaExtractor.h"
@@ -175,10 +174,6 @@
RegisterSniffer_l(SniffMP3);
RegisterSniffer_l(SniffAAC);
RegisterSniffer_l(SniffMPEG2PS);
- if (getuid() == AID_MEDIA) {
- // WVM only in the media server process
- RegisterSniffer_l(SniffWVM);
- }
RegisterSniffer_l(SniffMidi);
char value[PROPERTY_VALUE_MAX];
@@ -200,14 +195,10 @@
*contentType = "";
}
- bool isWidevine = !strncasecmp("widevine://", uri, 11);
-
sp<DataSource> source;
if (!strncasecmp("file://", uri, 7)) {
source = new FileSource(uri + 7);
- } else if (!strncasecmp("http://", uri, 7)
- || !strncasecmp("https://", uri, 8)
- || isWidevine) {
+ } else if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
if (httpService == NULL) {
ALOGE("Invalid http service!");
return NULL;
@@ -222,14 +213,6 @@
httpSource = new MediaHTTP(conn);
}
- String8 tmp;
- if (isWidevine) {
- tmp = String8("http://");
- tmp.append(uri + 11);
-
- uri = tmp.string();
- }
-
String8 cacheConfig;
bool disconnectAtHighwatermark;
KeyedVector<String8, String8> nonCacheSpecificHeaders;
@@ -246,20 +229,14 @@
return NULL;
}
- if (!isWidevine) {
- if (contentType != NULL) {
- *contentType = httpSource->getMIMEType();
- }
-
- source = NuCachedSource2::Create(
- httpSource,
- cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
- disconnectAtHighwatermark);
- } else {
- // We do not want that prefetching, caching, datasource wrapper
- // in the widevine:// case.
- source = httpSource;
+ if (contentType != NULL) {
+ *contentType = httpSource->getMIMEType();
}
+
+ source = NuCachedSource2::Create(
+ httpSource,
+ cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
+ disconnectAtHighwatermark);
} else if (!strncasecmp("data:", uri, 5)) {
source = DataURISource::Create(uri);
} else {
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 80860db..5382689 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -843,16 +843,6 @@
return OK;
}
-status_t MediaCodec::getWidevineLegacyBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
- sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
- msg->setInt32("portIndex", kPortIndexInput);
- msg->setPointer("buffers", buffers);
- msg->setInt32("widevine", true);
-
- sp<AMessage> response;
- return PostAndAwaitResponse(msg, &response);
-}
-
status_t MediaCodec::getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
msg->setInt32("portIndex", kPortIndexInput);
@@ -1560,19 +1550,26 @@
break;
}
- case CodecBase::kWhatShutdownCompleted:
+ case CodecBase::kWhatStopCompleted:
{
- if (mState == UNINITIALIZED) {
- // Ignore shutdown complete if we're already released.
+ if (mState != STOPPING) {
+ ALOGW("Received kWhatStopCompleted in state %d", mState);
break;
}
- if (mState == STOPPING) {
- setState(INITIALIZED);
- } else {
- CHECK_EQ(mState, RELEASING);
- setState(UNINITIALIZED);
- mComponentName.clear();
+ setState(INITIALIZED);
+ (new AMessage)->postReply(mReplyID);
+ break;
+ }
+
+ case CodecBase::kWhatReleaseCompleted:
+ {
+ if (mState != RELEASING) {
+ ALOGW("Received kWhatReleaseCompleted in state %d", mState);
+ break;
}
+ setState(UNINITIALIZED);
+ mComponentName.clear();
+
mFlags &= ~kFlagIsComponentAllocated;
mResourceManagerService->removeResource(getId(mResourceManagerClient));
@@ -2132,12 +2129,7 @@
{
sp<AReplyToken> replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
- // Unfortunately widevine legacy source requires knowing all of the
- // codec input buffers, so we have to provide them even in async mode.
- int32_t widevine = 0;
- msg->findInt32("widevine", &widevine);
-
- if (!isExecuting() || ((mFlags & kFlagIsAsync) && !widevine)) {
+ if (!isExecuting() || (mFlags & kFlagIsAsync)) {
PostReplyWithError(replyID, INVALID_OPERATION);
break;
} else if (mFlags & kFlagStickyError) {
@@ -2370,8 +2362,6 @@
if (info->mNotify != NULL) {
sp<AMessage> msg = info->mNotify;
info->mNotify = NULL;
- msg->setObject("buffer", (portIndex == kPortIndexInput && mCrypto != NULL)
- ? info->mSecureData : info->mData);
if (isReclaim && info->mOwnedByClient) {
ALOGD("port %d buffer %zu still owned by client when codec is reclaimed",
portIndex, i);
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index f2fdbc9..66bf7cb 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -28,7 +28,6 @@
#include "include/MPEG2PSExtractor.h"
#include "include/MPEG2TSExtractor.h"
#include "include/DRMExtractor.h"
-#include "include/WVMExtractor.h"
#include "include/FLACExtractor.h"
#include "include/AACExtractor.h"
#include "include/MidiExtractor.h"
@@ -151,15 +150,9 @@
ALOGW("creating media extractor in calling process");
return CreateFromService(source, mime);
} else {
- // Check if it's WVM, since WVMExtractor needs to be created in the media server process,
- // not the extractor process.
String8 mime8;
float confidence;
sp<AMessage> meta;
- if (SniffWVM(source, &mime8, &confidence, &meta) &&
- !strcasecmp(mime8, MEDIA_MIMETYPE_CONTAINER_WVM)) {
- return new WVMExtractor(source);
- }
// Check if it's es-based DRM, since DRMExtractor needs to be created in the media server
// process, not the extractor process.
@@ -251,9 +244,6 @@
ret = new MatroskaExtractor(source);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
ret = new MPEG2TSExtractor(source);
- } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_WVM) && getuid() == AID_MEDIA) {
- // Return now. WVExtractor should not have the DrmFlag set in the block below.
- return new WVMExtractor(source);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC_ADTS)) {
ret = new AACExtractor(source, meta);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2PS)) {
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index e3270ed..6f8220f 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -22,7 +22,6 @@
#include "include/ESDS.h"
#include "include/NuCachedSource2.h"
-#include "include/WVMExtractor.h"
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -40,8 +39,7 @@
namespace android {
NuMediaExtractor::NuMediaExtractor()
- : mIsWidevineExtractor(false),
- mTotalBitrate(-1ll),
+ : mTotalBitrate(-1ll),
mDurationUs(-1ll) {
}
@@ -78,48 +76,15 @@
return -ENOENT;
}
- mIsWidevineExtractor = false;
- if (!strncasecmp("widevine://", path, 11)) {
- String8 mimeType;
- float confidence;
- sp<AMessage> dummy;
- bool success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
-
- if (!success
- || strcasecmp(
- mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
- return ERROR_UNSUPPORTED;
- }
-
- sp<WVMExtractor> extractor = new WVMExtractor(dataSource);
- extractor->setAdaptiveStreamingMode(true);
-
- mImpl = extractor;
- mIsWidevineExtractor = true;
- } else {
- mImpl = MediaExtractor::Create(dataSource);
- }
+ mImpl = MediaExtractor::Create(dataSource);
if (mImpl == NULL) {
return ERROR_UNSUPPORTED;
}
sp<MetaData> fileMeta = mImpl->getMetaData();
- const char *containerMime;
- if (fileMeta != NULL
- && fileMeta->findCString(kKeyMIMEType, &containerMime)
- && !strcasecmp(containerMime, "video/wvm")) {
- // We always want to use "cryptoPluginMode" when using the wvm
- // extractor. We can tell that it is this extractor by looking
- // at the container mime type.
- // The cryptoPluginMode ensures that the extractor will actually
- // give us data in a call to MediaSource::read(), unlike its
- // default mode that we used in AwesomePlayer.
- // TODO: change default mode
- static_cast<WVMExtractor *>(mImpl.get())->setCryptoPluginMode(true);
- } else if (mImpl->getDrmFlag()) {
- // For all other drm content, we don't want to expose decrypted
- // content to Java application.
+ if (mImpl->getDrmFlag()) {
+ // Don't expose decrypted content to Java application
mImpl.clear();
mImpl = NULL;
return ERROR_UNSUPPORTED;
@@ -633,15 +598,7 @@
Mutex::Autolock autoLock(mLock);
int64_t bitrate;
- if (mIsWidevineExtractor) {
- sp<WVMExtractor> wvmExtractor =
- static_cast<WVMExtractor *>(mImpl.get());
-
- status_t finalStatus;
- *durationUs = wvmExtractor->getCachedDurationUs(&finalStatus);
- *eos = (finalStatus != OK);
- return true;
- } else if ((mDataSource->flags() & DataSource::kIsCachingDataSource)
+ if ((mDataSource->flags() & DataSource::kIsCachingDataSource)
&& getTotalBitrate(&bitrate)) {
sp<NuCachedSource2> cachedSource =
static_cast<NuCachedSource2 *>(mDataSource.get());
diff --git a/media/libstagefright/WVMExtractor.cpp b/media/libstagefright/WVMExtractor.cpp
deleted file mode 100644
index d1b2f54..0000000
--- a/media/libstagefright/WVMExtractor.cpp
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#define LOG_TAG "WVMExtractor"
-#include <utils/Log.h>
-
-#include "include/WVMExtractor.h"
-
-#include <arpa/inet.h>
-#include <utils/String8.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/Utils.h>
-#include <media/stagefright/DataSource.h>
-#include <media/stagefright/MediaSource.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MediaBuffer.h>
-#include <dlfcn.h>
-
-#include <utils/Errors.h>
-
-/* The extractor lifetime is short - just long enough to get
- * the media sources constructed - so the shared lib needs to remain open
- * beyond the lifetime of the extractor. So keep the handle as a global
- * rather than a member of the extractor
- */
-void *gVendorLibHandle = NULL;
-
-namespace android {
-
-static Mutex gWVMutex;
-
-WVMExtractor::WVMExtractor(const sp<DataSource> &source)
- : mDataSource(source)
-{
- Mutex::Autolock autoLock(gWVMutex);
-
- if (!getVendorLibHandle()) {
- return;
- }
-
- typedef WVMLoadableExtractor *(*GetInstanceFunc)(sp<DataSource>);
- GetInstanceFunc getInstanceFunc =
- (GetInstanceFunc) dlsym(gVendorLibHandle,
- "_ZN7android11GetInstanceENS_2spINS_10DataSourceEEE");
-
- if (getInstanceFunc) {
- if (source->DrmInitialization(
- MEDIA_MIMETYPE_CONTAINER_WVM) != NULL) {
- mImpl = (*getInstanceFunc)(source);
- CHECK(mImpl != NULL);
- setDrmFlag(true);
- } else {
- ALOGE("Drm manager failed to initialize.");
- }
- } else {
- ALOGE("Failed to locate GetInstance in libwvm.so");
- }
-}
-
-static void init_routine()
-{
- gVendorLibHandle = dlopen("libwvm.so", RTLD_NOW);
- if (gVendorLibHandle == NULL) {
- ALOGE("Failed to open libwvm.so: %s", dlerror());
- }
-}
-
-bool WVMExtractor::getVendorLibHandle()
-{
- static pthread_once_t sOnceControl = PTHREAD_ONCE_INIT;
- pthread_once(&sOnceControl, init_routine);
-
- return gVendorLibHandle != NULL;
-}
-
-WVMExtractor::~WVMExtractor() {
-}
-
-size_t WVMExtractor::countTracks() {
- return (mImpl != NULL) ? mImpl->countTracks() : 0;
-}
-
-sp<IMediaSource> WVMExtractor::getTrack(size_t index) {
- if (mImpl == NULL) {
- return NULL;
- }
- return mImpl->getTrack(index);
-}
-
-sp<MetaData> WVMExtractor::getTrackMetaData(size_t index, uint32_t flags) {
- if (mImpl == NULL) {
- return NULL;
- }
- return mImpl->getTrackMetaData(index, flags);
-}
-
-sp<MetaData> WVMExtractor::getMetaData() {
- if (mImpl == NULL) {
- return NULL;
- }
- return mImpl->getMetaData();
-}
-
-int64_t WVMExtractor::getCachedDurationUs(status_t *finalStatus) {
- if (mImpl == NULL) {
- return 0;
- }
-
- return mImpl->getCachedDurationUs(finalStatus);
-}
-
-status_t WVMExtractor::getEstimatedBandwidthKbps(int32_t *kbps) {
- if (mImpl == NULL) {
- return UNKNOWN_ERROR;
- }
-
- return mImpl->getEstimatedBandwidthKbps(kbps);
-}
-
-
-void WVMExtractor::setAdaptiveStreamingMode(bool adaptive) {
- if (mImpl != NULL) {
- mImpl->setAdaptiveStreamingMode(adaptive);
- }
-}
-
-void WVMExtractor::setCryptoPluginMode(bool cryptoPluginMode) {
- if (mImpl != NULL) {
- mImpl->setCryptoPluginMode(cryptoPluginMode);
- }
-}
-
-void WVMExtractor::setUID(uid_t uid) {
- if (mImpl != NULL) {
- mImpl->setUID(uid);
- }
-}
-
-status_t WVMExtractor::getError() {
- if (mImpl == NULL) {
- return UNKNOWN_ERROR;
- }
-
- return mImpl->getError();
-}
-
-void WVMExtractor::setError(status_t err) {
- if (mImpl != NULL) {
- mImpl->setError(err);
- }
-}
-
-bool SniffWVM(
- const sp<DataSource> &source, String8 *mimeType, float *confidence,
- sp<AMessage> *) {
-
- Mutex::Autolock autoLock(gWVMutex);
-
- if (!WVMExtractor::getVendorLibHandle()) {
- return false;
- }
-
- typedef WVMLoadableExtractor *(*SnifferFunc)(const sp<DataSource>&);
- SnifferFunc snifferFunc =
- (SnifferFunc) dlsym(gVendorLibHandle,
- "_ZN7android15IsWidevineMediaERKNS_2spINS_10DataSourceEEE");
-
- if (snifferFunc) {
- if ((*snifferFunc)(source)) {
- *mimeType = MEDIA_MIMETYPE_CONTAINER_WVM;
- *confidence = 10.0f;
- return true;
- }
- } else {
- ALOGE("IsWidevineMedia not found in libwvm.so");
- }
-
- return false;
-}
-
-} //namespace android
-
diff --git a/media/libstagefright/filters/MediaFilter.cpp b/media/libstagefright/filters/MediaFilter.cpp
index 30e3643..877aead 100644
--- a/media/libstagefright/filters/MediaFilter.cpp
+++ b/media/libstagefright/filters/MediaFilter.cpp
@@ -676,7 +676,8 @@
}
sp<AMessage> notify = mNotify->dup();
- notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
+ notify->setInt32("what", keepComponentAllocated ?
+ CodecBase::kWhatStopCompleted : CodecBase::kWhatReleaseCompleted);
notify->post();
}
diff --git a/media/libstagefright/foundation/tests/Android.mk b/media/libstagefright/foundation/tests/Android.mk
new file mode 100644
index 0000000..e7598ca
--- /dev/null
+++ b/media/libstagefright/foundation/tests/Android.mk
@@ -0,0 +1,33 @@
+# Build the unit tests.
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_MODULE := sf_foundation_test
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := \
+ Flagged_test.cpp \
+ TypeTraits_test.cpp \
+ Utils_test.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright_foundation \
+
+LOCAL_C_INCLUDES := \
+ frameworks/av/include \
+
+LOCAL_CFLAGS += -Werror -Wall
+LOCAL_CLANG := true
+
+include $(BUILD_NATIVE_TEST)
+
+# Include subdirectory makefiles
+# ============================================================
+
+# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework
+# team really wants is to build the stuff defined by this makefile.
+ifeq (,$(ONE_SHOT_MAKEFILE))
+include $(call first-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/media/libstagefright/foundation/tests/Flagged_test.cpp b/media/libstagefright/foundation/tests/Flagged_test.cpp
new file mode 100644
index 0000000..3c90699
--- /dev/null
+++ b/media/libstagefright/foundation/tests/Flagged_test.cpp
@@ -0,0 +1,639 @@
+/*
+ * Copyright 2016 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Flagged_test"
+
+#include <gtest/gtest.h>
+
+#include <media/stagefright/foundation/Flagged.h>
+
+namespace android {
+
+/**
+ * Helper template that can be used to print values in static_assert error messages.
+ *
+ * Use integers here.
+ */
+template<bool, int ...N>
+struct _print_as_warning { };
+
+template<int ...N>
+struct _print_as_warning<true, N...> : std::true_type { };
+
+#define static_assert_equals(a, b, msg) \
+static_assert(_print_as_warning<(a) == (b), a, b>::value, msg)
+
+class FlaggedTest : public ::testing::Test {
+protected:
+ // empty structs
+ struct A0 { };
+ struct A1 { };
+ struct A_A0 : public A0 { };
+
+ // simple struct
+ struct BB {
+ int32_t i;
+ uint32_t u;
+ };
+
+ // struct inheriting from A0
+ struct BB_A0 : public A0 {
+ int32_t i;
+ uint32_t u;
+ };
+
+ // struct inheriting from struct inheriting A0
+ struct BB_AA0 : public A_A0 {
+ int32_t i;
+ uint32_t u;
+ };
+
+ // struct that wraps
+ struct WBBA0 {
+ BB_A0 b;
+ };
+
+ struct WBBA0_A1 : public A1 {
+ BB_A0 b;
+ };
+
+ struct WBBA0_A0 : public A0 {
+ BB_A0 b;
+ };
+
+ struct WBB_A0 : public A0 {
+ BB b;
+ };
+
+ struct WBBA0_AA0 : public A_A0 {
+ BB_A0 b;
+ };
+
+ struct WBBAA0_A0 : public A0 {
+ BB_AA0 b;
+ };
+
+ struct WWBBA0_A0 : public A0 {
+ WBBA0 b;
+ };
+};
+
+/**
+ * This test is here to confirm the handling of wrapping classes that inherit from an interface
+ * while also inheriting from that same interface. While we no longer use this construct, we want
+ * to track if this defect is ever fixed.
+ */
+TEST_F(FlaggedTest, StaticSanityTests) {
+ static_assert(sizeof(A0) == 1, "");
+ static_assert(sizeof(A1) == 1, "");
+ static_assert(sizeof(A_A0) == 1, "");
+
+ static constexpr size_t size = sizeof(BB); // original [pair]
+
+ // inheriting from A0 does not increase size
+ static_assert(sizeof(BB_A0) == size, ""); // [pair]:A0
+ static_assert(sizeof(BB_AA0) == size, ""); // [pair]:[:A0]
+
+ // wrapping a class that inherits from A0 does not increase size
+ static_assert(sizeof(WBBA0) == size, ""); // [ [pair]:[:A0] ]
+
+ // wrapping a class that inherits from A0 while also inheriting from A1 does not increase size
+ static_assert(sizeof(WBBA0_A1) == size, ""); // [ [pair]:A0 ]:A1
+
+ // wrapping a class that inherits from A0 while also inheriting from A0 DOES increase size
+ EXPECT_GT(sizeof(WBBA0_A0), size); // [ [pair]:A0 ]:A0
+
+ // wrapping a class that does not inherit from A0 while inheriting from A0 does not increase
+ // size
+ static_assert(sizeof(WBB_A0) == size, ""); // [[pair]]:A0
+
+ // wrapping a class that inherits from A0 while also inheriting from a class that inherits
+ // from A0 does increase size
+ EXPECT_GT(sizeof(WBBA0_AA0), size); // [ [pair]:A0 ]:[:A0]
+
+ // wrapping a class that indirectly inherits from A0 while also inheriting from A0 does
+ // increase size
+ EXPECT_GT(sizeof(WBBAA0_A0), size); // [ [pair]:[:A0] ]:A0
+
+ // wrapping a class that inherits from A0 while also inheriting A0 does increase size
+ EXPECT_GT(sizeof(WWBBA0_A0), size); // [ [pair]:A0 ]:A0
+}
+
+enum FLAG : int32_t {
+ kMask0 = 0x0FF,
+ kFlag0_A = 0x0AA,
+ kFlag0_B = 0x0BB,
+ kFlag0_C = 0x0CC,
+ kMask1 = 0xFF0,
+ kFlag1_A = 0xAA0,
+ kFlag1_B = 0xBB0,
+ kFlag1_C = 0xCC0,
+ kMaskCommon = 0x0F0,
+};
+
+TEST_F(FlaggedTest, BasicExample) {
+ enum SafeFlags : uint32_t {
+ kUnsafe,
+ kSafe,
+ kSafeMask = _Flagged_helper::minMask(kSafe),
+ };
+ typedef Flagged<int32_t, SafeFlags, kSafeMask> safeInt32;
+
+ safeInt32 a(kUnsafe);
+ a.setFlags(kSafe);
+ a.get() = 15;
+ EXPECT_EQ(a.flags(), kSafe);
+ EXPECT_EQ(a.get(), 15);
+
+ enum OriginFlags : uint32_t {
+ kUnknown,
+ kConst,
+ kCalculated,
+ kComponent,
+ kApplication,
+ kFile,
+ kBinder,
+ kOriginMask = _Flagged_helper::minMask(kBinder),
+ };
+ typedef Flagged<safeInt32, OriginFlags, kOriginMask>
+ trackedSafeInt32;
+
+ static_assert(sizeof(trackedSafeInt32) == sizeof(safeInt32), "");
+
+ trackedSafeInt32 b(kConst, kSafe, 1);
+ EXPECT_EQ(b.flags(), kConst);
+ EXPECT_EQ(b.get().flags(), kSafe);
+ EXPECT_EQ(b.get().get(), 1);
+ b.setFlags(kCalculated);
+ volatile bool overflow = true;
+ b.get().setFlags(overflow ? kUnsafe : kSafe);
+
+ enum ValidatedFlags : uint32_t {
+ kUnsafeV = kUnsafe,
+ kSafeV = kSafe,
+ kValidated = kSafe | 2,
+ kSharedMaskV = kSafeMask,
+ kValidatedMask = _Flagged_helper::minMask(kValidated),
+ };
+ typedef Flagged<safeInt32, ValidatedFlags, kValidatedMask, kSharedMaskV> validatedInt32;
+
+ validatedInt32 v(kUnsafeV, kSafe, 10);
+ EXPECT_EQ(v.flags(), kUnsafeV);
+ EXPECT_EQ(v.get().flags(), kUnsafe); // !kUnsafeV overrides kSafe
+ EXPECT_EQ(v.get().get(), 10);
+ v.setFlags(kValidated);
+ EXPECT_EQ(v.flags(), kValidated);
+ EXPECT_EQ(v.get().flags(), kSafe);
+ v.get().setFlags(kUnsafe);
+ EXPECT_EQ(v.flags(), 2); // NOTE: sharing masks with enums allows strange situations to occur
+}
+
+TEST_F(FlaggedTest, _Flagged_helper_Test) {
+ using helper = _Flagged_helper;
+
+ using i32 = int32_t;
+ using u32 = uint32_t;
+ using u8 = uint8_t;
+
+ // base2
+ static_assert(Flagged<i32, u32, 0u, 0u, 0>::sFlagMask == 0u, "");
+ static_assert(Flagged<i32, u32, 0u, 0u, 0>::sFlagShift == 0, "");
+ static_assert(Flagged<i32, u32, 0u, 0u, 0>::sEffectiveMask == 0u, "");
+
+ static_assert(Flagged<i32, u32, 0u, 0u, 10>::sFlagMask == 0u, "");
+ static_assert(Flagged<i32, u32, 0u, 0u, 10>::sFlagShift == 10, "");
+ static_assert(Flagged<i32, u32, 0u, 0u, 10>::sEffectiveMask == 0u, "");
+
+ static_assert(Flagged<i32, u32, 0u, 0u, -1>::sFlagMask == 0u, "");
+ static_assert(Flagged<i32, u32, 0u, 0u, -1>::sFlagShift == 0, "");
+ static_assert(Flagged<i32, u32, 0u, 0u, -1>::sEffectiveMask == 0u, "");
+
+ static_assert(Flagged<i32, u32, 99u, 0u, 0>::sFlagMask == 99u, "");
+ static_assert(Flagged<i32, u32, 99u, 0u, 0>::sFlagShift == 0, "");
+ static_assert(Flagged<i32, u32, 99u, 0u, 0>::sEffectiveMask == 99u, "");
+
+ static_assert(Flagged<i32, u32, 0x99u, 0u, 12>::sFlagMask == 0x99u, "");
+ static_assert(Flagged<i32, u32, 0x99u, 0u, 12>::sFlagShift == 12, "");
+ static_assert(Flagged<i32, u32, 0x99u, 0u, 12>::sEffectiveMask == 0x99000u, "");
+
+ static_assert(Flagged<i32, u32, 99u, 0u, -1>::sFlagMask == 99u, "");
+ static_assert(Flagged<i32, u32, 99u, 0u, -1>::sFlagShift == 0, "");
+ static_assert(Flagged<i32, u32, 99u, 0u, -1>::sEffectiveMask == 99u, "");
+
+ // mask_of<T, Flag>
+ // also Flagged<> no default
+ typedef Flagged<i32, u32, 0x800F /* mask */, 0 /* shared mask */, 0 /* shift */> i32_800f_0;
+ typedef Flagged<i32, u32, 0x800F /* mask */, 0 /* shared mask */, 4 /* shift */> i32_800f_4;
+ // this also tests that these types can be instantiated
+ static_assert(sizeof(i32_800f_0) >= sizeof(i32) + sizeof(u32),
+ "should be at least size of component types");
+ static_assert(sizeof(i32_800f_4) == sizeof(i32_800f_0), "regardless of shift");
+ static_assert(!i32_800f_0::sFlagCombined, "");
+ static_assert(!i32_800f_4::sFlagCombined, "");
+
+ static_assert(helper::mask_of<i32_800f_0, u32>::value == 0x800F, "incorrect mask");
+ static_assert(helper::mask_of<i32_800f_0, i32>::value == 0,
+ "mask should be 0 when types mismatch");
+ static_assert(helper::mask_of<i32_800f_0, u32>::effective_value == 0x800F, "incorrect mask");
+ static_assert(helper::mask_of<i32_800f_0, i32>::effective_value == 0,
+ "mask should be 0 when types mismatch");
+ static_assert(helper::mask_of<i32_800f_0, u32>::shift == 0, "incorrect shift");
+ static_assert(helper::mask_of<i32_800f_0, i32>::shift == 0,
+ "shift should be 0 when types mismatch");
+
+ static_assert(helper::mask_of<i32_800f_4, u32>::value == 0x800F, "incorrect mask");
+ static_assert(helper::mask_of<i32_800f_4, i32>::value == 0,
+ "mask should be 0 when types mismatch");
+ static_assert(helper::mask_of<i32_800f_4, u32>::effective_value == 0x800F0, "incorrect mask");
+ static_assert(helper::mask_of<i32_800f_4, i32>::effective_value == 0,
+ "mask should be 0 when types mismatch");
+ static_assert(helper::mask_of<i32_800f_4, u32>::shift == 4, "incorrect shift");
+ static_assert(helper::mask_of<i32_800f_4, i32>::shift == 0,
+ "shift should be 0 when types mismatch");
+ static_assert(helper::mask_of<i32, u32>::value == 0, "mask should be 0 if not masked");
+ static_assert(helper::mask_of<i32, i32>::value == 0, "mask should be 0 if not masked");
+
+ // lshift(value, n)
+ static_assert(helper::lshift(0U, 0) == 0U, "");
+ static_assert(helper::lshift(0U, 30) == 0U, "");
+ static_assert(helper::lshift(1U, 0) == 1U, "");
+ static_assert(helper::lshift(1U, 10) == 1024U, "");
+ static_assert(helper::lshift(10U, 10) == 10240U, "");
+ static_assert(helper::lshift(10, 10) == 10240, "");
+ static_assert(helper::lshift(-10, 0) == -10, "");
+ // static_assert(helper::lshift(-10, 10) == -10240, ""); // error: left shift of negative value
+
+ // minMask(maxValue)
+ static_assert(helper::minMask(0U) == 0U, "lowest 0 bits");
+ static_assert(helper::minMask(1U) == 1U, "lowest 1 bit");
+ static_assert(helper::minMask(2U) == 3U, "lowest 2 bits");
+ static_assert(helper::minMask(3U) == 3U, "lowest 2 bits");
+ static_assert(helper::minMask(4U) == 7U, "lowest 3 bits");
+ static_assert(helper::minMask(~0U) == ~0U, "all bits");
+ // static_assert(helper::minMask(10) == 0xF, "all bits"); // error: must be unsigned
+
+ // topBits(n)
+ static_assert(helper::topBits<u32>(0) == 0U, "top 0 bit");
+ static_assert(helper::topBits<u32>(1) == 0x80000000U, "top 1 bit");
+ static_assert(helper::topBits<u32>(2) == 0xC0000000U, "top 2 bits");
+ static_assert(helper::topBits<u32>(12) == 0xFFF00000U, "top 12 bits");
+ static_assert(helper::topBits<u32>(32) == 0xFFFFFFFFU, "all bits");
+ // static_assert(helper::topBits<u32>(33) == 0xFFFFFFFFU, ""); // should OVERFLOW
+
+ static_assert(helper::topBits<u8>(0) == 0U, "top 0 bit");
+ static_assert(helper::topBits<u8>(1) == 0x80U, "top 1 bit");
+ static_assert(helper::topBits<u8>(2) == 0xC0U, "top 2 bit");
+ static_assert(helper::topBits<u8>(8) == 0xFFU, "all bits");
+ // static_assert(helper::topBits<u8>(9) == 0xFFU, ""); // should OVERFLOW
+
+ // getShift(mask, base, shared, base-shift, base-effective)
+ static_assert(helper::getShift(0u, 0u, 0u, 0, 0u) == 0, "no flag require no shift");
+ static_assert(helper::getShift(0u, 0u, 1u, 0, 0u) == -1,
+ "shared must be within mask and base mask");
+ static_assert(helper::getShift(0u, 1u, 1u, 0, 1u) == -1, "shared must be within mask");
+ static_assert(helper::getShift(0u, 1u, 0u, 0, 1u) == 0,
+ "no flags require no shift even with base mask");
+ static_assert(helper::getShift(0u, 1u, 0u, 1, 2u) == 0,
+ "no flags require no shift even with shifted base mask");
+ static_assert(helper::getShift(1u, 0u, 0u, 0, 0u) == 0, "no base mask requires no shift");
+ static_assert(helper::getShift(1u, 1u, 0u, 0, 1u) == 1,
+ "overlapping mask and basemask requires shift");
+ static_assert(helper::getShift(1u, 1u, 0u, 0, 1u) == 1,
+ "overlapping mask and basemask requires shift");
+ static_assert(helper::getShift(1u, 1u, 1u, 0, 1u) == 0,
+ "shared mask requires using base shift");
+ static_assert(helper::getShift(1u, 1u, 1u, 1, 2u) == 1,
+ "shared mask requires using base shift");
+ static_assert(helper::getShift(3u, 5u, 1u, 0, 5u) == 0,
+ "mask and basemask that overlap only in shared region requires no shift");
+ static_assert(helper::getShift(3u, 7u, 1u, 0, 7u) == -1,
+ "mask and basemask must not overlap in more than shared region");
+ static_assert(helper::getShift(1u, 0u, 1u, 0, 0u) == -1, "shared must be within base mask");
+
+ static_assert(helper::getShift(0u, 1u, 0u, 1, 1u) == -2, "effective mask must cover base mask");
+ static_assert(helper::getShift(0u, 5u, 0u, 1, 2u) == -2, "effective mask must cover base mask");
+ static_assert(helper::getShift(0u, 5u, 0u, 1, 10u) == 0, "");
+ static_assert(helper::getShift(0u, 5u, 0u, 1, 31u) == 0,
+ "effective mask can be larger than base mask");
+
+ static_assert(helper::getShift(0x800Fu, 0x800Fu, 0x800Fu, 0, 0x800Fu) == 0,
+ "(0x800F << 0) & 0x800F == 0x800F");
+ static_assert(helper::getShift(0x800Fu, 0x800Fu, 0x800Fu, 16, 0x800F0000u) == 16,
+ "(0x800F << 0) & 0x800F == 0x800F");
+ static_assert(helper::getShift(0x1800Fu, 0x800Fu, 0x800Fu, 0, 0x800Fu) == 0,
+ "(0x1800F << 0) & 0x800F == 0x800F");
+ static_assert(helper::getShift(0x1800Fu, 0x800Fu, 0x800Fu, 16, 0x800F0000u) == -1,
+ "(0x1800F << 16) overflows");
+
+ // verify that when not sharing masks, effective mask makes the difference
+ static_assert(helper::getShift(0x800Fu, 0u, 0u, 0, 0x800Fu) == 4,
+ "(0x800F << 4) & 0x800F == 0");
+ static_assert(helper::getShift(0x800Fu, 0x2u, 0u, 0, 0x8002u) == 2,
+ "(0x800F << 2) & 0x8002 == 0");
+ static_assert(helper::getShift(0x800Fu, 0x1u, 0u, 15, 0x8001u) == 1,
+ "(0x800F << 1) & 0x8001 == 0");
+ static_assert(helper::getShift(0x800Fu, 0x800Fu, 0u, 16, 0x800F0000u) == 0,
+ "0x800F & 0x800F0000 == 0");
+ static_assert(helper::getShift(0x800Fu, 0x800F8000u, 0u, 0, 0x800F8000u) == 5,
+ "(0x800F << 5) & 0x800F8000 == 0");
+ static_assert(helper::getShift(0x800Fu, 0xF0000u, 0u, 0, 0x800F8000u) == 5,
+ "(0x800F << 5) & 0x800F8000 == 0");
+ static_assert(helper::getShift(0x800Fu, 0x1Fu, 0u, 15, 0x800F8000u) == 5,
+ "(0x800F << 5) & 0x800F8000 == 0");
+ static_assert(helper::getShift(0xFFu, 0x80808080u, 0u, 0, 0x80808080u) == -1,
+ "0xFF always overlaps with 0x80808080");
+ static_assert(helper::getShift(0xFFu, 0x10001000u, 0u, 3, 0x80808080u) == -1,
+ "0xFF always overlaps with 0x80808080");
+ static_assert(helper::getShift(0xFFu, 0x80808040u, 0u, 0, 0x80808040u) == 7,
+ "(0xFF << 7) & 0x 80808040 == 0");
+
+ // verify min_shift (mask must be positive or no shift can be required)
+ static_assert(helper::getShift(0xFF, 0x40808040, 0, 0, 0x40808040) == 7, "");
+ static_assert(helper::getShift((i32)0x800000FF, 0x40808040, 0, 0, 0x40808040) == -1, "");
+ static_assert(helper::getShift(0x100000FF, 0x40808040, 0, 0, 0x40808040) == -1, "");
+ static_assert(helper::getShift(0xFF, (i32)0x80808040, 0, 0, (i32)0x80808040) == 7, "");
+ static_assert(helper::getShift((i32)0x80007F80, 0x40808040, 0, 0, 0x40808040) == 0, "");
+
+ // shared mask can also be negative (but not shift can be required)
+ static_assert(helper::getShift((i32)0x80007F80, (i32)0xC0808040, (i32)0x80000000,
+ 0, (i32)0xC0808040) == 0, "");
+ static_assert(helper::getShift((i32)0x80007F80, (i32)0xC0808040, (i32)0xC0000000,
+ 0, (i32)0xC0808040) == -1, "");
+ static_assert(helper::getShift((i32)0x80007F80, (i32)0x60404020, (i32)0x60000000,
+ 1, (i32)0xC0808040) == -1, "");
+
+ // min_shift
+ typedef Flagged<i32, u32, 0u> i32_0_0;
+ typedef Flagged<i32, u32, 1u> i32_1_0;
+ typedef Flagged<i32, u32, 1u, 0u, 1> i32_1_1;
+
+ // this is a wrapper over getShift, so same test cases apply when T is flagged
+ static_assert(helper::min_shift<i32_0_0, u32, 0u, 0u>::value == 0, "");
+ static_assert(helper::min_shift<i32_0_0, u32, 0u, 1u>::value == -1, "");
+ static_assert(helper::min_shift<i32_1_0, u32, 0u, 1u>::value == -1, "");
+ static_assert(helper::min_shift<i32_1_0, u32, 0u, 0u>::value == 0, "");
+ static_assert(helper::min_shift<i32_0_0, u32, 1u, 0u>::value == 0, "");
+ static_assert(helper::min_shift<i32_1_0, u32, 1u, 0u>::value == 1, "");
+ static_assert(helper::min_shift<i32_1_0, u32, 1u, 1u>::value == 0, "");
+ static_assert(helper::min_shift<i32_1_1, u32, 1u, 1u>::value == 1, "");
+ static_assert(helper::min_shift<i32_1_1, u32, 3u, 0u>::value == 2, "");
+ static_assert(helper::min_shift<Flagged<i32, u32, 5u>, u32, 3u, 1u>::value == 0, "");
+ static_assert(helper::min_shift<Flagged<i32, u32, 7u>, u32, 3u, 1u>::value == -1, "");
+ static_assert(helper::min_shift<i32_0_0, u32, 1u, 1u>::value == -1, "");
+
+ static_assert(helper::min_shift<i32_800f_0, u32, 0x800Fu, 0u>::value == 4, "");
+ static_assert(helper::min_shift<i32_800f_4, u32, 0x1800Fu, 0x800Fu>::value == 4, "");
+ static_assert(helper::min_shift<i32_800f_4, u32, 0x800Fu, 0u>::value == 0, "");
+ static_assert(helper::min_shift<Flagged<i32, u32, 0x8002u>, u32, 0x800Fu, 0u>::value == 2, "");
+ static_assert(helper::min_shift<Flagged<i32, u32, 0x8001u>, u32, 0x800Fu, 0u>::value == 1, "");
+ static_assert(
+ helper::min_shift<Flagged<i32, u32, 0x800Fu, 0u, 16>, u32, 0x800Fu, 0u>::value == 0, "");
+ static_assert(
+ helper::min_shift<Flagged<i32, u32, 0x800F8000u>, u32, 0x800Fu, 0u>::value == 5, "");
+ static_assert(
+ helper::min_shift<Flagged<i32, u32, 0x80808080u>, u32, 0xFFu, 0u>::value == -1, "");
+ static_assert(
+ helper::min_shift<Flagged<i32, u32, 0x80808040u>, u32, 0xFFu, 0u>::value == 7, "");
+
+ // for min_shift, non-tagged type behaves as if having base mask of 0
+ static_assert(helper::min_shift<i32, u32, 0u, 0u>::value == 0, "");
+ static_assert(helper::min_shift<u32, u32, 0u, 0u>::value == 0, "");
+ static_assert(helper::min_shift<i32, u32, 0u, 0u>::value == 0, "");
+ static_assert(helper::min_shift<i32, u32, 0u, 1u>::value == -1, "");
+ static_assert(helper::min_shift<i32, u32, 1u, 0u>::value == 0, "");
+ static_assert(helper::min_shift<i32, u32, 1u, 1u>::value == -1, "");
+
+ // verify min_shift (mask must be positive or no shift can be required)
+ static_assert(helper::min_shift<Flagged<i32, i32, 0x40808040>, i32, 0xFF, 0>::value == 7, "");
+ static_assert(helper::min_shift<Flagged<i32, i32, 0x40808040>,
+ i32, (i32)0x800000FF, 0>::value == -1, "");
+ static_assert(helper::min_shift<Flagged<i32, i32, 0x40808040>,
+ i32, 0x100000FF, 0>::value == -1, "");
+ static_assert(helper::min_shift<Flagged<i32, i32, (i32)0x80808040>,
+ i32, 0xFF, 0>::value == 7, "");
+ static_assert(helper::min_shift<Flagged<i32, i32, 0x40808040>,
+ i32, (i32)0x80007F80, 0>::value == 0, "");
+
+ static_assert(helper::min_shift<Flagged<i32, i32, (i32)0x80808040>,
+ i32, (i32)0x80007F80, (i32)0x80000000>::value == 0, "");
+ static_assert(helper::min_shift<Flagged<i32, i32, (i32)0xC0808040>,
+ i32, (i32)0x80007F80, (i32)0xC0000000>::value == -1, "");
+ // note: cannot create a flagged type with signed flag and shift
+ // static_assert(helper::min_shift<Flagged<i32, i32, (i32)0x60404020, 0, 1>,
+ // i32, (i32)0x40003FC0, (i32)0x40000000>::value == -1, "");
+
+ typedef Flagged<i32, u32, 0x800F /* mask */, 0 /* shared mask */, 16 /* shift */> i32_800f_16;
+ static_assert_equals(sizeof(i32_800f_16), sizeof(i32_800f_0), "");
+ // shifted mask overflows!
+ // typedef Flagged<i32, u32, 0x800F /* mask */, 0 /* shared mask */, 17 /* shift */> i32_800f_17;
+ // static_assert(sizeof(i32_800f_17) == sizeof(i32_800f_0), "");
+ typedef Flagged<i32, i32, 0x800F /* mask */, 0 /* shared mask */, 15 /* shift */> i32_800f_15i;
+ static_assert_equals(sizeof(i32_800f_15i), sizeof(i32_800f_0), "");
+ // shifted mask overflows!
+ // typedef Flagged<i32, i32, 0x800F /* mask */, 0 /* shared mask */, 16 /* shift */> i32_800f_16i;
+ // static_assert(sizeof(i32_800f_16i) == sizeof(i32_800f_0), "");
+
+ // canCombine(mask, base, shared, shift, base-shift, base-effective)
+ static_assert(helper::canCombine(0u, 0u, 0u, 0, 0, 0u), "using no mask is valid");
+ static_assert(helper::canCombine(0u, 0u, 0u, 0, 0, 0u), "");
+ static_assert(helper::canCombine(0u, 0u, 0u, 4, 0, 0u), "");
+ static_assert(!helper::canCombine(0u, 0u, 1u, 0, 0, 0u),
+ "shared mask must be the overlap of masks");
+ static_assert(helper::canCombine(1u, 0u, 0u, 0, 0, 0u), "");
+ static_assert(helper::canCombine(1u, 0u, 0u, 4, 0, 0u), "");
+ static_assert(helper::canCombine(3u, 5u, 1u, 0, 0, 5u), "");
+ static_assert(!helper::canCombine(3u, 3u, 3u, 1, 0, 3u), "shift must match when sharing mask");
+ static_assert(helper::canCombine(3u, 3u, 3u, 1, 1, 6u), "");
+ static_assert(!helper::canCombine(3u, 3u, 3u, 1, 2, 12u), "shift must match when sharing mask");
+ static_assert(!helper::canCombine(3u, 7u, 1u, 0, 0, 7u), "");
+ static_assert(!helper::canCombine(1u, 0u, 1u, 0, 0, 0u), "");
+
+ static_assert(!helper::canCombine(0u, 1u, 1u, 0, 0, 1u),
+ "shared mask must be the overlap of masks");
+ static_assert(helper::canCombine(0u, 1u, 0u, 0, 0, 1u), "");
+ static_assert(helper::canCombine(0u, 1u, 0u, 4, 0, 1u), "");
+ static_assert(helper::canCombine(1u, 1u, 0u, 1, 0, 1u), "");
+ static_assert(!helper::canCombine(1u, 1u, 0u, 0, 0, 1u), "");
+ static_assert(helper::canCombine(1u, 1u, 0u, 1, 0, 1u), "");
+ static_assert(helper::canCombine(1u, 1u, 1u, 0, 0, 1u), "");
+ static_assert(!helper::canCombine(1u, 1u, 1u, 1, 0, 1u), "shift must match when sharing mask");
+
+ static_assert(helper::canCombine(0x800Fu, 0x800Fu, 0u, 4, 0, 0x800Fu), "");
+ static_assert(!helper::canCombine(0x800Fu, 0x800Fu, 0u, 1, 0, 0x800Fu), "");
+ static_assert(helper::canCombine(0x800Fu, 0x8002u, 0u, 2, 0, 0x8002u), "");
+ static_assert(helper::canCombine(0x800Fu, 0x8001u, 0u, 1, 0, 0x8001u), "");
+ static_assert(helper::canCombine(0x800Fu, 0x800Fu, 0u, 0, 16, 0x800F0000u), "");
+ static_assert(helper::canCombine(0x800Fu, 0x800Fu, 0x800Fu, 16, 16, 0x800F0000u), "");
+ static_assert(!helper::canCombine(0x1800Fu, 0x800Fu, 0u, 0, 16, 0x800F0000u), "");
+ static_assert(!helper::canCombine(0x1800Fu, 0x800Fu, 0x800Fu, 16, 16, 0x800F0000u), "");
+ static_assert(helper::canCombine(0x800Fu, 0x800F8000u, 0u, 8, 0, 0x800F8000u), "");
+ static_assert(!helper::canCombine(0xFFu, 0x80808080u, 0u, -1, 0, 0x80808080u), "");
+ static_assert(helper::canCombine(0xFFu, 0x80808040u, 0u, 7, 0, 0x80808040u), "");
+ static_assert(helper::canCombine(0xFFu, 0x8000u, 0u, 7, 0, 0x80808040u), "");
+ static_assert(helper::canCombine(0xFFu, 0x101u, 0u, 7, 15, 0x80808040u), "");
+
+ // can combine signed-flagged types only if mask is positive or no shift is required
+ static_assert(!helper::canCombine(0xFF, 0x40808040, 0, 0, 0, 0x40808040), "");
+ static_assert(helper::canCombine(0xFF, 0x40808040, 0, 7, 0, 0x40808040), "");
+ static_assert(!helper::canCombine((i32)0x800000FF, 0x40808040, 0, 0, 0, 0x40808040), "");
+ static_assert(!helper::canCombine((i32)0x800000FF, 0x40808040, 0, 7, 0, 0x40808040), "");
+ static_assert(!helper::canCombine(0x100000FF, 0x40808040, 0, 0, 0, 0x40808040), "");
+ static_assert(!helper::canCombine(0x100000FF, 0x40808040, 0, 7, 0, 0x40808040), "");
+ static_assert(!helper::canCombine(0xFF, (i32)0x80808040, 0, 0, 0, (i32)0x80808040), "");
+ static_assert(helper::canCombine(0xFF, (i32)0x80808040, 0, 7, 0, (i32)0x80808040), "");
+ static_assert(helper::canCombine((i32)0x80007F80, 0x40808040, 0, 0, 0, 0x40808040), "");
+
+ static_assert(helper::canCombine((i32)0x80007F80, (i32)0x80808040, (i32)0x80000000, 0, 0, (i32)0x80808040), "");
+ static_assert(!helper::canCombine((i32)0xC0007F80, (i32)0x80808040, (i32)0xC0000000, 0, 0, (i32)0x80808040), "");
+ static_assert(!helper::canCombine((i32)0x80007F80, (i32)0x80808040, (i32)0x80000000, 1, 0, (i32)0x80808040), "");
+ static_assert(!helper::canCombine((i32)0xC0007F80, (i32)0x80808040, (i32)0xC0000000, 1, 0, (i32)0x80808040), "");
+
+ // can_combine<T, Flag, MASK, [SHARED_MASK], [SHIFT]
+ static_assert(helper::can_combine<i32_0_0, u32, 0u>::value, "");
+ static_assert(helper::can_combine<i32_0_0, u32, 0u, 0u>::value, "");
+ static_assert(helper::can_combine<i32_0_0, u32, 0u, 0u, 4>::value, "");
+ static_assert(!helper::can_combine<i32_0_0, u32, 0u, 1u>::value, "");
+ static_assert(helper::can_combine<i32_0_0, u32, 1u, 0u>::value, "");
+ static_assert(helper::can_combine<i32_0_0, u32, 1u, 0u, 4>::value, "");
+ static_assert(!helper::can_combine<i32_0_0, u32, 1u, 1u>::value, "");
+
+ static_assert(!helper::can_combine<i32_1_0, u32, 0u, 1u>::value, "");
+ static_assert(helper::can_combine<i32_1_0, u32, 0u, 0u>::value, "");
+ static_assert(helper::can_combine<i32_1_0, u32, 0u, 0u, 4>::value, "");
+ static_assert(helper::can_combine<i32_1_0, u32, 1u, 0u>::value, "");
+ static_assert(!helper::can_combine<i32_1_0, u32, 1u, 0u, 0>::value, "");
+ static_assert(helper::can_combine<i32_1_0, u32, 1u, 0u, 1>::value, "");
+ static_assert(helper::can_combine<i32_1_0, u32, 1u, 1u>::value, "");
+ static_assert(helper::can_combine<i32_1_0, u32, 1u, 1u, 0>::value, "");
+ static_assert(!helper::can_combine<i32_1_0, u32, 1u, 1u, 1>::value,
+ "shouldn't be able to use SHIFT with SHARED_MASK");
+
+ static_assert(helper::can_combine<i32_800f_0, u32, 0x800Fu, 0u, 4>::value, "");
+ static_assert(!helper::can_combine<i32_800f_0, u32, 0x800Fu, 0u, 1>::value, "");
+ static_assert(helper::can_combine<i32_800f_0, u32, 0x800Fu, 0u>::value, "");
+ static_assert(helper::can_combine<Flagged<i32, u32, 0x8002u>, u32, 0x800Fu, 0u>::value, "");
+ static_assert(helper::can_combine<Flagged<i32, u32, 0x8001u>, u32, 0x800Fu, 0u>::value, "");
+ static_assert(helper::can_combine<Flagged<i32, u32, 0x800F0000u>, u32, 0x800Fu, 0u>::value, "");
+ static_assert(helper::can_combine<Flagged<i32, u32, 0x800F8000u>, u32, 0x800Fu, 0u>::value, "");
+ static_assert(!helper::can_combine<Flagged<i32, u32, 0x80808080u>, u32, 0xFFu, 0u>::value, "");
+ static_assert(helper::can_combine<Flagged<i32, u32, 0x80808040u>, u32, 0xFFu, 0u>::value, "");
+
+ // can combine signed-flagged types only if mask is positive or no shift is required
+ static_assert(helper::can_combine<Flagged<i32, i32, 0x40808040>, i32, 0xFF, 0>::value, "");
+ static_assert(!helper::can_combine<Flagged<i32, i32, 0x40808040>,
+ i32, (i32)0x800000FF, 0>::value, "");
+ static_assert(!helper::can_combine<Flagged<i32, i32, 0x40808040>,
+ i32, 0x100000FF, 0>::value, "");
+ static_assert(helper::can_combine<Flagged<i32, i32, (i32)0x80808040>, i32, 0xFF, 0>::value, "");
+ static_assert(helper::can_combine<Flagged<i32, i32, 0x40808040>,
+ i32, (i32)0x80007F80, 0>::value, "");
+
+ static_assert(helper::can_combine<Flagged<i32, i32, (i32)0x80808040>,
+ i32, (i32)0x80007F80, (i32)0x80000000>::value, "");
+ static_assert(!helper::can_combine<Flagged<i32, i32, (i32)0xC0808040>,
+ i32, (i32)0x80007F80, (i32)0xC0000000>::value, "");
+
+ static_assert(helper::min_shift<Flagged<i32, FLAG, (FLAG)0x80808040>,
+ FLAG, (FLAG)0x80007F80, (FLAG)0x80000000>::value == 0, "");
+ static_assert(helper::can_combine<Flagged<i32, FLAG, (FLAG)0x80808040>,
+ FLAG, (FLAG)0x80007F80, (FLAG)0x80000000>::value, "");
+
+ // cannot combine non-tagged types
+ static_assert(!helper::can_combine<i32, u32, 0u, 0u>::value, "");
+ static_assert(!helper::can_combine<u32, u32, 0u, 0u>::value, "");
+ static_assert(!helper::can_combine<i32, u32, 0u, 0u>::value, "");
+ static_assert(!helper::can_combine<i32, u32, 0u, 1u>::value, "");
+ static_assert(!helper::can_combine<i32, u32, 1u, 0u>::value, "");
+ static_assert(!helper::can_combine<i32, u32, 1u, 1u>::value, "");
+
+ typedef Flagged<i32_800f_0, u32, 0x800F /* mask */, 0 /* shared mask */> i32_800f_800f;
+ static_assert(i32_800f_800f::sFlagMask == 0x800F, "");
+ static_assert(i32_800f_800f::sFlagShift == 4, "");
+ static_assert(i32_800f_800f::sEffectiveMask == 0x880FF, "");
+ static_assert(!i32_800f_0::sFlagCombined, "");
+ static_assert(!i32_800f_4::sFlagCombined, "");
+
+ static_assert(i32_800f_800f::sFlagCombined, "");
+ static_assert_equals(sizeof(i32_800f_800f), sizeof(i32_800f_0), "");
+
+ typedef Flagged<i32_800f_0, u32, 0x1FFFF /* mask */> i32_800f_1ffff;
+ static_assert(i32_800f_1ffff::sFlagMask == 0x1FFFF, "");
+ static_assert(i32_800f_1ffff::sFlagShift == 0, "");
+ static_assert(i32_800f_1ffff::sEffectiveMask == 0x1FFFF, "");
+ static_assert(!i32_800f_1ffff::sFlagCombined, "");
+
+ // operational tests
+ i32_800f_800f val(0x8000, 0x1234, 56);
+ EXPECT_EQ(val.get().get(), 56);
+ EXPECT_EQ(val.flags(), 0x8000u);
+ EXPECT_EQ(val.get().flags(), 0x1234u & 0x800F);
+ val.setFlags(0x12345);
+ EXPECT_EQ(val.flags(), 0x12345u & 0x800F);
+ EXPECT_EQ(val.get().flags(), 0x1234u & 0x800F);
+ val.get().setFlags(0x54321);
+ EXPECT_EQ(val.flags(), 0x12345u & 0x800F);
+ EXPECT_EQ(val.get().flags(), 0x54321u & 0x800F);
+ EXPECT_EQ(val.get().get(), 56);
+
+ typedef Flagged<i32_800f_4, u32, 0x800F /* mask */, 0 /* shared mask */> i32_800f_800f_B;
+ static_assert(i32_800f_800f_B::sFlagMask == 0x800F, "");
+ static_assert(i32_800f_800f_B::sFlagShift == 0, "");
+ static_assert(i32_800f_800f_B::sEffectiveMask == 0x880FF, "");
+
+ i32_800f_800f_B valB(0x8000, 0x1234, -987);
+ EXPECT_EQ(valB.get().get(), -987);
+ EXPECT_EQ(valB.flags(), 0x8000u);
+ EXPECT_EQ(valB.get().flags(), 0x1234u & 0x800F);
+ valB.setFlags(0x12345);
+ EXPECT_EQ(valB.flags(), 0x12345u & 0x800F);
+ EXPECT_EQ(valB.get().flags(), 0x1234u & 0x800F);
+ valB.get().setFlags(0x5C321);
+ EXPECT_EQ(valB.flags(), 0x12345u & 0x800F);
+ EXPECT_EQ(valB.get().flags(), 0x5C321u & 0x800F);
+ EXPECT_EQ(valB.get().get(), -987);
+
+ typedef Flagged<Flagged<i32, u32, 0xFF>, u32, 0xFF0, 0xF0> i32_ff_ff0;
+ i32_ff_ff0 valC(0xABCD, 0x1234, 101);
+ EXPECT_EQ(valC.get().get(), 101);
+ EXPECT_EQ(valC.flags(), 0xBC0u);
+ EXPECT_EQ(valC.get().flags(), 0xC4u);
+ valC.setFlags(0x12345);
+ EXPECT_EQ(valC.flags(), 0x340u);
+ EXPECT_EQ(valC.get().flags(), 0x44u);
+ valC.get().setFlags(0x54321);
+ EXPECT_EQ(valC.flags(), 0x320u);
+ EXPECT_EQ(valC.get().flags(), 0x21u);
+ EXPECT_EQ(valC.get().get(), 101);
+
+ // when combining flags (with no shift), it should work with signed flags
+ typedef Flagged<Flagged<i32, FLAG, kMask0>, FLAG, kMask1, kMaskCommon> i32_F_ff_ff0;
+ static_assert(i32_F_ff_ff0::sFlagCombined, "flags should be combined");
+
+ i32_F_ff_ff0 valD(kFlag1_A, kFlag0_A, 1023);
+ EXPECT_EQ(valD.get().get(), 1023);
+ EXPECT_EQ(valD.flags(), kFlag1_A);
+ EXPECT_EQ(valD.get().flags(), kFlag0_A);
+ valD.setFlags(kFlag1_B);
+ EXPECT_EQ(valD.flags(), kFlag1_B);
+ EXPECT_EQ(valD.get().flags(), FLAG(0x0BA));
+ valD.get().setFlags(kFlag0_C);
+ EXPECT_EQ(valD.flags(), FLAG(0xBC0));
+ EXPECT_EQ(valD.get().flags(), kFlag0_C);
+ EXPECT_EQ(valD.get().get(), 1023);
+}
+
+} // namespace android
diff --git a/media/libstagefright/foundation/tests/TypeTraits_test.cpp b/media/libstagefright/foundation/tests/TypeTraits_test.cpp
new file mode 100644
index 0000000..9fba435
--- /dev/null
+++ b/media/libstagefright/foundation/tests/TypeTraits_test.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2016 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "TypeTraits_test"
+
+#include <gtest/gtest.h>
+
+#include <media/stagefright/foundation/TypeTraits.h>
+
+namespace android {
+
+class TypeTraitsTest : public ::testing::Test {
+protected:
+ enum A { };
+ enum UA : uint32_t { };
+ enum IA : int32_t { };
+};
+
+// =========== basic sanity tests for type-support templates
+TEST_F(TypeTraitsTest, StaticTests) {
+ static_assert(!std::is_integral<A>::value, "enums should not be integral");
+ static_assert(!std::is_integral<UA>::value, "enums should not be integral");
+ static_assert(!std::is_integral<IA>::value, "enums should not be integral");
+ static_assert(is_integral_or_enum<A>::value, "enums should be integral_or_enum");
+ static_assert(is_integral_or_enum<UA>::value, "enums should be integral_or_enum");
+ static_assert(is_integral_or_enum<IA>::value, "enums should be integral_or_enum");
+ static_assert(is_integral_or_enum<int>::value, "ints should be integral_or_enum");
+ static_assert(is_integral_or_enum<unsigned>::value, "unsigned ints should be integral_or_enum");
+ static_assert(!is_integral_or_enum<float>::value, "floats should not be integral_or_enum");
+
+ static_assert(!std::is_unsigned<UA>::value,
+ "unsigned enums should not be unsigned");
+ static_assert(!std::is_unsigned<IA>::value,
+ "unsigned enums should not be unsigned");
+ static_assert(std::is_unsigned<typename std::underlying_type<UA>::type>::value,
+ "underlying type of unsigned enums should be unsigned");
+ static_assert(!std::is_unsigned<typename std::underlying_type<IA>::type>::value,
+ "underlying type of unsigned enums should be unsigned");
+ static_assert(is_unsigned_integral<UA>::value,
+ "unsigned enums should be unsigned_integral");
+ static_assert(!is_unsigned_integral<IA>::value,
+ "signed enums should not be unsigned_integral");
+ static_assert(is_unsigned_integral<unsigned>::value,
+ "unsigned ints should be unsigned_integral");
+ static_assert(!is_unsigned_integral<int>::value,
+ "ints should not be unsigned_integral");
+ static_assert(!is_unsigned_integral<float>::value,
+ "floats should not be unsigned_integral");
+
+ static_assert(!std::is_signed<UA>::value,
+ "unsigned enums should not be signed");
+ static_assert(!std::is_signed<IA>::value,
+ "unsigned enums should not be signed");
+ static_assert(!std::is_signed<typename std::underlying_type<UA>::type>::value,
+ "underlying type of unsigned enums should be signed");
+ static_assert(std::is_signed<typename std::underlying_type<IA>::type>::value,
+ "underlying type of unsigned enums should be signed");
+ static_assert(!is_signed_integral<UA>::value,
+ "unsigned enums should not be signed_integral");
+ static_assert(is_signed_integral<IA>::value,
+ "signed enums should be signed_integral");
+ static_assert(!is_signed_integral<unsigned>::value,
+ "unsigned ints should not be signed_integral");
+ static_assert(is_signed_integral<int>::value,
+ "ints should be signed_integral");
+ static_assert(!is_signed_integral<float>::value,
+ "floats should not be signed_integral");
+
+ static_assert(std::is_same<uint64_t, typename underlying_integral_type<uint64_t>::type>::value,
+ "underlying integral type of uint64_t should be uint64_t");
+ static_assert(std::is_same<uint32_t, typename underlying_integral_type<UA>::type>::value,
+ "underlying integral type of uint32_t based enums should be uint32_t");
+ static_assert(std::is_same<int64_t, typename underlying_integral_type<int64_t>::type>::value,
+ "underlying integral type of int64_t should be int64_t");
+ static_assert(std::is_same<int32_t, typename underlying_integral_type<IA>::type>::value,
+ "underlying integral type of int32_t based enums should be int32_t");
+ //typedef underlying_integral_type<float>::type no_type;
+ static_assert(std::is_same<void, typename underlying_integral_type<float, void>::type>::value,
+ "underlying integral type of float cannot be specified");
+}
+
+} // namespace android
diff --git a/media/libstagefright/tests/Utils_test.cpp b/media/libstagefright/foundation/tests/Utils_test.cpp
similarity index 98%
rename from media/libstagefright/tests/Utils_test.cpp
rename to media/libstagefright/foundation/tests/Utils_test.cpp
index d736501..0439d5c 100644
--- a/media/libstagefright/tests/Utils_test.cpp
+++ b/media/libstagefright/foundation/tests/Utils_test.cpp
@@ -18,15 +18,11 @@
#define LOG_TAG "Utils_test"
#include <gtest/gtest.h>
-#include <utils/String8.h>
-#include <utils/Errors.h>
-#include <fcntl.h>
-#include <unistd.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AStringUtils.h>
#include <media/stagefright/foundation/AUtils.h>
-#include <media/stagefright/Utils.h>
+#include <media/stagefright/Utils.h> // for FOURCC
namespace android {
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index e654a01..477280a 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -178,7 +178,7 @@
*shortTermBps = mShortTermEstimate;
}
- int32_t minEstimate = -1, maxEstimate = -1;
+ int64_t minEstimate = -1, maxEstimate = -1;
List<int32_t>::iterator it;
for (it = mPrevEstimates.begin(); it != mPrevEstimates.end(); it++) {
int32_t estimate = *it;
@@ -518,10 +518,10 @@
return err;
}
-status_t LiveSession::seekTo(int64_t timeUs, bool precise) {
+status_t LiveSession::seekTo(int64_t timeUs, MediaPlayerSeekMode mode) {
sp<AMessage> msg = new AMessage(kWhatSeek, this);
msg->setInt64("timeUs", timeUs);
- msg->setInt32("precise", precise);
+ msg->setInt32("mode", mode);
sp<AMessage> response;
status_t err = msg->postAndAwaitResponse(&response);
@@ -1442,11 +1442,11 @@
void LiveSession::onSeek(const sp<AMessage> &msg) {
int64_t timeUs;
- int32_t precise;
+ int32_t mode;
CHECK(msg->findInt64("timeUs", &timeUs));
- CHECK(msg->findInt32("precise", &precise));
- // TODO: add "precise" to changeConfiguration.
- changeConfiguration(timeUs);
+ CHECK(msg->findInt32("mode", &mode));
+ // TODO: add "mode" to changeConfiguration.
+ changeConfiguration(timeUs/* , (MediaPlayerSeekMode)mode */);
}
status_t LiveSession::getDuration(int64_t *durationUs) const {
diff --git a/media/libstagefright/httplive/LiveSession.h b/media/libstagefright/httplive/LiveSession.h
index 4dc529c..a0138be 100644
--- a/media/libstagefright/httplive/LiveSession.h
+++ b/media/libstagefright/httplive/LiveSession.h
@@ -86,7 +86,7 @@
status_t disconnect();
// Blocks until seek is complete.
- status_t seekTo(int64_t timeUs, bool precise);
+ status_t seekTo(int64_t timeUs, MediaPlayerSeekMode mode);
status_t getDuration(int64_t *durationUs) const;
size_t getTrackCount() const;
diff --git a/media/libstagefright/include/WVMExtractor.h b/media/libstagefright/include/WVMExtractor.h
deleted file mode 100644
index 65cb99a..0000000
--- a/media/libstagefright/include/WVMExtractor.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef WVM_EXTRACTOR_H_
-
-#define WVM_EXTRACTOR_H_
-
-#include <media/stagefright/MediaExtractor.h>
-#include <utils/Errors.h>
-
-namespace android {
-
-struct AMessage;
-class String8;
-class DataSource;
-
-class WVMLoadableExtractor : public MediaExtractor {
-public:
- WVMLoadableExtractor() {}
- virtual ~WVMLoadableExtractor() {}
-
- virtual int64_t getCachedDurationUs(status_t *finalStatus) = 0;
- virtual status_t getError() = 0;
- virtual status_t getEstimatedBandwidthKbps(int32_t *kbps) = 0;
- virtual void setAdaptiveStreamingMode(bool adaptive) = 0;
- virtual void setCryptoPluginMode(bool cryptoPluginMode) = 0;
- virtual void setError(status_t err) = 0;
- virtual void setUID(uid_t uid) = 0;
-};
-
-class WVMExtractor : public MediaExtractor {
-public:
- explicit WVMExtractor(const sp<DataSource> &source);
-
- virtual size_t countTracks();
- virtual sp<IMediaSource> getTrack(size_t index);
- virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
- virtual sp<MetaData> getMetaData();
- virtual void setUID(uid_t uid);
-
- // Return the amount of data cached from the current
- // playback positiion (in us).
- // While more data is still being fetched *finalStatus == OK,
- // Once fetching is completed (no more data available), *finalStatus != OK
- // If fetching completed normally (i.e. reached EOS instead of IO error)
- // *finalStatus == ERROR_END_OF_STREAM
- int64_t getCachedDurationUs(status_t *finalStatus);
-
- // Return the current estimated bandwidth
- status_t getEstimatedBandwidthKbps(int32_t *kbps);
-
- // Set to use adaptive streaming mode by the WV component.
- // If adaptive == true, adaptive streaming mode will be used.
- // Default mode is non-adaptive streaming mode.
- // Should set to use adaptive streaming mode only if widevine:// protocol
- // is used.
- void setAdaptiveStreamingMode(bool adaptive);
-
- // setCryptoPluginMode(true) to select crypto plugin mode.
- // In this mode, the extractor returns encrypted data for use
- // with the MediaCodec model, which handles the decryption in the
- // codec.
- void setCryptoPluginMode(bool cryptoPluginMode);
-
- static bool getVendorLibHandle();
-
- status_t getError();
-
- void setError(status_t err);
-
-protected:
- virtual ~WVMExtractor();
-
-private:
- sp<DataSource> mDataSource;
- sp<WVMLoadableExtractor> mImpl;
-
- WVMExtractor(const WVMExtractor &);
- WVMExtractor &operator=(const WVMExtractor &);
-};
-
-bool SniffWVM(
- const sp<DataSource> &source, String8 *mimeType, float *confidence,
- sp<AMessage> *);
-
-} // namespace android
-
-#endif // DRM_EXTRACTOR_H_
-
diff --git a/media/libstagefright/tests/Android.mk b/media/libstagefright/tests/Android.mk
index a93770a..c6963b1 100644
--- a/media/libstagefright/tests/Android.mk
+++ b/media/libstagefright/tests/Android.mk
@@ -38,35 +38,6 @@
include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE := Utils_test
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
- Utils_test.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- liblog \
- libmedia \
- libstagefright \
- libstagefright_foundation \
- libstagefright_omx \
-
-LOCAL_C_INCLUDES := \
- frameworks/av/include \
- frameworks/av/media/libstagefright \
- frameworks/av/media/libstagefright/include \
- $(TOP)/frameworks/native/include/media/openmax \
-
-LOCAL_CFLAGS += -Werror -Wall
-
-include $(BUILD_NATIVE_TEST)
-
include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
diff --git a/services/audiopolicy/engineconfigurable/Android.mk b/services/audiopolicy/engineconfigurable/Android.mk
index 6b18921..08c677e 100644
--- a/services/audiopolicy/engineconfigurable/Android.mk
+++ b/services/audiopolicy/engineconfigurable/Android.mk
@@ -48,6 +48,7 @@
libxml2
LOCAL_SHARED_LIBRARIES := \
+ liblog \
libcutils \
libutils \
liblog \
diff --git a/services/audiopolicy/engineconfigurable/wrapper/Android.mk b/services/audiopolicy/engineconfigurable/wrapper/Android.mk
index 3cc112f..d031bc3 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/Android.mk
+++ b/services/audiopolicy/engineconfigurable/wrapper/Android.mk
@@ -8,7 +8,6 @@
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/include \
- $(TARGET_OUT_HEADERS)/parameter \
$(TOPDIR)frameworks/av/services/audiopolicy/engineconfigurable/include \
$(TOPDIR)frameworks/av/services/audiopolicy/engineconfigurable/interface \
$(TOPDIR)frameworks/av/services/audiopolicy/utilities/convert \
@@ -17,6 +16,9 @@
LOCAL_WHOLE_STATIC_LIBRARIES := libmedia_helper
+LOCAL_SHARED_LIBRARIES := \
+ libparameter \
+
LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
LOCAL_MODULE:= libaudiopolicypfwwrapper
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 2f01b02..5ef0216 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1754,7 +1754,7 @@
audio_devices_t primaryInputDevices = availablePrimaryInputDevices();
if (((device & primaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
- mInputs.activeInputsCountOnDevices(primaryInputDevices) == 0) {
+ mInputs.activeInputsCountOnDevices(primaryInputDevices) == 1) {
SoundTrigger::setCaptureState(true);
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 3437e9d..3705e8f 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2962,6 +2962,8 @@
}
}
mRequestQueue.clear();
+
+ Mutex::Autolock al(mTriggerMutex);
mTriggerMap.clear();
if (lastFrameNumber != NULL) {
*lastFrameNumber = mRepeatingLastFrameNumber;
diff --git a/services/soundtrigger/Android.mk b/services/soundtrigger/Android.mk
index 5d01999..e1e1fb1 100644
--- a/services/soundtrigger/Android.mk
+++ b/services/soundtrigger/Android.mk
@@ -42,7 +42,8 @@
LOCAL_SHARED_LIBRARIES += \
libhwbinder \
- libhidl \
+ libhidlbase \
+ libhidltransport \
libbase \
android.hardware.soundtrigger@2.0 \
android.hardware.audio.common@2.0