Merge "MediaCodec refactoring part 2-a: introduce callback"
diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp
index 26135d7..3108a67 100644
--- a/cmds/stagefright/codec.cpp
+++ b/cmds/stagefright/codec.cpp
@@ -32,7 +32,6 @@
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AString.h>
-#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaCodec.h>
#include <media/stagefright/MediaCodecList.h>
#include <media/stagefright/MediaDefs.h>
@@ -401,8 +400,6 @@
ProcessState::self()->startThreadPool();
- DataSource::RegisterDefaultSniffers();
-
sp<ALooper> looper = new ALooper;
looper->start();
diff --git a/cmds/stagefright/mediafilter.cpp b/cmds/stagefright/mediafilter.cpp
index 410dd69..f219e69 100644
--- a/cmds/stagefright/mediafilter.cpp
+++ b/cmds/stagefright/mediafilter.cpp
@@ -30,7 +30,6 @@
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaCodec.h>
#include <media/stagefright/NuMediaExtractor.h>
#include <media/stagefright/RenderScriptWrapper.h>
@@ -738,8 +737,6 @@
ProcessState::self()->startThreadPool();
- DataSource::RegisterDefaultSniffers();
-
android::sp<ALooper> looper = new ALooper;
looper->start();
diff --git a/cmds/stagefright/muxer.cpp b/cmds/stagefright/muxer.cpp
index 0a3bdf3..4a83a4a 100644
--- a/cmds/stagefright/muxer.cpp
+++ b/cmds/stagefright/muxer.cpp
@@ -29,7 +29,6 @@
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AString.h>
-#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaCodec.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaMuxer.h>
@@ -319,9 +318,6 @@
}
ProcessState::self()->startThreadPool();
- // Make sure setDataSource() works.
- DataSource::RegisterDefaultSniffers();
-
sp<ALooper> looper = new ALooper;
looper->start();
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
index 9aa0156..94c2e96 100644
--- a/cmds/stagefright/record.cpp
+++ b/cmds/stagefright/record.cpp
@@ -170,8 +170,6 @@
int main(int argc, char **argv) {
android::ProcessState::self()->startThreadPool();
- DataSource::RegisterDefaultSniffers();
-
#if 1
if (argc != 3) {
fprintf(stderr, "usage: %s <filename> <input_color_format>\n", argv[0]);
diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp
index 31acdbc..12bbfd1 100644
--- a/cmds/stagefright/sf2.cpp
+++ b/cmds/stagefright/sf2.cpp
@@ -728,8 +728,6 @@
return 1;
}
- DataSource::RegisterDefaultSniffers();
-
sp<ALooper> looper = new ALooper;
looper->setName("sf2");
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 2bb35cb..5e3a859 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -965,8 +965,6 @@
}
}
- DataSource::RegisterDefaultSniffers();
-
status_t err = OK;
for (int k = 0; k < argc && err == OK; ++k) {
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index 16ff39d..0cba8b9 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -301,8 +301,6 @@
int main(int argc, char **argv) {
android::ProcessState::self()->startThreadPool();
- DataSource::RegisterDefaultSniffers();
-
if (argc != 2) {
fprintf(stderr, "Usage: %s filename\n", argv[0]);
return 1;
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/BufferingSettings.h b/include/media/BufferingSettings.h
new file mode 100644
index 0000000..7dd9d40
--- /dev/null
+++ b/include/media/BufferingSettings.h
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_BUFFERING_SETTINGS_H
+#define ANDROID_BUFFERING_SETTINGS_H
+
+#include <binder/Parcelable.h>
+
+namespace android {
+
+enum BufferingMode : int {
+ // Do not support buffering.
+ BUFFERING_MODE_NONE = 0,
+ // Support only time based buffering.
+ BUFFERING_MODE_TIME_ONLY = 1,
+ // Support only size based buffering.
+ BUFFERING_MODE_SIZE_ONLY = 2,
+ // Support both time and size based buffering, time based calculation precedes size based.
+ // Size based calculation will be used only when time information is not available for
+ // the stream.
+ BUFFERING_MODE_TIME_THEN_SIZE = 3,
+ // Number of modes.
+ BUFFERING_MODE_COUNT = 4,
+};
+
+struct BufferingSettings : public Parcelable {
+ static const int kNoWatermark = -1;
+
+ static bool IsValidBufferingMode(int mode);
+
+ BufferingMode mInitialBufferingMode; // for prepare
+ BufferingMode mRebufferingMode; // for playback
+
+ int mInitialWatermarkMs; // time based
+ int mInitialWatermarkKB; // size based
+
+ // When cached data is below this mark, playback will be paused for buffering
+ // till data reach |mRebufferingWatermarkHighMs| or end of stream.
+ int mRebufferingWatermarkLowMs;
+ // When cached data is above this mark, buffering will be paused.
+ int mRebufferingWatermarkHighMs;
+
+ // When cached data is below this mark, playback will be paused for buffering
+ // till data reach |mRebufferingWatermarkHighKB| or end of stream.
+ int mRebufferingWatermarkLowKB;
+ // When cached data is above this mark, buffering will be paused.
+ int mRebufferingWatermarkHighKB;
+
+ BufferingSettings();
+
+ status_t writeToParcel(Parcel* parcel) const override;
+ status_t readFromParcel(const Parcel* parcel) override;
+
+};
+
+} // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_BUFFERING_SETTINGS_H
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index 99ef59f..f642373 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -39,6 +39,7 @@
struct IMediaHTTPService;
struct AudioPlaybackRate;
struct AVSyncSettings;
+struct BufferingSettings;
typedef IMediaSource::ReadOptions::SeekMode MediaPlayerSeekMode;
@@ -59,6 +60,9 @@
virtual status_t setDataSource(const sp<IDataSource>& source) = 0;
virtual status_t setVideoSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer) = 0;
+ virtual status_t getDefaultBufferingSettings(
+ BufferingSettings* buffering /* nonnull */) = 0;
+ virtual status_t setBufferingSettings(const BufferingSettings& buffering) = 0;
virtual status_t prepareAsync() = 0;
virtual status_t start() = 0;
virtual status_t stop() = 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 4e4878a..0e815cb 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -30,6 +30,7 @@
#include <media/AudioSystem.h>
#include <media/AudioTimestamp.h>
#include <media/AVSyncSettings.h>
+#include <media/BufferingSettings.h>
#include <media/Metadata.h>
// Fwd decl to make sure everyone agrees that the scope of struct sockaddr_in is
@@ -174,6 +175,15 @@
virtual status_t setVideoSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer) = 0;
+ virtual status_t getDefaultBufferingSettings(
+ BufferingSettings* buffering /* nonnull */) {
+ *buffering = BufferingSettings();
+ return OK;
+ }
+ virtual status_t setBufferingSettings(const BufferingSettings& /* buffering */) {
+ return OK;
+ }
+
virtual status_t prepare() = 0;
virtual status_t prepareAsync() = 0;
virtual status_t start() = 0;
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index 0254545..3479f76 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -102,17 +102,6 @@
////////////////////////////////////////////////////////////////////////////
- bool sniff(String8 *mimeType, float *confidence, sp<AMessage> *meta);
-
- // The sniffer can optionally fill in "meta" with an AMessage containing
- // a dictionary of values that helps the corresponding extractor initialize
- // its state without duplicating effort already exerted by the sniffer.
- typedef bool (*SnifferFunc)(
- const sp<DataSource> &source, String8 *mimeType,
- float *confidence, sp<AMessage> *meta);
-
- static void RegisterDefaultSniffers();
-
// for DRM
virtual sp<DecryptHandle> DrmInitialization(const char *mime = NULL) {
return NULL;
@@ -131,12 +120,6 @@
virtual ~DataSource() {}
private:
- static Mutex gSnifferMutex;
- static List<SnifferFunc> gSniffers;
- static bool gSniffersRegistered;
-
- static void RegisterSniffer_l(SnifferFunc func);
-
DataSource(const DataSource &);
DataSource &operator=(const DataSource &);
};
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/MediaExtractor.h b/include/media/stagefright/MediaExtractor.h
index 6bf8c9e..e5ee72e 100644
--- a/include/media/stagefright/MediaExtractor.h
+++ b/include/media/stagefright/MediaExtractor.h
@@ -80,6 +80,24 @@
private:
bool mIsDrm;
+ typedef bool (*SnifferFunc)(
+ const sp<DataSource> &source, String8 *mimeType,
+ float *confidence, sp<AMessage> *meta);
+
+ static Mutex gSnifferMutex;
+ static List<SnifferFunc> gSniffers;
+ static bool gSniffersRegistered;
+
+ // The sniffer can optionally fill in "meta" with an AMessage containing
+ // a dictionary of values that helps the corresponding extractor initialize
+ // its state without duplicating effort already exerted by the sniffer.
+ static void RegisterSniffer_l(SnifferFunc func);
+
+ static bool sniff(const sp<DataSource> &source,
+ String8 *mimeType, float *confidence, sp<AMessage> *meta);
+
+ static void RegisterDefaultSniffers();
+
MediaExtractor(const MediaExtractor &);
MediaExtractor &operator=(const MediaExtractor &);
};
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/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 2e4cf7d..f4d8bc0 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -12,6 +12,7 @@
LOCAL_SRC_FILES += \
IDataSource.cpp \
IHDCP.cpp \
+ BufferingSettings.cpp \
mediaplayer.cpp \
IMediaCodecList.cpp \
IMediaCodecService.cpp \
diff --git a/media/libmedia/BufferingSettings.cpp b/media/libmedia/BufferingSettings.cpp
new file mode 100644
index 0000000..6dc4a53
--- /dev/null
+++ b/media/libmedia/BufferingSettings.cpp
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "BufferingSettings"
+//#define LOG_NDEBUG 0
+
+#include <binder/Parcel.h>
+
+#include <media/BufferingSettings.h>
+
+namespace android {
+
+// static
+bool BufferingSettings::IsValidBufferingMode(int mode) {
+ return (mode >= BUFFERING_MODE_NONE && mode < BUFFERING_MODE_COUNT);
+}
+
+BufferingSettings::BufferingSettings()
+ : mInitialBufferingMode(BUFFERING_MODE_NONE),
+ mRebufferingMode(BUFFERING_MODE_NONE),
+ mInitialWatermarkMs(kNoWatermark),
+ mInitialWatermarkKB(kNoWatermark),
+ mRebufferingWatermarkLowMs(kNoWatermark),
+ mRebufferingWatermarkHighMs(kNoWatermark),
+ mRebufferingWatermarkLowKB(kNoWatermark),
+ mRebufferingWatermarkHighKB(kNoWatermark) { }
+
+status_t BufferingSettings::readFromParcel(const Parcel* parcel) {
+ if (parcel == nullptr) {
+ return BAD_VALUE;
+ }
+ mInitialBufferingMode = (BufferingMode)parcel->readInt32();
+ mRebufferingMode = (BufferingMode)parcel->readInt32();
+ mInitialWatermarkMs = parcel->readInt32();
+ mInitialWatermarkKB = parcel->readInt32();
+ mRebufferingWatermarkLowMs = parcel->readInt32();
+ mRebufferingWatermarkHighMs = parcel->readInt32();
+ mRebufferingWatermarkLowKB = parcel->readInt32();
+ mRebufferingWatermarkHighKB = parcel->readInt32();
+
+ return OK;
+}
+
+status_t BufferingSettings::writeToParcel(Parcel* parcel) const {
+ if (parcel == nullptr) {
+ return BAD_VALUE;
+ }
+ parcel->writeInt32(mInitialBufferingMode);
+ parcel->writeInt32(mRebufferingMode);
+ parcel->writeInt32(mInitialWatermarkMs);
+ parcel->writeInt32(mInitialWatermarkKB);
+ parcel->writeInt32(mRebufferingWatermarkLowMs);
+ parcel->writeInt32(mRebufferingWatermarkHighMs);
+ parcel->writeInt32(mRebufferingWatermarkLowKB);
+ parcel->writeInt32(mRebufferingWatermarkHighKB);
+
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index dda2570..9ffde4e 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -23,6 +23,7 @@
#include <media/AudioResamplerPublic.h>
#include <media/AVSyncSettings.h>
+#include <media/BufferingSettings.h>
#include <media/IDataSource.h>
#include <media/IMediaHTTPService.h>
@@ -40,6 +41,8 @@
SET_DATA_SOURCE_FD,
SET_DATA_SOURCE_STREAM,
SET_DATA_SOURCE_CALLBACK,
+ SET_BUFFERING_SETTINGS,
+ GET_DEFAULT_BUFFERING_SETTINGS,
PREPARE_ASYNC,
START,
STOP,
@@ -148,6 +151,30 @@
return reply.readInt32();
}
+ status_t setBufferingSettings(const BufferingSettings& buffering)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ buffering.writeToParcel(&data);
+ remote()->transact(SET_BUFFERING_SETTINGS, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t getDefaultBufferingSettings(BufferingSettings* buffering /* nonnull */)
+ {
+ if (buffering == nullptr) {
+ return BAD_VALUE;
+ }
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ remote()->transact(GET_DEFAULT_BUFFERING_SETTINGS, data, &reply);
+ status_t err = reply.readInt32();
+ if (err == OK) {
+ err = buffering->readFromParcel(&reply);
+ }
+ return err;
+ }
+
status_t prepareAsync()
{
Parcel data, reply;
@@ -497,6 +524,23 @@
reply->writeInt32(setVideoSurfaceTexture(bufferProducer));
return NO_ERROR;
} break;
+ case SET_BUFFERING_SETTINGS: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ BufferingSettings buffering;
+ buffering.readFromParcel(&data);
+ reply->writeInt32(setBufferingSettings(buffering));
+ return NO_ERROR;
+ } break;
+ case GET_DEFAULT_BUFFERING_SETTINGS: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ BufferingSettings buffering;
+ status_t err = getDefaultBufferingSettings(&buffering);
+ reply->writeInt32(err);
+ if (err == OK) {
+ buffering.writeToParcel(reply);
+ }
+ return NO_ERROR;
+ } break;
case PREPARE_ASYNC: {
CHECK_INTERFACE(IMediaPlayer, data, reply);
reply->writeInt32(prepareAsync());
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index c1fe87f..3d466b1 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -590,7 +590,7 @@
params = mmap(NULL, allocSize, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1 /* fd */, 0 /* offset */);
}
- if (params != MAP_FAILED) {
+ if (params != MAP_FAILED && params != NULL) {
err = data.read(params, size);
if (err != OK) {
android_errorWriteLog(0x534e4554, "26914474");
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/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 6e163d9..3ad461c 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -972,6 +972,42 @@
return OK;
}
+status_t MediaPlayerService::Client::setBufferingSettings(
+ const BufferingSettings& buffering)
+{
+ ALOGV("[%d] setBufferingSettings(%d, %d, %d, %d, %d, %d, %d, %d)",
+ mConnId, buffering.mInitialBufferingMode, buffering.mRebufferingMode,
+ buffering.mInitialWatermarkMs, buffering.mInitialWatermarkKB,
+ buffering.mRebufferingWatermarkLowMs,
+ buffering.mRebufferingWatermarkHighMs,
+ buffering.mRebufferingWatermarkLowKB,
+ buffering.mRebufferingWatermarkHighKB);
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == 0) return UNKNOWN_ERROR;
+ return p->setBufferingSettings(buffering);
+}
+
+status_t MediaPlayerService::Client::getDefaultBufferingSettings(
+ BufferingSettings* buffering /* nonnull */)
+{
+ sp<MediaPlayerBase> p = getPlayer();
+ // TODO: create mPlayer on demand.
+ if (p == 0) return UNKNOWN_ERROR;
+ status_t ret = p->getDefaultBufferingSettings(buffering);
+ if (ret == NO_ERROR) {
+ ALOGV("[%d] getDefaultBufferingSettings(%d, %d, %d, %d, %d, %d, %d, %d)",
+ mConnId, buffering->mInitialBufferingMode, buffering->mRebufferingMode,
+ buffering->mInitialWatermarkMs, buffering->mInitialWatermarkKB,
+ buffering->mRebufferingWatermarkLowMs,
+ buffering->mRebufferingWatermarkHighMs,
+ buffering->mRebufferingWatermarkLowKB,
+ buffering->mRebufferingWatermarkHighKB);
+ } else {
+ ALOGV("[%d] getDefaultBufferingSettings returned %d", mConnId, ret);
+ }
+ return ret;
+}
+
status_t MediaPlayerService::Client::prepareAsync()
{
ALOGV("[%d] prepareAsync", mConnId);
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index a4ea37f..8a6ada0 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -288,6 +288,9 @@
virtual void disconnect();
virtual status_t setVideoSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer);
+ virtual status_t setBufferingSettings(const BufferingSettings& buffering) override;
+ virtual status_t getDefaultBufferingSettings(
+ BufferingSettings* buffering /* nonnull */) override;
virtual status_t prepareAsync();
virtual status_t start();
virtual status_t stop();
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index fce9ab5..4956fa0 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),
@@ -70,7 +68,6 @@
mPendingReadBufferTypes(0) {
mBufferingMonitor = new BufferingMonitor(notify);
resetDataSource();
- DataSource::RegisterDefaultSniffers();
}
void NuPlayer::GenericSource::resetDataSource() {
@@ -141,44 +138,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 +156,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 +247,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 +332,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 +346,6 @@
mHTTPService, uri, &mUriHeaders, &contentType,
static_cast<HTTPBase *>(mHttpSource.get()));
} else {
- mIsWidevine = false;
-
mDataSource = new FileSource(mFd, mOffset, mLength);
mFd = -1;
}
@@ -412,13 +361,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 +395,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 +424,7 @@
if (mIsStreaming) {
if (mBufferingMonitorLooper == NULL) {
- mBufferingMonitor->prepare(mCachedSource, mWVMExtractor, mDurationUs, mBitrate,
+ mBufferingMonitor->prepare(mCachedSource, mDurationUs, mBitrate,
mIsStreaming);
mBufferingMonitorLooper = new ALooper;
@@ -536,12 +484,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() {
@@ -719,20 +661,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;
@@ -888,11 +816,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) {
@@ -1222,6 +1145,9 @@
// 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;
}
@@ -1366,6 +1292,9 @@
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;
}
@@ -1374,19 +1303,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;
@@ -1414,9 +1335,9 @@
seeking = true;
}
- const bool couldReadMultiple = (!mIsWidevine && track->mSource->supportReadMultiple());
+ const bool couldReadMultiple = (track->mSource->supportReadMultiple());
- if (mIsWidevine || couldReadMultiple) {
+ if (couldReadMultiple) {
options.setNonBlocking();
}
@@ -1538,17 +1459,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 */);
}
@@ -1603,22 +1523,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;
@@ -1702,9 +1617,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);
}
@@ -1744,10 +1657,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 d317c42..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);
@@ -103,7 +102,6 @@
kWhatSelectTrack,
kWhatSeek,
kWhatReadBuffer,
- kWhatStopWidevine,
kWhatStart,
kWhatResume,
kWhatSecureDecodersInstantiated,
@@ -123,7 +121,6 @@
// Set up state.
void prepare(const sp<NuCachedSource2> &cachedSource,
- const sp<WVMExtractor> &wvmExtractor,
int64_t durationUs,
int64_t bitrate,
bool isStreaming);
@@ -157,7 +154,6 @@
sp<AMessage> mNotify;
sp<NuCachedSource2> mCachedSource;
- sp<WVMExtractor> mWVMExtractor;
int64_t mDurationUs;
int64_t mBitrate;
bool mIsStreaming;
@@ -177,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);
@@ -206,7 +201,6 @@
int32_t mFetchTimedTextDataGeneration;
int64_t mDurationUs;
bool mAudioIsVorbis;
- bool mIsWidevine;
bool mIsSecure;
bool mIsStreaming;
bool mUIDValid;
@@ -221,7 +215,6 @@
sp<DataSource> mDataSource;
sp<NuCachedSource2> mCachedSource;
sp<DataSource> mHttpSource;
- sp<WVMExtractor> mWVMExtractor;
sp<MetaData> mFileMeta;
DrmManagerClient *mDrmManagerClient;
sp<DecryptHandle> mDecryptHandle;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index d240521..1476206 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -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);
@@ -1671,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();
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/liboboe/README.md b/media/liboboe/README.md
new file mode 100644
index 0000000..80894c6
--- /dev/null
+++ b/media/liboboe/README.md
@@ -0,0 +1 @@
+Oboe Audio input/output API
diff --git a/media/liboboe/include/oboe/OboeAudio.h b/media/liboboe/include/oboe/OboeAudio.h
new file mode 100644
index 0000000..35013a7
--- /dev/null
+++ b/media/liboboe/include/oboe/OboeAudio.h
@@ -0,0 +1,482 @@
+/*
+ * 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.
+ */
+
+/**
+ * This is the 'C' ABI for Oboe.
+ */
+#ifndef OBOE_OBOEAUDIO_H
+#define OBOE_OBOEAUDIO_H
+
+#include "OboeDefinitions.h"
+
+typedef int32_t OboeDeviceId;
+typedef oboe_handle_t OboeStream;
+typedef oboe_handle_t OboeStreamBuilder;
+typedef oboe_handle_t OboeThread;
+
+#define OBOE_STREAM_NONE ((OboeStream)OBOE_HANDLE_INVALID)
+#define OBOE_STREAM_BUILDER_NONE ((OboeStreamBuilder)OBOE_HANDLE_INVALID)
+
+
+// ============================================================
+// Audio System
+// ============================================================
+
+/**
+ * @return time in the same clock domain as the timestamps
+ */
+oboe_nanoseconds_t Oboe_getNanoseconds(oboe_clockid_t clockid);
+
+/**
+ * The text is the ASCII symbol corresponding to the returnCode,
+ * or an English message saying the returnCode is unrecognized.
+ * This is intended for developers to use when debugging.
+ * It is not for display to users.
+ *
+ * @return pointer to a text representation of an Oboe result code.
+ */
+const char * Oboe_convertResultToText(oboe_result_t returnCode);
+
+/**
+ * The text is the ASCII symbol corresponding to the state,
+ * or an English message saying the state is unrecognized.
+ * This is intended for developers to use when debugging.
+ * It is not for display to users.
+ *
+ * @return pointer to a text representation of an Oboe state.
+ */
+const char * Oboe_convertStateToText(oboe_state_t state);
+
+// ============================================================
+// StreamBuilder
+// ============================================================
+/**
+ * Create a StreamBuilder that can be used to open a Stream.
+ *
+ * OboeStreamBuilder_delete() must be called when you are done using the builder.
+ */
+oboe_result_t Oboe_createStreamBuilder(OboeStreamBuilder *builder);
+
+/**
+ * Request an audio device identified device using an ID.
+ * The ID is platform specific.
+ * On Android, for example, the ID could be obtained from the Java AudioManager.
+ *
+ * By default, the primary output device will be used.
+ *
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStreamBuilder_setDeviceId(OboeStreamBuilder builder, OboeDeviceId deviceId);
+
+/**
+ * Request a sample rate in Hz.
+ * The stream may be opened with a different sample rate.
+ * So the application should query for the actual rate after the stream is opened.
+ *
+ * Technically, this should be called the "frame rate" or "frames per second",
+ * because it refers to the number of complete frames transferred per second.
+ * But it is traditionally called "sample rate". Se we use that term.
+ *
+ * Default is OBOE_UNSPECIFIED.
+ *
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStreamBuilder_setSampleRate(OboeStreamBuilder builder,
+ oboe_sample_rate_t sampleRate);
+
+/**
+ * Returns sample rate in Hertz (samples per second).
+ * @return positive sampleRate or a negative error, zero for unspecified
+ */
+oboe_result_t OboeStreamBuilder_getSampleRate(OboeStreamBuilder builder,
+ oboe_sample_rate_t *sampleRate);
+
+
+/**
+ * Request a number of samples per frame.
+ * The stream may be opened with a different value.
+ * So the application should query for the actual value after the stream is opened.
+ *
+ * Default is OBOE_UNSPECIFIED.
+ *
+ * Note, this quantity is sometimes referred to as "channel count".
+ *
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStreamBuilder_setSamplesPerFrame(OboeStreamBuilder builder,
+ int32_t samplesPerFrame);
+
+/**
+ * Note, this quantity is sometimes referred to as "channel count".
+ *
+ * @param builder handle provided by Oboe_createStreamBuilder()
+ * @param samplesPerFrame pointer to a variable to be set to samplesPerFrame.
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStreamBuilder_getSamplesPerFrame(OboeStreamBuilder builder,
+ int32_t *samplesPerFrame);
+
+
+/**
+ * Request a sample data format, for example OBOE_AUDIO_FORMAT_PCM16.
+ * The application should query for the actual format after the stream is opened.
+ *
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStreamBuilder_setFormat(OboeStreamBuilder builder, oboe_audio_format_t format);
+
+/**
+ * @return positive data format or a negative error, zero for unspecified
+ */
+oboe_result_t OboeStreamBuilder_getFormat(OboeStreamBuilder builder, oboe_audio_format_t *format);
+
+/**
+ * Request a mode for sharing the device.
+ * The requested sharing mode may not be available.
+ * So the application should query for the actual mode after the stream is opened.
+ *
+ * @param builder handle provided by Oboe_createStreamBuilder()
+ * @param sharingMode OBOE_SHARING_MODE_LEGACY or OBOE_SHARING_MODE_EXCLUSIVE
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStreamBuilder_setSharingMode(OboeStreamBuilder builder,
+ oboe_sharing_mode_t sharingMode);
+
+/**
+ * Return requested sharing mode.
+ * @return OBOE_OK or a negative error
+ */
+oboe_result_t OboeStreamBuilder_getSharingMode(OboeStreamBuilder builder,
+ oboe_sharing_mode_t *sharingMode);
+
+/**
+ * Request the direction for a stream. The default is OBOE_DIRECTION_OUTPUT.
+ *
+ * @param builder handle provided by Oboe_createStreamBuilder()
+ * @param direction OBOE_DIRECTION_OUTPUT or OBOE_DIRECTION_INPUT
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStreamBuilder_setDirection(OboeStreamBuilder builder,
+ oboe_direction_t direction);
+
+/**
+ * @param builder handle provided by Oboe_createStreamBuilder()
+ * @param direction pointer to a variable to be set to the currently requested direction.
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStreamBuilder_getDirection(OboeStreamBuilder builder,
+ oboe_direction_t *direction);
+
+/**
+ * Open a stream based on the options in the StreamBuilder.
+ *
+ * OboeStream_close must be called when finished with the stream to recover
+ * the memory and to free the associated resources.
+ *
+ * @return OBOE_OK or a negative error. Also pass back a stream handle.
+ */
+oboe_result_t OboeStreamBuilder_openStream(OboeStreamBuilder builder, OboeStream *stream);
+
+/**
+ * Delete the resources associated with the StreamBuilder.
+ * @param builder handle provided by Oboe_createStreamBuilder()
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStreamBuilder_delete(OboeStreamBuilder builder);
+
+// ============================================================
+// Stream Control
+// ============================================================
+
+/**
+ * Free the resources associated with a stream created by OboeStreamBuilder_openStream()
+ */
+oboe_result_t OboeStream_close(OboeStream stream);
+
+/**
+ * Asynchronously request to start playing the stream. For output streams, one should
+ * write to the stream to fill the buffer before starting.
+ * Otherwise it will underflow.
+ * After this call the state will be in OBOE_STATE_STARTING or OBOE_STATE_STARTED.
+ */
+oboe_result_t OboeStream_requestStart(OboeStream stream);
+
+/**
+ * Asynchronous request for the stream to pause.
+ * Pausing a stream will freeze the data flow but not flush any buffers.
+ * Use OboeStream_Start() to resume playback after a pause.
+ * After this call the state will be in OBOE_STATE_PAUSING or OBOE_STATE_PAUSED.
+ */
+oboe_result_t OboeStream_requestPause(OboeStream stream);
+
+/**
+ * Asynchronous request for the stream to flush.
+ * Flushing will discard any pending data.
+ * This call only works if the stream is pausing or paused. TODO review
+ * Frame counters are not reset by a flush. They may be advanced.
+ * After this call the state will be in OBOE_STATE_FLUSHING or OBOE_STATE_FLUSHED.
+ */
+oboe_result_t OboeStream_requestFlush(OboeStream stream);
+
+/**
+ * Asynchronous request for the stream to stop.
+ * The stream will stop after all of the data currently buffered has been played.
+ * After this call the state will be in OBOE_STATE_STOPPING or OBOE_STATE_STOPPED.
+ */
+oboe_result_t OboeStream_requestStop(OboeStream stream);
+
+/**
+ * Query the current state, eg. OBOE_STATE_PAUSING
+ *
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStream_getState(OboeStream stream, oboe_state_t *state);
+
+/**
+ * Wait until the current state no longer matches the input state.
+ *
+ * <pre><code>
+ * oboe_state_t currentState = OboeStream_getState(stream);
+ * while (currentState >= 0 && currentState != OBOE_STATE_PAUSING) {
+ * currentState = OboeStream_waitForStateChange(
+ * stream, currentState, MY_TIMEOUT_MSEC);
+ * }
+ * </code></pre>
+ *
+ * @param stream A handle provided by OboeStreamBuilder_openStream()
+ * @param inputState The state we want to avoid.
+ * @param nextState Pointer to a variable that will be set to the new state.
+ * @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion.
+ * @return oboe_state_t or a negative error.
+ */
+oboe_result_t OboeStream_waitForStateChange(OboeStream stream,
+ oboe_state_t inputState,
+ oboe_state_t *nextState,
+ oboe_nanoseconds_t timeoutNanoseconds);
+
+// ============================================================
+// Stream I/O
+// ============================================================
+
+/**
+ * Read data from the stream.
+ *
+ * The call will wait until the read is complete or until it runs out of time.
+ * If timeoutNanos is zero then this call will not wait.
+ *
+ * Note that timeoutNanoseconds is a relative duration in wall clock time.
+ * Time will not stop if the thread is asleep.
+ * So it will be implemented using CLOCK_BOOTTIME.
+ *
+ * This call is "strong non-blocking" unless it has to wait for data.
+ *
+ * @param stream A stream created using OboeStreamBuilder_openStream().
+ * @param buffer The address of the first sample.
+ * @param numFrames Number of frames to read. Only complete frames will be written.
+ * @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion.
+ * @return The number of frames actually written or a negative error.
+ */
+oboe_result_t OboeStream_read(OboeStream stream,
+ void *buffer,
+ int32_t numFrames,
+ oboe_nanoseconds_t timeoutNanoseconds);
+
+/**
+ * Write data to the stream.
+ *
+ * The call will wait until the write is complete or until it runs out of time.
+ * If timeoutNanos is zero then this call will not wait.
+ *
+ * Note that timeoutNanoseconds is a relative duration in wall clock time.
+ * Time will not stop if the thread is asleep.
+ * So it will be implemented using CLOCK_BOOTTIME.
+ *
+ * This call is "strong non-blocking" unless it has to wait for room in the buffer.
+ *
+ * @param stream A stream created using OboeStreamBuilder_openStream().
+ * @param buffer The address of the first sample.
+ * @param numFrames Number of frames to write. Only complete frames will be written.
+ * @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion.
+ * @return The number of frames actually written or a negative error.
+ */
+oboe_result_t OboeStream_write(OboeStream stream,
+ const void *buffer,
+ int32_t numFrames,
+ oboe_nanoseconds_t timeoutNanoseconds);
+
+
+// ============================================================
+// High priority audio threads
+// ============================================================
+
+/**
+ * Create a thread with special properties for low latency audio performance.
+ * This thread can be used to implement a callback API.
+ *
+ * Note that this API is in flux.
+ *
+ * @param threadHandlePtr a pointer to receive a thread handle
+ * @param periodNanoseconds the estimated period at which the audio thread will need to wake up
+ * @param start_routine your thread entry point
+ * @param arg an argument that will be passed to your thread entry point
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t Oboe_createAudioThread(OboeThread *threadHandlePtr,
+ oboe_nanoseconds_t periodNanoseconds,
+ void *(*start_routine)(void *), void *arg);
+
+/**
+ * Wait until the thread exits or an error occurs.
+ * The thread handle will be deleted.
+ *
+ * @param thread the thread handle passed back from Oboe_createAudioThread()
+ * @param returnArg a pointer to a variable to receive the return value
+ * @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion.
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t Oboe_joinAudioThread(OboeThread thread,
+ void **returnArg,
+ oboe_nanoseconds_t timeoutNanoseconds);
+
+// ============================================================
+// Stream - queries
+// ============================================================
+
+
+/**
+ * This can be used to adjust the latency of the buffer by changing
+ * the threshold where blocking will occur.
+ * By combining this with OboeStream_getUnderrunCount(), the latency can be tuned
+ * at run-time for each device.
+ *
+ * This cannot be set higher than OboeStream_getBufferCapacity().
+ *
+ * @param stream handle provided by OboeStreamBuilder_openStream()
+ * @param frames requested number of frames that can be filled without blocking
+ * @return actual number of frames or a negative error
+ */
+oboe_result_t OboeStream_setBufferSize(OboeStream stream, oboe_size_frames_t frames);
+
+/**
+ * Query the maximum number of frames that can be filled without blocking.
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStream_getBufferSize(OboeStream stream, oboe_size_frames_t *frames);
+
+/**
+ * Query the number of frames that are read or written by the endpoint at one time.
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStream_getFramesPerBurst(OboeStream stream, oboe_size_frames_t *frames);
+
+/**
+ * Query maximum buffer capacity in frames.
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStream_getBufferCapacity(OboeStream stream, oboe_size_frames_t *frames);
+
+/**
+ * An XRun is an Underrun or an Overrun.
+ * During playing, an underrun will occur if the stream is not written in time
+ * and the system runs out of valid data.
+ * During recording, an overrun will occur if the stream is not read in time
+ * and there is no place to put the incoming data so it is discarded.
+ *
+ * An underrun or overrun can cause an audible "pop" or "glitch".
+ *
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStream_getXRunCount(OboeStream stream, int32_t *xRunCount);
+
+/**
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStream_getSampleRate(OboeStream stream, int32_t *sampleRate);
+
+/**
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStream_getSamplesPerFrame(OboeStream stream, int32_t *samplesPerFrame);
+
+/**
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStream_getFormat(OboeStream stream, oboe_audio_format_t *format);
+
+/**
+ * Provide actual sharing mode.
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStream_getSharingMode(OboeStream stream,
+ oboe_sharing_mode_t *sharingMode);
+
+/**
+ * @param stream handle provided by OboeStreamBuilder_openStream()
+ * @param direction pointer to a variable to be set to the current direction.
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStream_getDirection(OboeStream stream, uint32_t *direction);
+
+/**
+ * Passes back the number of frames that have been written since the stream was created.
+ * For an output stream, this will be advanced by the application calling write().
+ * For an input stream, this will be advanced by the device or service.
+ *
+ * The frame position is monotonically increasing.
+ *
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStream_getFramesWritten(OboeStream stream, oboe_position_frames_t *frames);
+
+/**
+ * Passes back the number of frames that have been read since the stream was created.
+ * For an output stream, this will be advanced by the device or service.
+ * For an input stream, this will be advanced by the application calling read().
+ *
+ * The frame position is monotonically increasing.
+ *
+ * @return OBOE_OK or a negative error.
+ */
+oboe_result_t OboeStream_getFramesRead(OboeStream stream, oboe_position_frames_t *frames);
+
+/**
+ * Passes back the time at which a particular frame was presented.
+ * This can be used to synchronize audio with video or MIDI.
+ * It can also be used to align a recorded stream with a playback stream.
+ *
+ * Timestamps are only valid when the stream is in OBOE_STATE_STARTED.
+ * OBOE_ERROR_INVALID_STATE will be returned if the stream is not started.
+ * Note that because requestStart() is asynchronous, timestamps will not be valid until
+ * a short time after calling requestStart().
+ * So OBOE_ERROR_INVALID_STATE should not be considered a fatal error.
+ * Just try calling again later.
+ *
+ * If an error occurs, then the position and time will not be modified.
+ *
+ * The position and time passed back are monotonically increasing.
+ *
+ * @param stream A handle provided by OboeStreamBuilder_openStream()
+ * @param clockId OBOE_CLOCK_MONOTONIC or OBOE_CLOCK_BOOTTIME
+ * @param framePosition pointer to a variable to receive the position
+ * @param timeNanoseconds pointer to a variable to receive the time
+ * @return OBOE_OK or a negative error
+ */
+oboe_result_t OboeStream_getTimestamp(OboeStream stream,
+ oboe_clockid_t clockid,
+ oboe_position_frames_t *framePosition,
+ oboe_nanoseconds_t *timeNanoseconds);
+
+#endif //NATIVEOBOE_OBOEAUDIO_H
diff --git a/media/liboboe/include/oboe/OboeDefinitions.h b/media/liboboe/include/oboe/OboeDefinitions.h
new file mode 100644
index 0000000..ff9bd92
--- /dev/null
+++ b/media/liboboe/include/oboe/OboeDefinitions.h
@@ -0,0 +1,177 @@
+/*
+ * 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 OBOE_OBOEDEFINITIONS_H
+#define OBOE_OBOEDEFINITIONS_H
+
+#include <stdint.h>
+
+typedef int32_t oboe_handle_t;
+typedef int32_t oboe_result_t;
+typedef int32_t oboe_sample_rate_t;
+/** This is used for small quantities such as the number of frames in a buffer. */
+typedef int32_t oboe_size_frames_t;
+/** This is used for large quantities, such as the number of frames that have
+ * been played since a stream was started.
+ * At 48000 Hz, a 32-bit integer would wrap around in just over 12 hours.
+ */
+typedef int64_t oboe_position_frames_t;
+
+typedef int64_t oboe_nanoseconds_t;
+typedef uint32_t oboe_audio_format_t;
+
+/**
+ * This is used to represent a value that has not been specified.
+ * For example, an application could use OBOE_UNSPECIFIED to indicate
+ * that is did not not care what the specific value of a parameter was
+ * and would accept whatever it was given.
+ */
+#define OBOE_UNSPECIFIED 0
+#define OBOE_NANOS_PER_MICROSECOND ((int64_t)1000)
+#define OBOE_NANOS_PER_MILLISECOND (OBOE_NANOS_PER_MICROSECOND * 1000)
+#define OBOE_MILLIS_PER_SECOND 1000
+#define OBOE_NANOS_PER_SECOND (OBOE_NANOS_PER_MILLISECOND * OBOE_MILLIS_PER_SECOND)
+
+#define OBOE_HANDLE_INVALID ((oboe_handle_t)-1)
+
+enum oboe_direction_t {
+ OBOE_DIRECTION_OUTPUT,
+ OBOE_DIRECTION_INPUT,
+ OBOE_DIRECTION_COUNT // This should always be last.
+};
+
+enum {
+ OBOE_AUDIO_DATATYPE_INT16,
+ OBOE_AUDIO_DATATYPE_INT32,
+ OBOE_AUDIO_DATATYPE_INT824,
+ OBOE_AUDIO_DATATYPE_UINT8,
+ OBOE_AUDIO_DATATYPE_FLOAT32, // Add new values below.
+ OBOE_AUDIO_DATATYPE_COUNT // This should always be last.
+};
+
+enum {
+ OBOE_AUDIO_CONTENT_PCM,
+ OBOE_AUDIO_CONTENT_MP3,
+ OBOE_AUDIO_CONTENT_AAC,
+ OBOE_AUDIO_CONTENT_AC3,
+ OBOE_AUDIO_CONTENT_EAC3,
+ OBOE_AUDIO_CONTENT_DTS,
+ OBOE_AUDIO_CONTENT_DTSHD, // Add new values below.
+ OBOE_AUDIO_CONTENT_COUNT // This should always be last.
+};
+
+enum {
+ OBOE_AUDIO_WRAPPER_NONE,
+ OBOE_AUDIO_WRAPPER_IEC61937, // Add new values below.
+ OBOE_AUDIO_WRAPPER_COUNT // This should always be last.
+};
+
+/**
+ * Fields packed into oboe_audio_format_t, from most to least significant bits.
+ * Reserved:8
+ * Wrapper:8
+ * Content:8
+ * Data Type:8
+ */
+#define OBOE_AUDIO_FORMAT(dataType, content, wrapper) \
+ ((oboe_audio_format_t)((wrapper << 16) | (content << 8) | dataType))
+
+#define OBOE_AUDIO_FORMAT_RAW(dataType, content) \
+ OBOE_AUDIO_FORMAT(dataType, content, OBOE_AUDIO_WRAPPER_NONE)
+
+#define OBOE_AUDIO_FORMAT_DATA_TYPE(format) \
+ (format & 0x0FF)
+
+// Define some common formats.
+#define OBOE_AUDIO_FORMAT_PCM16 \
+ OBOE_AUDIO_FORMAT_RAW(OBOE_AUDIO_DATATYPE_INT16, OBOE_AUDIO_CONTENT_PCM)
+#define OBOE_AUDIO_FORMAT_PCM_FLOAT \
+ OBOE_AUDIO_FORMAT_RAW(OBOE_AUDIO_DATATYPE_FLOAT32, OBOE_AUDIO_CONTENT_PCM)
+#define OBOE_AUDIO_FORMAT_PCM824 \
+ OBOE_AUDIO_FORMAT_RAW(OBOE_AUDIO_DATATYPE_INT824, OBOE_AUDIO_CONTENT_PCM)
+
+enum {
+ OBOE_OK,
+ OBOE_ERROR_BASE = -900, // TODO review
+ OBOE_ERROR_DISCONNECTED,
+ OBOE_ERROR_ILLEGAL_ARGUMENT,
+ OBOE_ERROR_INCOMPATIBLE,
+ OBOE_ERROR_INTERNAL, // an underlying API returned an error code
+ OBOE_ERROR_INVALID_STATE,
+ OBOE_ERROR_UNEXPECTED_STATE,
+ OBOE_ERROR_UNEXPECTED_VALUE,
+ OBOE_ERROR_INVALID_HANDLE,
+ OBOE_ERROR_INVALID_QUERY,
+ OBOE_ERROR_UNIMPLEMENTED,
+ OBOE_ERROR_UNAVAILABLE,
+ OBOE_ERROR_NO_FREE_HANDLES,
+ OBOE_ERROR_NO_MEMORY,
+ OBOE_ERROR_NULL,
+ OBOE_ERROR_TIMEOUT,
+ OBOE_ERROR_WOULD_BLOCK,
+ OBOE_ERROR_INVALID_ORDER
+};
+
+typedef enum {
+ OBOE_CLOCK_MONOTONIC, // Clock since booted, pauses when CPU is sleeping.
+ OBOE_CLOCK_BOOTTIME, // Clock since booted, runs all the time.
+ OBOE_CLOCK_COUNT // This should always be last.
+} oboe_clockid_t;
+
+typedef enum
+{
+ OBOE_STATE_UNINITIALIZED = 0,
+ OBOE_STATE_OPEN,
+ OBOE_STATE_STARTING,
+ OBOE_STATE_STARTED,
+ OBOE_STATE_PAUSING,
+ OBOE_STATE_PAUSED,
+ OBOE_STATE_FLUSHING,
+ OBOE_STATE_FLUSHED,
+ OBOE_STATE_STOPPING,
+ OBOE_STATE_STOPPED,
+ OBOE_STATE_CLOSING,
+ OBOE_STATE_CLOSED,
+} oboe_state_t;
+
+// TODO review API
+typedef enum {
+ /**
+ * This will use an AudioTrack object for playing audio
+ * and an AudioRecord for recording data.
+ */
+ OBOE_SHARING_MODE_LEGACY,
+ /**
+ * This will be the only stream using a particular source or sink.
+ * This mode will provide the lowest possible latency.
+ * You should close EXCLUSIVE streams immediately when you are not using them.
+ */
+ OBOE_SHARING_MODE_EXCLUSIVE,
+ /**
+ * Multiple applications will be mixed by the Oboe Server.
+ * This will have higher latency than the EXCLUSIVE mode.
+ */
+ OBOE_SHARING_MODE_SHARED,
+ /**
+ * Multiple applications will do their own mixing into a memory mapped buffer.
+ * It may be possible for malicious applications to read the data produced by
+ * other apps. So do not use this for private data such as telephony or messaging.
+ */
+ OBOE_SHARING_MODE_PUBLIC_MIX,
+ OBOE_SHARING_MODE_COUNT // This should always be last.
+} oboe_sharing_mode_t;
+
+#endif // OBOE_OBOEDEFINITIONS_H
diff --git a/media/liboboe/include/oboe/README.md b/media/liboboe/include/oboe/README.md
new file mode 100644
index 0000000..de60d03
--- /dev/null
+++ b/media/liboboe/include/oboe/README.md
@@ -0,0 +1,4 @@
+Oboe Audio headers
+
+This folder contains the public header files.
+
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 47c3f82..a0c8ace 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -5484,9 +5484,8 @@
int32_t err = OK;
bool eos = false;
PortMode mode = getPortMode(kPortIndexInput);
-
- sp<RefBase> obj;
- if (!msg->findObject("buffer", &obj)) {
+ int32_t discarded = 0;
+ if (msg->findInt32("discarded", &discarded) && discarded) {
/* these are unfilled buffers returned by client */
CHECK(msg->findInt32("err", &err));
@@ -5498,9 +5497,10 @@
mCodec->mComponentName.c_str(), err);
eos = true;
}
- } else {
- buffer = static_cast<MediaCodecBuffer *>(obj.get());
}
+ sp<RefBase> obj;
+ CHECK(msg->findObject("buffer", &obj));
+ buffer = static_cast<MediaCodecBuffer *>(obj.get());
int32_t tmp;
if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
@@ -5916,10 +5916,11 @@
IOMX::buffer_id bufferID;
CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
sp<RefBase> obj;
- sp<MediaCodecBuffer> buffer = nullptr;
- if (msg->findObject("buffer", &obj)) {
- buffer = static_cast<MediaCodecBuffer *>(obj.get());
- }
+ CHECK(msg->findObject("buffer", &obj));
+ sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
+ int32_t discarded = 0;
+ msg->findInt32("discarded", &discarded);
+
ssize_t index;
BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
BufferInfo::Status status = BufferInfo::getSafeStatus(info);
@@ -5951,7 +5952,7 @@
int32_t render;
if (mCodec->mNativeWindow != NULL
&& msg->findInt32("render", &render) && render != 0
- && buffer != NULL && buffer->size() != 0) {
+ && !discarded && buffer->size() != 0) {
ATRACE_NAME("render");
// The client wants this buffer to be rendered.
@@ -5990,8 +5991,7 @@
info->mIsReadFence = false;
}
} else {
- if (mCodec->mNativeWindow != NULL &&
- (buffer == NULL || buffer->size() != 0)) {
+ if (mCodec->mNativeWindow != NULL && (discarded || buffer->size() != 0)) {
// move read fence into write fence to avoid clobbering
info->mIsReadFence = false;
ATRACE_NAME("frame-drop");
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..a9536b9 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"
@@ -112,83 +111,6 @@
////////////////////////////////////////////////////////////////////////////////
-Mutex DataSource::gSnifferMutex;
-List<DataSource::SnifferFunc> DataSource::gSniffers;
-bool DataSource::gSniffersRegistered = false;
-
-bool DataSource::sniff(
- String8 *mimeType, float *confidence, sp<AMessage> *meta) {
- *mimeType = "";
- *confidence = 0.0f;
- meta->clear();
-
- {
- Mutex::Autolock autoLock(gSnifferMutex);
- if (!gSniffersRegistered) {
- return false;
- }
- }
-
- for (List<SnifferFunc>::iterator it = gSniffers.begin();
- it != gSniffers.end(); ++it) {
- String8 newMimeType;
- float newConfidence;
- sp<AMessage> newMeta;
- if ((*it)(this, &newMimeType, &newConfidence, &newMeta)) {
- if (newConfidence > *confidence) {
- *mimeType = newMimeType;
- *confidence = newConfidence;
- *meta = newMeta;
- }
- }
- }
-
- return *confidence > 0.0;
-}
-
-// static
-void DataSource::RegisterSniffer_l(SnifferFunc func) {
- for (List<SnifferFunc>::iterator it = gSniffers.begin();
- it != gSniffers.end(); ++it) {
- if (*it == func) {
- return;
- }
- }
-
- gSniffers.push_back(func);
-}
-
-// static
-void DataSource::RegisterDefaultSniffers() {
- Mutex::Autolock autoLock(gSnifferMutex);
- if (gSniffersRegistered) {
- return;
- }
-
- RegisterSniffer_l(SniffMPEG4);
- RegisterSniffer_l(SniffMatroska);
- RegisterSniffer_l(SniffOgg);
- RegisterSniffer_l(SniffWAV);
- RegisterSniffer_l(SniffFLAC);
- RegisterSniffer_l(SniffAMR);
- RegisterSniffer_l(SniffMPEG2TS);
- 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];
- if (property_get("drm.service.enabled", value, NULL)
- && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
- RegisterSniffer_l(SniffDRM);
- }
- gSniffersRegistered = true;
-}
-
// static
sp<DataSource> DataSource::CreateFromURI(
const sp<IMediaHTTPService> &httpService,
@@ -200,14 +122,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 +140,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 +156,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 230a22b..f29f786 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1046,16 +1046,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);
@@ -2342,12 +2332,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) {
@@ -2579,9 +2564,10 @@
if (info->mNotify != NULL) {
sp<AMessage> msg = info->mNotify;
- info->mNotify = NULL;
- msg->setObject("buffer", (portIndex == kPortIndexInput && mCrypto != NULL)
+ msg->setObject("buffer", (info->mSecureData != nullptr)
? info->mSecureData : info->mData);
+ msg->setInt32("discarded", true);
+ info->mNotify = NULL;
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..9362a07 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.
@@ -192,14 +185,14 @@
const sp<DataSource> &source, const char *mime) {
ALOGV("MediaExtractor::CreateFromService %s", mime);
- DataSource::RegisterDefaultSniffers();
+ RegisterDefaultSniffers();
sp<AMessage> meta;
String8 tmp;
if (mime == NULL) {
float confidence;
- if (!source->sniff(&tmp, &confidence, &meta)) {
+ if (!sniff(source, &tmp, &confidence, &meta)) {
ALOGV("FAILED to autodetect media content.");
return NULL;
@@ -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)) {
@@ -273,4 +263,79 @@
return ret;
}
+Mutex MediaExtractor::gSnifferMutex;
+List<MediaExtractor::SnifferFunc> MediaExtractor::gSniffers;
+bool MediaExtractor::gSniffersRegistered = false;
+
+// static
+bool MediaExtractor::sniff(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence, sp<AMessage> *meta) {
+ *mimeType = "";
+ *confidence = 0.0f;
+ meta->clear();
+
+ {
+ Mutex::Autolock autoLock(gSnifferMutex);
+ if (!gSniffersRegistered) {
+ return false;
+ }
+ }
+
+ for (List<SnifferFunc>::iterator it = gSniffers.begin();
+ it != gSniffers.end(); ++it) {
+ String8 newMimeType;
+ float newConfidence;
+ sp<AMessage> newMeta;
+ if ((*it)(source, &newMimeType, &newConfidence, &newMeta)) {
+ if (newConfidence > *confidence) {
+ *mimeType = newMimeType;
+ *confidence = newConfidence;
+ *meta = newMeta;
+ }
+ }
+ }
+
+ return *confidence > 0.0;
+}
+
+// static
+void MediaExtractor::RegisterSniffer_l(SnifferFunc func) {
+ for (List<SnifferFunc>::iterator it = gSniffers.begin();
+ it != gSniffers.end(); ++it) {
+ if (*it == func) {
+ return;
+ }
+ }
+
+ gSniffers.push_back(func);
+}
+
+// static
+void MediaExtractor::RegisterDefaultSniffers() {
+ Mutex::Autolock autoLock(gSnifferMutex);
+ if (gSniffersRegistered) {
+ return;
+ }
+
+ RegisterSniffer_l(SniffMPEG4);
+ RegisterSniffer_l(SniffMatroska);
+ RegisterSniffer_l(SniffOgg);
+ RegisterSniffer_l(SniffWAV);
+ RegisterSniffer_l(SniffFLAC);
+ RegisterSniffer_l(SniffAMR);
+ RegisterSniffer_l(SniffMPEG2TS);
+ RegisterSniffer_l(SniffMP3);
+ RegisterSniffer_l(SniffAAC);
+ RegisterSniffer_l(SniffMPEG2PS);
+ RegisterSniffer_l(SniffMidi);
+
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("drm.service.enabled", value, NULL)
+ && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
+ RegisterSniffer_l(SniffDRM);
+ }
+ gSniffersRegistered = true;
+}
+
+
} // namespace android
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/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index d8fec5c..5e00c44 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -55,8 +55,6 @@
: mParsedMetaData(false),
mAlbumArt(NULL) {
ALOGV("StagefrightMetadataRetriever()");
-
- DataSource::RegisterDefaultSniffers();
}
StagefrightMetadataRetriever::~StagefrightMetadataRetriever() {
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/id3/testid3.cpp b/media/libstagefright/id3/testid3.cpp
index b2f4188..442a3ff 100644
--- a/media/libstagefright/id3/testid3.cpp
+++ b/media/libstagefright/id3/testid3.cpp
@@ -154,8 +154,6 @@
int main(int argc, char **argv) {
android::ProcessState::self()->startThreadPool();
- DataSource::RegisterDefaultSniffers();
-
for (int i = 1; i < argc; ++i) {
scan(argv[i]);
}
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/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 935d7bf..1ce5d1a 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -800,7 +800,6 @@
using namespace android;
android::ProcessState::self()->startThreadPool();
- DataSource::RegisterDefaultSniffers();
const char *me = argv[0];
diff --git a/media/libstagefright/rtsp/rtp_test.cpp b/media/libstagefright/rtsp/rtp_test.cpp
index 24f529b..e612a8d 100644
--- a/media/libstagefright/rtsp/rtp_test.cpp
+++ b/media/libstagefright/rtsp/rtp_test.cpp
@@ -37,8 +37,6 @@
int main(int argc, char **argv) {
android::ProcessState::self()->startThreadPool();
- DataSource::RegisterDefaultSniffers();
-
const char *rtpFilename = NULL;
const char *rtcpFilename = NULL;
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
index 3587cb9..f1ecca0 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
@@ -36,7 +36,6 @@
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/AudioSource.h>
-#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MediaSource.h>
@@ -748,8 +747,6 @@
status_t WifiDisplaySource::PlaybackSession::setupMediaPacketizer(
bool enableAudio, bool enableVideo) {
- DataSource::RegisterDefaultSniffers();
-
mExtractor = new NuMediaExtractor;
status_t err = mExtractor->setDataSource(
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
index 582a5e8..945f4b3 100644
--- a/services/audioflinger/AudioMixer.cpp
+++ b/services/audioflinger/AudioMixer.cpp
@@ -1611,8 +1611,13 @@
// in == NULL can happen if the track was flushed just after having
// been enabled for mixing.
if (in == NULL || (((uintptr_t)in) & 3)) {
- memset(out, 0, numFrames
- * t.mMixerChannelCount * audio_bytes_per_sample(t.mMixerFormat));
+ if ( AUDIO_FORMAT_PCM_FLOAT == t.mMixerFormat ) {
+ memset((char*)fout, 0, numFrames
+ * t.mMixerChannelCount * audio_bytes_per_sample(t.mMixerFormat));
+ } else {
+ memset((char*)out, 0, numFrames
+ * t.mMixerChannelCount * audio_bytes_per_sample(t.mMixerFormat));
+ }
ALOGE_IF((((uintptr_t)in) & 3),
"process__OneTrack16BitsStereoNoResampling: misaligned buffer"
" %p track %d, channels %d, needs %08x, volume %08x vfl %f vfr %f",
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 3a04651..ec9ced2 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1287,36 +1287,54 @@
// particular client process: no risk to block the whole media server process or mixer
// threads if we are stuck here
Mutex::Autolock _l(mCblk->lock);
- if (mCblk->clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
- mCblk->serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
+
+ // keep local copy of index in case of client corruption b/32220769
+ const uint32_t clientIndex = mCblk->clientIndex;
+ const uint32_t serverIndex = mCblk->serverIndex;
+ if (clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
+ serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
mCblk->serverIndex = 0;
mCblk->clientIndex = 0;
return BAD_VALUE;
}
status_t status = NO_ERROR;
- while (mCblk->serverIndex < mCblk->clientIndex) {
- int reply;
- uint32_t rsize = sizeof(int);
- int *p = (int *)(mBuffer + mCblk->serverIndex);
- int size = *p++;
- if (((uint8_t *)p + size) > mBuffer + mCblk->clientIndex) {
+ effect_param_t *param = NULL;
+ for (uint32_t index = serverIndex; index < clientIndex;) {
+ int *p = (int *)(mBuffer + index);
+ const int size = *p++;
+ if (size < 0
+ || size > EFFECT_PARAM_BUFFER_SIZE
+ || ((uint8_t *)p + size) > mBuffer + clientIndex) {
ALOGW("command(): invalid parameter block size");
+ status = BAD_VALUE;
break;
}
- effect_param_t *param = (effect_param_t *)p;
- if (param->psize == 0 || param->vsize == 0) {
- ALOGW("command(): null parameter or value size");
- mCblk->serverIndex += size;
- continue;
+
+ // copy to local memory in case of client corruption b/32220769
+ param = (effect_param_t *)realloc(param, size);
+ if (param == NULL) {
+ ALOGW("command(): out of memory");
+ status = NO_MEMORY;
+ break;
}
- uint32_t psize = sizeof(effect_param_t) +
- ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
- param->vsize;
+ memcpy(param, p, size);
+
+ int reply = 0;
+ uint32_t rsize = sizeof(reply);
status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM,
- psize,
- p,
+ size,
+ param,
&rsize,
&reply);
+
+ // verify shared memory: server index shouldn't change; client index can't go back.
+ if (serverIndex != mCblk->serverIndex
+ || clientIndex > mCblk->clientIndex) {
+ android_errorWriteLog(0x534e4554, "32220769");
+ status = BAD_VALUE;
+ break;
+ }
+
// stop at first error encountered
if (ret != NO_ERROR) {
status = ret;
@@ -1326,8 +1344,9 @@
*(int *)pReplyData = reply;
break;
}
- mCblk->serverIndex += size;
+ index += size;
}
+ free(param);
mCblk->serverIndex = 0;
mCblk->clientIndex = 0;
return status;
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 818da72..a224004 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -384,6 +384,7 @@
sp<AudioPort> source = ctx->findPortByTagName(String8(devTag));
if (source == NULL) {
ALOGE("%s: no source found with name=%s", __FUNCTION__, devTag);
+ free(sourcesLiteral);
return BAD_VALUE;
}
sources.add(source);
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 5ef0216..a714041 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -4477,9 +4477,7 @@
bool AudioPolicyManager::streamsMatchForvolume(audio_stream_type_t stream1,
audio_stream_type_t stream2) {
- return ((stream1 == stream2) ||
- ((stream1 == AUDIO_STREAM_ACCESSIBILITY) && (stream2 == AUDIO_STREAM_MUSIC)) ||
- ((stream1 == AUDIO_STREAM_MUSIC) && (stream2 == AUDIO_STREAM_ACCESSIBILITY)));
+ return (stream1 == stream2);
}
uint32_t AudioPolicyManager::getStrategyForStream(audio_stream_type_t stream) {
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index bcd62d6..bfbf640 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -993,7 +993,7 @@
}
status_t Camera2Client::startRecordingL(Parameters ¶ms, bool restart) {
- status_t res;
+ status_t res = OK;
ALOGV("%s: state == %d, restart = %d", __FUNCTION__, params.state, restart);
diff --git a/services/radio/Android.mk b/services/radio/Android.mk
index b4cda19..4344506 100644
--- a/services/radio/Android.mk
+++ b/services/radio/Android.mk
@@ -17,9 +17,8 @@
include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= \
- RadioService.cpp \
- RadioHalLegacy.cpp
+LOCAL_SRC_FILES:= \
+ RadioService.cpp
LOCAL_SHARED_LIBRARIES:= \
liblog \
@@ -31,6 +30,26 @@
libradio \
libradio_metadata
+ifeq ($(ENABLE_TREBLE),true)
+# Treble configuration
+LOCAL_CFLAGS += -DENABLE_TREBLE
+LOCAL_SRC_FILES += \
+ HidlUtils.cpp \
+ RadioHalHidl.cpp
+
+LOCAL_SHARED_LIBRARIES += \
+ libhwbinder \
+ libhidlbase \
+ libhidltransport \
+ libbase \
+ android.hardware.broadcastradio@1.0
+else
+# libhardware configuration
+LOCAL_SRC_FILES += \
+ RadioHalLegacy.cpp
+endif
+
+
LOCAL_CFLAGS += -Wall -Wextra -Werror
LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
diff --git a/services/radio/HidlUtils.cpp b/services/radio/HidlUtils.cpp
new file mode 100644
index 0000000..bfced7a
--- /dev/null
+++ b/services/radio/HidlUtils.cpp
@@ -0,0 +1,179 @@
+/*
+ * 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.
+ */
+#define LOG_TAG "HidlUtils"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/misc.h>
+#include <system/radio_metadata.h>
+
+#include "HidlUtils.h"
+
+namespace android {
+
+using android::hardware::broadcastradio::V1_0::MetadataType;
+using android::hardware::broadcastradio::V1_0::Band;
+using android::hardware::broadcastradio::V1_0::Deemphasis;
+using android::hardware::broadcastradio::V1_0::Rds;
+
+//static
+int HidlUtils::convertHalResult(Result result)
+{
+ switch (result) {
+ case Result::OK:
+ return 0;
+ case Result::INVALID_ARGUMENTS:
+ return -EINVAL;
+ case Result::INVALID_STATE:
+ return -ENOSYS;
+ case Result::TIMEOUT:
+ return -ETIMEDOUT;
+ case Result::NOT_INITIALIZED:
+ default:
+ return -ENODEV;
+ }
+}
+
+
+//static
+void HidlUtils::convertBandConfigToHal(BandConfig *halConfig,
+ const radio_hal_band_config_t *config)
+{
+ halConfig->type = static_cast<Band>(config->type);
+ halConfig->antennaConnected = config->antenna_connected;
+ halConfig->lowerLimit = config->lower_limit;
+ halConfig->upperLimit = config->upper_limit;
+ halConfig->spacings.setToExternal(const_cast<unsigned int *>(&config->spacings[0]),
+ config->num_spacings * sizeof(uint32_t));
+ // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
+ halConfig->spacings.resize(config->num_spacings);
+
+ if (halConfig->type == Band::FM) {
+ halConfig->ext.fm.deemphasis = static_cast<Deemphasis>(config->fm.deemphasis);
+ halConfig->ext.fm.stereo = config->fm.stereo;
+ halConfig->ext.fm.rds = static_cast<Rds>(config->fm.rds);
+ halConfig->ext.fm.ta = config->fm.ta;
+ halConfig->ext.fm.af = config->fm.af;
+ halConfig->ext.fm.ea = config->fm.ea;
+ } else {
+ halConfig->ext.am.stereo = config->am.stereo;
+ }
+}
+
+//static
+void HidlUtils::convertPropertiesFromHal(radio_hal_properties_t *properties,
+ const Properties *halProperties)
+{
+ properties->class_id = static_cast<radio_class_t>(halProperties->classId);
+ strlcpy(properties->implementor, halProperties->implementor.c_str(), RADIO_STRING_LEN_MAX);
+ strlcpy(properties->product, halProperties->product.c_str(), RADIO_STRING_LEN_MAX);
+ strlcpy(properties->version, halProperties->version.c_str(), RADIO_STRING_LEN_MAX);
+ strlcpy(properties->serial, halProperties->serial.c_str(), RADIO_STRING_LEN_MAX);
+ properties->num_tuners = halProperties->numTuners;
+ properties->num_audio_sources = halProperties->numAudioSources;
+ properties->supports_capture = halProperties->supportsCapture;
+ properties->num_bands = halProperties->bands.size();
+
+ for (size_t i = 0; i < halProperties->bands.size(); i++) {
+ convertBandConfigFromHal(&properties->bands[i], &halProperties->bands[i]);
+ }
+}
+
+//static
+void HidlUtils::convertBandConfigFromHal(radio_hal_band_config_t *config,
+ const BandConfig *halConfig)
+{
+ config->type = static_cast<radio_band_t>(halConfig->type);
+ config->antenna_connected = halConfig->antennaConnected;
+ config->lower_limit = halConfig->lowerLimit;
+ config->upper_limit = halConfig->upperLimit;
+ config->num_spacings = halConfig->spacings.size();
+ if (config->num_spacings > RADIO_NUM_SPACINGS_MAX) {
+ config->num_spacings = RADIO_NUM_SPACINGS_MAX;
+ }
+ memcpy(config->spacings, halConfig->spacings.data(),
+ sizeof(uint32_t) * config->num_spacings);
+
+ if (halConfig->type == Band::FM) {
+ config->fm.deemphasis = static_cast<radio_deemphasis_t>(halConfig->ext.fm.deemphasis);
+ config->fm.stereo = halConfig->ext.fm.stereo;
+ config->fm.rds = static_cast<radio_rds_t>(halConfig->ext.fm.rds);
+ config->fm.ta = halConfig->ext.fm.ta;
+ config->fm.af = halConfig->ext.fm.af;
+ config->fm.ea = halConfig->ext.fm.ea;
+ } else {
+ config->am.stereo = halConfig->ext.am.stereo;
+ }
+}
+
+
+//static
+void HidlUtils::convertProgramInfoFromHal(radio_program_info_t *info,
+ const ProgramInfo *halInfo,
+ bool withMetadata)
+{
+ info->channel = halInfo->channel;
+ info->sub_channel = halInfo->subChannel;
+ info->tuned = halInfo->tuned;
+ info->stereo = halInfo->stereo;
+ info->digital = halInfo->digital;
+ info->signal_strength = halInfo->signalStrength;
+ if (withMetadata && halInfo->metadata.size() != 0) {
+ convertMetaDataFromHal(&info->metadata, halInfo->metadata,
+ halInfo->channel, halInfo->subChannel);
+ }
+}
+
+//static
+void HidlUtils::convertMetaDataFromHal(radio_metadata_t **metadata,
+ const hidl_vec<MetaData>& halMetadata,
+ uint32_t channel,
+ uint32_t subChannel)
+{
+
+ radio_metadata_allocate(metadata, channel, subChannel);
+ for (size_t i = 0; i < halMetadata.size(); i++) {
+ radio_metadata_key_t key = static_cast<radio_metadata_key_t>(halMetadata[i].key);
+ radio_metadata_type_t type = static_cast<radio_metadata_key_t>(halMetadata[i].type);
+ radio_metadata_clock_t clock;
+
+ switch (type) {
+ case RADIO_METADATA_TYPE_INT:
+ radio_metadata_add_int(metadata, key, halMetadata[i].intValue);
+ break;
+ case RADIO_METADATA_TYPE_TEXT:
+ radio_metadata_add_text(metadata, key, halMetadata[i].stringValue.c_str());
+ break;
+ case RADIO_METADATA_TYPE_RAW:
+ radio_metadata_add_raw(metadata, key,
+ halMetadata[i].rawValue.data(),
+ halMetadata[i].rawValue.size());
+ break;
+ case RADIO_METADATA_TYPE_CLOCK:
+ clock.utc_seconds_since_epoch =
+ halMetadata[i].clockValue.utcSecondsSinceEpoch;
+ clock.timezone_offset_in_minutes =
+ halMetadata[i].clockValue.timezoneOffsetInMinutes;
+ radio_metadata_add_clock(metadata, key, &clock);
+ break;
+ default:
+ ALOGW("%s invalid metadata type %u",__FUNCTION__, halMetadata[i].type);
+ break;
+ }
+ }
+}
+
+} // namespace android
diff --git a/services/radio/HidlUtils.h b/services/radio/HidlUtils.h
new file mode 100644
index 0000000..091abb7
--- /dev/null
+++ b/services/radio/HidlUtils.h
@@ -0,0 +1,51 @@
+/*
+ * 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 ANDROID_HARDWARE_RADIO_HAL_HIDL_UTILS_H
+#define ANDROID_HARDWARE_RADIO_HAL_HIDL_UTILS_H
+
+#include <android/hardware/broadcastradio/1.0/types.h>
+#include <hardware/radio.h>
+
+namespace android {
+
+using android::hardware::hidl_vec;
+using android::hardware::broadcastradio::V1_0::Result;
+using android::hardware::broadcastradio::V1_0::Properties;
+using android::hardware::broadcastradio::V1_0::BandConfig;
+using android::hardware::broadcastradio::V1_0::ProgramInfo;
+using android::hardware::broadcastradio::V1_0::MetaData;
+
+class HidlUtils {
+public:
+ static int convertHalResult(Result result);
+ static void convertBandConfigFromHal(radio_hal_band_config_t *config,
+ const BandConfig *halConfig);
+ static void convertPropertiesFromHal(radio_hal_properties_t *properties,
+ const Properties *halProperties);
+ static void convertBandConfigToHal(BandConfig *halConfig,
+ const radio_hal_band_config_t *config);
+ static void convertProgramInfoFromHal(radio_program_info_t *info,
+ const ProgramInfo *halInfo,
+ bool withMetadata);
+ static void convertMetaDataFromHal(radio_metadata_t **metadata,
+ const hidl_vec<MetaData>& halMetadata,
+ uint32_t channel,
+ uint32_t subChannel);
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_RADIO_HAL_HIDL_UTILS_H
diff --git a/services/radio/RadioHalHidl.cpp b/services/radio/RadioHalHidl.cpp
new file mode 100644
index 0000000..07cb4d5
--- /dev/null
+++ b/services/radio/RadioHalHidl.cpp
@@ -0,0 +1,388 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "RadioHalHidl"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/misc.h>
+#include <system/radio_metadata.h>
+#include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>
+
+#include "RadioHalHidl.h"
+#include "HidlUtils.h"
+
+namespace android {
+
+using android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory;
+using android::hardware::broadcastradio::V1_0::Class;
+using android::hardware::broadcastradio::V1_0::Direction;
+using android::hardware::broadcastradio::V1_0::Properties;
+
+
+/* static */
+sp<RadioInterface> RadioInterface::connectModule(radio_class_t classId)
+{
+ return new RadioHalHidl(classId);
+}
+
+int RadioHalHidl::getProperties(radio_hal_properties_t *properties)
+{
+ ALOGV("%s IN", __FUNCTION__);
+ sp<IBroadcastRadio> module = getService();
+ if (module == 0) {
+ return -ENODEV;
+ }
+ Properties halProperties;
+ Result halResult;
+ Return<void> hidlReturn =
+ module->getProperties([&](Result result, const Properties& properties) {
+ halResult = result;
+ if (result == Result::OK) {
+ halProperties = properties;
+ }
+ });
+
+ if (hidlReturn.getStatus().transactionError() == DEAD_OBJECT) {
+ clearService();
+ return -EPIPE;
+ }
+ if (halResult == Result::OK) {
+ HidlUtils::convertPropertiesFromHal(properties, &halProperties);
+ }
+ return HidlUtils::convertHalResult(halResult);
+}
+
+int RadioHalHidl::openTuner(const radio_hal_band_config_t *config,
+ bool audio,
+ sp<TunerCallbackInterface> callback,
+ sp<TunerInterface>& tuner)
+{
+ sp<IBroadcastRadio> module = getService();
+ if (module == 0) {
+ return -ENODEV;
+ }
+ sp<Tuner> tunerImpl = new Tuner(callback, this);
+
+ BandConfig halConfig;
+ Result halResult;
+ sp<ITuner> halTuner;
+
+ HidlUtils::convertBandConfigToHal(&halConfig, config);
+ Return<void> hidlReturn =
+ module->openTuner(halConfig, audio, tunerImpl,
+ [&](Result result, const sp<ITuner>& tuner) {
+ halResult = result;
+ if (result == Result::OK) {
+ halTuner = tuner;
+ }
+ });
+
+ if (hidlReturn.getStatus().transactionError() == DEAD_OBJECT) {
+ clearService();
+ return -EPIPE;
+ }
+ if (halResult == Result::OK) {
+ tunerImpl->setHalTuner(halTuner);
+ tuner = tunerImpl;
+ }
+
+ return HidlUtils::convertHalResult(halResult);
+}
+
+int RadioHalHidl::closeTuner(sp<TunerInterface>& tuner)
+{
+ sp<Tuner> tunerImpl = static_cast<Tuner *>(tuner.get());
+ sp<ITuner> clearTuner;
+ tunerImpl->setHalTuner(clearTuner);
+ return 0;
+}
+
+RadioHalHidl::RadioHalHidl(radio_class_t classId)
+ : mClassId(classId)
+{
+}
+
+RadioHalHidl::~RadioHalHidl()
+{
+}
+
+sp<IBroadcastRadio> RadioHalHidl::getService()
+{
+ if (mHalModule == 0) {
+ sp<IBroadcastRadioFactory> factory = IBroadcastRadioFactory::getService("broadcastradio");
+ if (factory != 0) {
+ factory->connectModule(static_cast<Class>(mClassId),
+ [&](Result retval, const ::android::sp<IBroadcastRadio>& result) {
+ if (retval == Result::OK) {
+ mHalModule = result;
+ }
+ });
+ }
+ }
+ ALOGV("%s OUT module %p", __FUNCTION__, mHalModule.get());
+ return mHalModule;
+}
+
+void RadioHalHidl::clearService()
+{
+ ALOGV("%s IN module %p", __FUNCTION__, mHalModule.get());
+ mHalModule.clear();
+}
+
+
+int RadioHalHidl::Tuner::setConfiguration(const radio_hal_band_config_t *config)
+{
+ ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
+
+ if (mHalTuner == 0) {
+ return -ENODEV;
+ }
+ BandConfig halConfig;
+ HidlUtils::convertBandConfigToHal(&halConfig, config);
+
+ Return<Result> hidlResult = mHalTuner->setConfiguration(halConfig);
+ checkHidlStatus(hidlResult.getStatus());
+ return HidlUtils::convertHalResult(hidlResult);
+}
+
+int RadioHalHidl::Tuner::getConfiguration(radio_hal_band_config_t *config)
+{
+ ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
+ if (mHalTuner == 0) {
+ return -ENODEV;
+ }
+ BandConfig halConfig;
+ Result halResult;
+ Return<void> hidlReturn =
+ mHalTuner->getConfiguration([&](Result result, const BandConfig& config) {
+ halResult = result;
+ if (result == Result::OK) {
+ halConfig = config;
+ }
+ });
+ status_t status = checkHidlStatus(hidlReturn.getStatus());
+ if (status == NO_ERROR && halResult == Result::OK) {
+ HidlUtils::convertBandConfigFromHal(config, &halConfig);
+ }
+ return HidlUtils::convertHalResult(halResult);
+}
+
+int RadioHalHidl::Tuner::scan(radio_direction_t direction, bool skip_sub_channel)
+{
+ ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
+ if (mHalTuner == 0) {
+ return -ENODEV;
+ }
+ Return<Result> hidlResult =
+ mHalTuner->scan(static_cast<Direction>(direction), skip_sub_channel);
+ checkHidlStatus(hidlResult.getStatus());
+ return HidlUtils::convertHalResult(hidlResult);
+}
+
+int RadioHalHidl::Tuner::step(radio_direction_t direction, bool skip_sub_channel)
+{
+ ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
+ if (mHalTuner == 0) {
+ return -ENODEV;
+ }
+ Return<Result> hidlResult =
+ mHalTuner->step(static_cast<Direction>(direction), skip_sub_channel);
+ checkHidlStatus(hidlResult.getStatus());
+ return HidlUtils::convertHalResult(hidlResult);
+}
+
+int RadioHalHidl::Tuner::tune(unsigned int channel, unsigned int sub_channel)
+{
+ ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
+ if (mHalTuner == 0) {
+ return -ENODEV;
+ }
+ Return<Result> hidlResult =
+ mHalTuner->tune(channel, sub_channel);
+ checkHidlStatus(hidlResult.getStatus());
+ return HidlUtils::convertHalResult(hidlResult);
+}
+
+int RadioHalHidl::Tuner::cancel()
+{
+ ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
+ if (mHalTuner == 0) {
+ return -ENODEV;
+ }
+ Return<Result> hidlResult = mHalTuner->cancel();
+ checkHidlStatus(hidlResult.getStatus());
+ return HidlUtils::convertHalResult(hidlResult);
+}
+
+int RadioHalHidl::Tuner::getProgramInformation(radio_program_info_t *info)
+{
+ ALOGV("%s IN mHalTuner %p", __FUNCTION__, mHalTuner.get());
+ if (mHalTuner == 0) {
+ return -ENODEV;
+ }
+ ProgramInfo halInfo;
+ Result halResult;
+ bool withMetaData = (info->metadata != NULL);
+ Return<void> hidlReturn = mHalTuner->getProgramInformation(
+ withMetaData, [&](Result result, const ProgramInfo& info) {
+ halResult = result;
+ if (result == Result::OK) {
+ halInfo = info;
+ }
+ });
+ status_t status = checkHidlStatus(hidlReturn.getStatus());
+ if (status == NO_ERROR && halResult == Result::OK) {
+ HidlUtils::convertProgramInfoFromHal(info, &halInfo, withMetaData);
+ }
+ return HidlUtils::convertHalResult(halResult);
+}
+
+Return<void> RadioHalHidl::Tuner::hardwareFailure()
+{
+ ALOGV("%s IN", __FUNCTION__);
+ handleHwFailure();
+ return Return<void>();
+}
+
+Return<void> RadioHalHidl::Tuner::configChange(Result result, const BandConfig& config)
+{
+ ALOGV("%s IN", __FUNCTION__);
+ radio_hal_event_t event;
+ memset(&event, 0, sizeof(radio_hal_event_t));
+ event.type = RADIO_EVENT_CONFIG;
+ event.status = HidlUtils::convertHalResult(result);
+ HidlUtils::convertBandConfigFromHal(&event.config, &config);
+ onCallback(&event);
+ return Return<void>();
+}
+
+Return<void> RadioHalHidl::Tuner::tuneComplete(Result result, const ProgramInfo& info)
+{
+ ALOGV("%s IN", __FUNCTION__);
+ radio_hal_event_t event;
+ memset(&event, 0, sizeof(radio_hal_event_t));
+ event.type = RADIO_EVENT_TUNED;
+ event.status = HidlUtils::convertHalResult(result);
+ HidlUtils::convertProgramInfoFromHal(&event.info, &info, true);
+ onCallback(&event);
+ if (event.info.metadata != NULL) {
+ radio_metadata_deallocate(event.info.metadata);
+ }
+ return Return<void>();
+}
+
+Return<void> RadioHalHidl::Tuner::afSwitch(const ProgramInfo& info)
+{
+ ALOGV("%s IN", __FUNCTION__);
+ radio_hal_event_t event;
+ memset(&event, 0, sizeof(radio_hal_event_t));
+ event.type = RADIO_EVENT_AF_SWITCH;
+ HidlUtils::convertProgramInfoFromHal(&event.info, &info, true);
+ onCallback(&event);
+ if (event.info.metadata != NULL) {
+ radio_metadata_deallocate(event.info.metadata);
+ }
+ return Return<void>();
+}
+
+Return<void> RadioHalHidl::Tuner::antennaStateChange(bool connected)
+{
+ ALOGV("%s IN", __FUNCTION__);
+ radio_hal_event_t event;
+ memset(&event, 0, sizeof(radio_hal_event_t));
+ event.type = RADIO_EVENT_ANTENNA;
+ event.on = connected;
+ onCallback(&event);
+ return Return<void>();
+}
+Return<void> RadioHalHidl::Tuner::trafficAnnouncement(bool active)
+{
+ ALOGV("%s IN", __FUNCTION__);
+ radio_hal_event_t event;
+ memset(&event, 0, sizeof(radio_hal_event_t));
+ event.type = RADIO_EVENT_TA;
+ event.on = active;
+ onCallback(&event);
+ return Return<void>();
+}
+Return<void> RadioHalHidl::Tuner::emergencyAnnouncement(bool active)
+{
+ ALOGV("%s IN", __FUNCTION__);
+ radio_hal_event_t event;
+ memset(&event, 0, sizeof(radio_hal_event_t));
+ event.type = RADIO_EVENT_EA;
+ event.on = active;
+ onCallback(&event);
+ return Return<void>();
+}
+Return<void> RadioHalHidl::Tuner::newMetadata(uint32_t channel, uint32_t subChannel,
+ const ::android::hardware::hidl_vec<MetaData>& metadata)
+{
+ ALOGV("%s IN", __FUNCTION__);
+ radio_hal_event_t event;
+ memset(&event, 0, sizeof(radio_hal_event_t));
+ event.type = RADIO_EVENT_METADATA;
+ HidlUtils::convertMetaDataFromHal(&event.metadata, metadata, channel, subChannel);
+ onCallback(&event);
+ if (event.metadata != NULL) {
+ radio_metadata_deallocate(event.info.metadata);
+ }
+ return Return<void>();
+}
+
+
+RadioHalHidl::Tuner::Tuner(sp<TunerCallbackInterface> callback, sp<RadioHalHidl> module)
+ : TunerInterface(), mHalTuner(NULL), mCallback(callback), mParentModule(module)
+{
+}
+
+
+RadioHalHidl::Tuner::~Tuner()
+{
+}
+
+void RadioHalHidl::Tuner::handleHwFailure()
+{
+ ALOGV("%s IN", __FUNCTION__);
+ sp<RadioHalHidl> parentModule = mParentModule.promote();
+ if (parentModule != 0) {
+ parentModule->clearService();
+ }
+ radio_hal_event_t event;
+ memset(&event, 0, sizeof(radio_hal_event_t));
+ event.type = RADIO_EVENT_HW_FAILURE;
+ onCallback(&event);
+ mHalTuner.clear();
+}
+
+status_t RadioHalHidl::Tuner::checkHidlStatus(Status hidlStatus)
+{
+ status_t status = hidlStatus.transactionError();
+ if (status == DEAD_OBJECT) {
+ handleHwFailure();
+ }
+ return status;
+}
+
+void RadioHalHidl::Tuner::onCallback(radio_hal_event_t *halEvent)
+{
+ if (mCallback != 0) {
+ mCallback->onEvent(halEvent);
+ }
+}
+
+} // namespace android
diff --git a/services/radio/RadioHalHidl.h b/services/radio/RadioHalHidl.h
new file mode 100644
index 0000000..5211ee2
--- /dev/null
+++ b/services/radio/RadioHalHidl.h
@@ -0,0 +1,108 @@
+/*
+ * 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 ANDROID_HARDWARE_RADIO_HAL_HIDL_H
+#define ANDROID_HARDWARE_RADIO_HAL_HIDL_H
+
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+#include "RadioInterface.h"
+#include "TunerInterface.h"
+#include "TunerCallbackInterface.h"
+#include <android/hardware/broadcastradio/1.0/types.h>
+#include <android/hardware/broadcastradio/1.0/IBroadcastRadio.h>
+#include <android/hardware/broadcastradio/1.0/ITuner.h>
+#include <android/hardware/broadcastradio/1.0/ITunerCallback.h>
+
+namespace android {
+
+using android::hardware::Status;
+using android::hardware::Return;
+using android::hardware::broadcastradio::V1_0::Result;
+using android::hardware::broadcastradio::V1_0::IBroadcastRadio;
+using android::hardware::broadcastradio::V1_0::ITuner;
+using android::hardware::broadcastradio::V1_0::ITunerCallback;
+
+using android::hardware::broadcastradio::V1_0::BandConfig;
+using android::hardware::broadcastradio::V1_0::ProgramInfo;
+using android::hardware::broadcastradio::V1_0::MetaData;
+
+class RadioHalHidl : public RadioInterface
+{
+public:
+ RadioHalHidl(radio_class_t classId);
+
+ // RadioInterface
+ virtual int getProperties(radio_hal_properties_t *properties);
+ virtual int openTuner(const radio_hal_band_config_t *config,
+ bool audio,
+ sp<TunerCallbackInterface> callback,
+ sp<TunerInterface>& tuner);
+ virtual int closeTuner(sp<TunerInterface>& tuner);
+
+ class Tuner : public TunerInterface, public virtual ITunerCallback
+ {
+ public:
+ Tuner(sp<TunerCallbackInterface> callback, sp<RadioHalHidl> module);
+
+ // TunerInterface
+ virtual int setConfiguration(const radio_hal_band_config_t *config);
+ virtual int getConfiguration(radio_hal_band_config_t *config);
+ virtual int scan(radio_direction_t direction, bool skip_sub_channel);
+ virtual int step(radio_direction_t direction, bool skip_sub_channel);
+ virtual int tune(unsigned int channel, unsigned int sub_channel);
+ virtual int cancel();
+ virtual int getProgramInformation(radio_program_info_t *info);
+
+ // ITunerCallback
+ virtual Return<void> hardwareFailure();
+ virtual Return<void> configChange(Result result, const BandConfig& config);
+ virtual Return<void> tuneComplete(Result result, const ProgramInfo& info);
+ virtual Return<void> afSwitch(const ProgramInfo& info);
+ virtual Return<void> antennaStateChange(bool connected);
+ virtual Return<void> trafficAnnouncement(bool active);
+ virtual Return<void> emergencyAnnouncement(bool active);
+ virtual Return<void> newMetadata(uint32_t channel, uint32_t subChannel,
+ const ::android::hardware::hidl_vec<MetaData>& metadata);
+
+ void setHalTuner(sp<ITuner>& halTuner) { mHalTuner = halTuner; }
+ sp<ITuner> getHalTuner() { return mHalTuner; }
+
+ private:
+ virtual ~Tuner();
+
+ void onCallback(radio_hal_event_t *halEvent);
+ void handleHwFailure();
+ status_t checkHidlStatus(Status hidlStatus);
+
+ sp<ITuner> mHalTuner;
+ sp<TunerCallbackInterface> mCallback;
+ wp<RadioHalHidl> mParentModule;
+ };
+
+ sp<IBroadcastRadio> getService();
+ void clearService();
+
+private:
+ virtual ~RadioHalHidl();
+
+ radio_class_t mClassId;
+ sp<IBroadcastRadio> mHalModule;
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_RADIO_HAL_HIDL_H