Merge "Fix potential NULL dereference in Visualizer effect" into klp-dev am: eee86b009e am: 6732f45ee9 am: 24566f2939 am: 25a681e678 am: 73895e0b02 am: c4605f157b am: 78188fec0f am: 24aff93b38 am: 7dc6f5d90b am: 54d76e28af am: eb5735a9f5 am: 121000246b am: da83e23c95 am: a051f466e7
am: fbed640187
Change-Id: I4e23b64d43748051751273c8631e021436beb8cc
diff --git a/camera/ndk/Android.mk b/camera/ndk/Android.mk
index 40dbeef..591dfc2 100644
--- a/camera/ndk/Android.mk
+++ b/camera/ndk/Android.mk
@@ -51,8 +51,6 @@
libcutils \
libcamera_metadata
-LOCAL_CLANG := true
-
include $(BUILD_SHARED_LIBRARY)
endif
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index 35555ff..1609da1 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -475,6 +475,7 @@
sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
if (cs == nullptr) {
ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
+ delete device;
return ACAMERA_ERROR_CAMERA_DISCONNECTED;
}
diff --git a/cmds/screenrecord/Overlay.cpp b/cmds/screenrecord/Overlay.cpp
index 9fd192c..be993e0 100644
--- a/cmds/screenrecord/Overlay.cpp
+++ b/cmds/screenrecord/Overlay.cpp
@@ -259,6 +259,11 @@
const char* format = "%T";
struct tm tm;
+ if (mUseMonotonicTimestamps) {
+ snprintf(buf, bufLen, "%" PRId64, monotonicNsec);
+ return;
+ }
+
// localtime/strftime is not the fastest way to do this, but a trivial
// benchmark suggests that the cost is negligible.
int64_t realTime = mStartRealtimeNsecs +
diff --git a/cmds/screenrecord/Overlay.h b/cmds/screenrecord/Overlay.h
index ee3444d..1d8a569 100644
--- a/cmds/screenrecord/Overlay.h
+++ b/cmds/screenrecord/Overlay.h
@@ -37,7 +37,7 @@
*/
class Overlay : public GLConsumer::FrameAvailableListener, Thread {
public:
- Overlay() : Thread(false),
+ Overlay(bool monotonicTimestamps) : Thread(false),
mThreadResult(UNKNOWN_ERROR),
mState(UNINITIALIZED),
mFrameAvailable(false),
@@ -45,7 +45,8 @@
mStartMonotonicNsecs(0),
mStartRealtimeNsecs(0),
mLastFrameNumber(-1),
- mTotalDroppedFrames(0)
+ mTotalDroppedFrames(0),
+ mUseMonotonicTimestamps(monotonicTimestamps)
{}
// Creates a thread that performs the overlay. Pass in the surface that
@@ -151,6 +152,8 @@
nsecs_t mLastFrameNumber;
size_t mTotalDroppedFrames;
+ bool mUseMonotonicTimestamps;
+
static const char* kPropertyNames[];
};
diff --git a/cmds/screenrecord/screenrecord.cpp b/cmds/screenrecord/screenrecord.cpp
index 59d5661..6097f01 100644
--- a/cmds/screenrecord/screenrecord.cpp
+++ b/cmds/screenrecord/screenrecord.cpp
@@ -51,6 +51,7 @@
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MediaMuxer.h>
#include <media/ICrypto.h>
+#include <media/MediaCodecBuffer.h>
#include "screenrecord.h"
#include "Overlay.h"
@@ -68,6 +69,7 @@
// Command-line parameters.
static bool gVerbose = false; // chatty on stdout
static bool gRotate = false; // rotate 90 degrees
+static bool gMonotonicTime = false; // use system monotonic time for timestamps
static enum {
FORMAT_MP4, FORMAT_H264, FORMAT_FRAMES, FORMAT_RAW_FRAMES
} gOutputFormat = FORMAT_MP4; // data format for output
@@ -327,7 +329,7 @@
assert((rawFp == NULL && muxer != NULL) || (rawFp != NULL && muxer == NULL));
- Vector<sp<ABuffer> > buffers;
+ Vector<sp<MediaCodecBuffer> > buffers;
err = encoder->getOutputBuffers(&buffers);
if (err != NO_ERROR) {
fprintf(stderr, "Unable to get output buffers (err=%d)\n", err);
@@ -410,7 +412,10 @@
// want to queue these up and do them on a different thread.
ATRACE_NAME("write sample");
assert(trackIdx != -1);
- err = muxer->writeSampleData(buffers[bufIndex], trackIdx,
+ // TODO
+ sp<ABuffer> buffer = new ABuffer(
+ buffers[bufIndex]->data(), buffers[bufIndex]->size());
+ err = muxer->writeSampleData(buffer, trackIdx,
ptsUsec, flags);
if (err != NO_ERROR) {
fprintf(stderr,
@@ -609,7 +614,7 @@
sp<Overlay> overlay;
if (gWantFrameTime) {
// Send virtual display frames to an external texture.
- overlay = new Overlay();
+ overlay = new Overlay(gMonotonicTime);
err = overlay->start(encoderInputSurface, &bufferProducer);
if (err != NO_ERROR) {
if (encoder != NULL) encoder->release();
@@ -892,6 +897,7 @@
{ "show-frame-time", no_argument, NULL, 'f' },
{ "rotate", no_argument, NULL, 'r' },
{ "output-format", required_argument, NULL, 'o' },
+ { "monotonic-time", no_argument, NULL, 'm' },
{ NULL, 0, NULL, 0 }
};
@@ -971,6 +977,9 @@
return 2;
}
break;
+ case 'm':
+ gMonotonicTime = true;
+ break;
default:
if (ic != '?') {
fprintf(stderr, "getopt_long returned unexpected value 0x%x\n", ic);
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 9e15a81..40726a3 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -18,7 +18,6 @@
external/jpeg \
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
-LOCAL_CLANG := true
LOCAL_MODULE_TAGS := optional
@@ -43,7 +42,6 @@
$(TOP)/frameworks/native/include/media/hardware
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
-LOCAL_CLANG := true
LOCAL_MODULE_TAGS := optional
@@ -68,7 +66,6 @@
$(TOP)/frameworks/native/include/media/hardware
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
-LOCAL_CLANG := true
LOCAL_MODULE_TAGS := optional
@@ -93,7 +90,6 @@
$(TOP)/frameworks/native/include/media/openmax
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
-LOCAL_CLANG := true
LOCAL_MODULE_TAGS := optional
@@ -117,7 +113,6 @@
$(TOP)/frameworks/native/include/media/openmax
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
-LOCAL_CLANG := true
LOCAL_MODULE_TAGS := optional
@@ -141,7 +136,6 @@
$(TOP)/frameworks/native/include/media/openmax
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
-LOCAL_CLANG := true
LOCAL_MODULE_TAGS := optional
@@ -166,7 +160,6 @@
$(TOP)/frameworks/native/include/media/openmax
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
-LOCAL_CLANG := true
LOCAL_MODULE_TAGS := optional
@@ -209,7 +202,6 @@
libstagefright_mediafilter
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
-LOCAL_CLANG := true
LOCAL_MODULE_TAGS := optional
@@ -233,7 +225,6 @@
$(TOP)/frameworks/native/include/media/openmax
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
-LOCAL_CLANG := true
LOCAL_MODULE_TAGS := optional
diff --git a/cmds/stagefright/SimplePlayer.cpp b/cmds/stagefright/SimplePlayer.cpp
index 50913cd..afb7db3 100644
--- a/cmds/stagefright/SimplePlayer.cpp
+++ b/cmds/stagefright/SimplePlayer.cpp
@@ -25,6 +25,7 @@
#include <media/AudioTrack.h>
#include <media/ICrypto.h>
#include <media/IMediaHTTPService.h>
+#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -355,7 +356,7 @@
err = state->mCodec->dequeueInputBuffer(&index, -1ll);
CHECK_EQ(err, (status_t)OK);
- const sp<ABuffer> &dstBuffer = state->mBuffers[0].itemAt(index);
+ const sp<MediaCodecBuffer> &dstBuffer = state->mBuffers[0].itemAt(index);
CHECK_LE(srcBuffer->size(), dstBuffer->capacity());
dstBuffer->setRange(0, srcBuffer->size());
@@ -482,11 +483,13 @@
state->mAvailInputBufferIndices.erase(
state->mAvailInputBufferIndices.begin());
- const sp<ABuffer> &dstBuffer =
+ const sp<MediaCodecBuffer> &dstBuffer =
state->mBuffers[0].itemAt(index);
+ sp<ABuffer> abuffer = new ABuffer(dstBuffer->base(), dstBuffer->capacity());
- err = mExtractor->readSampleData(dstBuffer);
+ err = mExtractor->readSampleData(abuffer);
CHECK_EQ(err, (status_t)OK);
+ dstBuffer->setRange(abuffer->offset(), abuffer->size());
int64_t timeUs;
CHECK_EQ(mExtractor->getSampleTime(&timeUs), (status_t)OK);
@@ -530,7 +533,7 @@
state->mCodec->releaseOutputBuffer(info->mIndex);
} else {
if (state->mAudioTrack != NULL) {
- const sp<ABuffer> &srcBuffer =
+ const sp<MediaCodecBuffer> &srcBuffer =
state->mBuffers[1].itemAt(info->mIndex);
renderAudio(state, info, srcBuffer);
@@ -597,7 +600,7 @@
}
void SimplePlayer::renderAudio(
- CodecState *state, BufferInfo *info, const sp<ABuffer> &buffer) {
+ CodecState *state, BufferInfo *info, const sp<MediaCodecBuffer> &buffer) {
CHECK(state->mAudioTrack != NULL);
if (state->mAudioTrack->stopped()) {
diff --git a/cmds/stagefright/SimplePlayer.h b/cmds/stagefright/SimplePlayer.h
index ae9dfd2..918fd24 100644
--- a/cmds/stagefright/SimplePlayer.h
+++ b/cmds/stagefright/SimplePlayer.h
@@ -25,6 +25,7 @@
struct AudioTrack;
class IGraphicBufferProducer;
struct MediaCodec;
+class MediaCodecBuffer;
struct NuMediaExtractor;
class Surface;
@@ -73,7 +74,7 @@
{
sp<MediaCodec> mCodec;
Vector<sp<ABuffer> > mCSD;
- Vector<sp<ABuffer> > mBuffers[2];
+ Vector<sp<MediaCodecBuffer> > mBuffers[2];
List<size_t> mAvailInputBufferIndices;
List<BufferInfo> mAvailOutputBufferInfos;
@@ -101,7 +102,7 @@
status_t onOutputFormatChanged(size_t trackIndex, CodecState *state);
void renderAudio(
- CodecState *state, BufferInfo *info, const sp<ABuffer> &buffer);
+ CodecState *state, BufferInfo *info, const sp<MediaCodecBuffer> &buffer);
DISALLOW_EVIL_CONSTRUCTORS(SimplePlayer);
};
diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp
index dae9bbe..26135d7 100644
--- a/cmds/stagefright/codec.cpp
+++ b/cmds/stagefright/codec.cpp
@@ -26,6 +26,7 @@
#include <media/ICrypto.h>
#include <media/IMediaHTTPService.h>
#include <media/IMediaPlayerService.h>
+#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>
@@ -56,8 +57,8 @@
struct CodecState {
sp<MediaCodec> mCodec;
- Vector<sp<ABuffer> > mInBuffers;
- Vector<sp<ABuffer> > mOutBuffers;
+ Vector<sp<MediaCodecBuffer> > mInBuffers;
+ Vector<sp<MediaCodecBuffer> > mOutBuffers;
bool mSignalledInputEOS;
bool mSawOutputEOS;
int64_t mNumBuffersDecoded;
@@ -174,10 +175,12 @@
if (err == OK) {
ALOGV("filling input buffer %zu", index);
- const sp<ABuffer> &buffer = state->mInBuffers.itemAt(index);
+ const sp<MediaCodecBuffer> &buffer = state->mInBuffers.itemAt(index);
+ sp<ABuffer> abuffer = new ABuffer(buffer->base(), buffer->capacity());
- err = extractor->readSampleData(buffer);
+ err = extractor->readSampleData(abuffer);
CHECK_EQ(err, (status_t)OK);
+ buffer->setRange(abuffer->offset(), abuffer->size());
int64_t timeUs;
err = extractor->getSampleTime(&timeUs);
diff --git a/cmds/stagefright/mediafilter.cpp b/cmds/stagefright/mediafilter.cpp
index d829df0..410dd69 100644
--- a/cmds/stagefright/mediafilter.cpp
+++ b/cmds/stagefright/mediafilter.cpp
@@ -26,6 +26,7 @@
#include <gui/Surface.h>
#include <media/ICrypto.h>
#include <media/IMediaHTTPService.h>
+#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -131,8 +132,8 @@
struct CodecState {
sp<MediaCodec> mCodec;
- Vector<sp<ABuffer> > mInBuffers;
- Vector<sp<ABuffer> > mOutBuffers;
+ Vector<sp<MediaCodecBuffer> > mInBuffers;
+ Vector<sp<MediaCodecBuffer> > mOutBuffers;
bool mSignalledInputEOS;
bool mSawOutputEOS;
int64_t mNumBuffersDecoded;
@@ -183,9 +184,9 @@
}
size_t outIndex = frame.index;
- const sp<ABuffer> &srcBuffer =
+ const sp<MediaCodecBuffer> &srcBuffer =
vidState->mOutBuffers.itemAt(outIndex);
- const sp<ABuffer> &destBuffer =
+ const sp<MediaCodecBuffer> &destBuffer =
filterState->mInBuffers.itemAt(filterIndex);
sp<AMessage> srcFormat, destFormat;
@@ -532,10 +533,12 @@
if (err == OK) {
ALOGV("filling input buffer %zu", index);
- const sp<ABuffer> &buffer = state->mInBuffers.itemAt(index);
+ const sp<MediaCodecBuffer> &buffer = state->mInBuffers.itemAt(index);
+ sp<ABuffer> abuffer = new ABuffer(buffer->base(), buffer->capacity());
- err = extractor->readSampleData(buffer);
+ err = extractor->readSampleData(abuffer);
CHECK(err == OK);
+ buffer->setRange(abuffer->offset(), abuffer->size());
int64_t timeUs;
err = extractor->getSampleTime(&timeUs);
diff --git a/drm/libmediadrm/Android.mk b/drm/libmediadrm/Android.mk
index f1c6b00..c822433 100644
--- a/drm/libmediadrm/Android.mk
+++ b/drm/libmediadrm/Android.mk
@@ -24,7 +24,6 @@
libutils
LOCAL_CFLAGS += -Werror -Wno-error=deprecated-declarations -Wall
-LOCAL_CLANG := true
LOCAL_MODULE:= libmediadrm
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 68a65f0..3e05532 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -28,8 +28,8 @@
}
class ICameraRecordingProxy;
class IMediaRecorderClient;
-class IGraphicBufferConsumer;
class IGraphicBufferProducer;
+struct PersistentSurface;
class IMediaRecorder: public IInterface
{
@@ -60,7 +60,7 @@
virtual status_t init() = 0;
virtual status_t close() = 0;
virtual status_t release() = 0;
- virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface) = 0;
+ virtual status_t setInputSurface(const sp<PersistentSurface>& surface) = 0;
virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() = 0;
};
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index 1c39b9c..311119b 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -19,8 +19,6 @@
#define ANDROID_IOMX_H_
#include <binder/IInterface.h>
-#include <gui/IGraphicBufferProducer.h>
-#include <gui/IGraphicBufferConsumer.h>
#include <ui/GraphicBuffer.h>
#include <utils/List.h>
#include <utils/String8.h>
@@ -34,23 +32,24 @@
namespace android {
+class IGraphicBufferProducer;
+class IGraphicBufferSource;
class IMemory;
+class IOMXBufferSource;
+class IOMXNode;
class IOMXObserver;
-class IOMXRenderer;
class NativeHandle;
-class Surface;
+struct omx_message;
class IOMX : public IInterface {
public:
DECLARE_META_INTERFACE(OMX);
typedef uint32_t buffer_id;
- typedef uint32_t node_id;
- // Given a node_id and the calling process' pid, returns true iff
- // the implementation of the OMX interface lives in the same
- // process.
- virtual bool livesLocally(node_id node, pid_t pid) = 0;
+ enum {
+ kFenceTimeoutMs = 1000
+ };
struct ComponentInfo {
String8 mName;
@@ -60,88 +59,74 @@
virtual status_t allocateNode(
const char *name, const sp<IOMXObserver> &observer,
- sp<IBinder> *nodeBinder,
- node_id *node) = 0;
+ sp<IOMXNode> *omxNode) = 0;
- virtual status_t freeNode(node_id node) = 0;
+ virtual status_t createInputSurface(
+ sp<IGraphicBufferProducer> *bufferProducer,
+ sp<IGraphicBufferSource> *bufferSource) = 0;
+};
+
+class IOMXNode : public IInterface {
+public:
+ DECLARE_META_INTERFACE(OMXNode);
+
+ typedef IOMX::buffer_id buffer_id;
+
+ virtual status_t freeNode() = 0;
virtual status_t sendCommand(
- node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) = 0;
+ OMX_COMMANDTYPE cmd, OMX_S32 param) = 0;
virtual status_t getParameter(
- node_id node, OMX_INDEXTYPE index,
- void *params, size_t size) = 0;
+ OMX_INDEXTYPE index, void *params, size_t size) = 0;
virtual status_t setParameter(
- node_id node, OMX_INDEXTYPE index,
- const void *params, size_t size) = 0;
+ OMX_INDEXTYPE index, const void *params, size_t size) = 0;
virtual status_t getConfig(
- node_id node, OMX_INDEXTYPE index,
- void *params, size_t size) = 0;
+ OMX_INDEXTYPE index, void *params, size_t size) = 0;
virtual status_t setConfig(
- node_id node, OMX_INDEXTYPE index,
- const void *params, size_t size) = 0;
-
- virtual status_t getState(
- node_id node, OMX_STATETYPE* state) = 0;
+ OMX_INDEXTYPE index, const void *params, size_t size) = 0;
// This will set *type to previous metadata buffer type on OMX error (not on binder error), and
// new metadata buffer type on success.
virtual status_t storeMetaDataInBuffers(
- node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type = NULL) = 0;
+ OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type = NULL) = 0;
virtual status_t prepareForAdaptivePlayback(
- node_id node, OMX_U32 portIndex, OMX_BOOL enable,
+ OMX_U32 portIndex, OMX_BOOL enable,
OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) = 0;
virtual status_t configureVideoTunnelMode(
- node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
+ OMX_U32 portIndex, OMX_BOOL tunneled,
OMX_U32 audioHwSync, native_handle_t **sidebandHandle) = 0;
virtual status_t enableNativeBuffers(
- node_id node, OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable) = 0;
+ OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable) = 0;
virtual status_t getGraphicBufferUsage(
- node_id node, OMX_U32 port_index, OMX_U32* usage) = 0;
+ OMX_U32 port_index, OMX_U32* usage) = 0;
// Use |params| as an OMX buffer, but limit the size of the OMX buffer to |allottedSize|.
virtual status_t useBuffer(
- node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
+ OMX_U32 port_index, const sp<IMemory> ¶ms,
buffer_id *buffer, OMX_U32 allottedSize) = 0;
virtual status_t useGraphicBuffer(
- node_id node, OMX_U32 port_index,
+ OMX_U32 port_index,
const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) = 0;
virtual status_t updateGraphicBufferInMeta(
- node_id node, OMX_U32 port_index,
+ OMX_U32 port_index,
const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) = 0;
virtual status_t updateNativeHandleInMeta(
- node_id node, OMX_U32 port_index,
+ OMX_U32 port_index,
const sp<NativeHandle> &nativeHandle, buffer_id buffer) = 0;
- // This will set *type to resulting metadata buffer type on OMX error (not on binder error) as
- // well as on success.
- virtual status_t createInputSurface(
- node_id node, OMX_U32 port_index, android_dataspace dataSpace,
- sp<IGraphicBufferProducer> *bufferProducer,
- MetadataBufferType *type = NULL) = 0;
-
- virtual status_t createPersistentInputSurface(
- sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferConsumer> *bufferConsumer) = 0;
-
- // This will set *type to resulting metadata buffer type on OMX error (not on binder error) as
- // well as on success.
virtual status_t setInputSurface(
- node_id node, OMX_U32 port_index,
- const sp<IGraphicBufferConsumer> &bufferConsumer,
- MetadataBufferType *type) = 0;
-
- virtual status_t signalEndOfInputStream(node_id node) = 0;
+ const sp<IOMXBufferSource> &bufferSource) = 0;
// Allocate an opaque buffer as a native handle. If component supports returning native
// handles, those are returned in *native_handle. Otherwise, the allocated buffer is
@@ -149,57 +134,45 @@
// same process as the callee, i.e. is the media_server, as the returned "buffer_data"
// pointer is just that, a pointer into local address space.
virtual status_t allocateSecureBuffer(
- node_id node, OMX_U32 port_index, size_t size,
- buffer_id *buffer, void **buffer_data, sp<NativeHandle> *native_handle) = 0;
-
- // Allocate an OMX buffer of size |allotedSize|. Use |params| as the backup buffer, which
- // may be larger.
- virtual status_t allocateBufferWithBackup(
- node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
- buffer_id *buffer, OMX_U32 allottedSize) = 0;
+ OMX_U32 port_index, size_t size, buffer_id *buffer,
+ void **buffer_data, sp<NativeHandle> *native_handle) = 0;
virtual status_t freeBuffer(
- node_id node, OMX_U32 port_index, buffer_id buffer) = 0;
+ OMX_U32 port_index, buffer_id buffer) = 0;
- enum {
- kFenceTimeoutMs = 1000
- };
// Calls OMX_FillBuffer on buffer, and passes |fenceFd| to component if it supports
// fences. Otherwise, it waits on |fenceFd| before calling OMX_FillBuffer.
// Takes ownership of |fenceFd| even if this call fails.
- virtual status_t fillBuffer(node_id node, buffer_id buffer, int fenceFd = -1) = 0;
+ virtual status_t fillBuffer(buffer_id buffer, int fenceFd = -1) = 0;
// Calls OMX_EmptyBuffer on buffer (after updating buffer header with |range_offset|,
// |range_length|, |flags| and |timestamp|). Passes |fenceFd| to component if it
// supports fences. Otherwise, it waits on |fenceFd| before calling OMX_EmptyBuffer.
// Takes ownership of |fenceFd| even if this call fails.
virtual status_t emptyBuffer(
- node_id node,
buffer_id buffer,
OMX_U32 range_offset, OMX_U32 range_length,
OMX_U32 flags, OMX_TICKS timestamp, int fenceFd = -1) = 0;
+ // Calls OMX_EmptyBuffer on buffer (after updating buffer header with metadata of
+ // |graphicBuffer|, |flags| and |timestamp|). Passes |fenceFd| to component if it
+ // supports fences. Otherwise, it waits on |fenceFd| before calling OMX_EmptyBuffer.
+ // Takes ownership of |fenceFd| even if this call fails. If |origTimestamp| >= 0,
+ // timestamp on the filled buffer corresponding to this frame will be modified to
+ // |origTimestamp| after it's filled.
+ virtual status_t emptyGraphicBuffer(
+ buffer_id buffer,
+ const sp<GraphicBuffer> &graphicBuffer, OMX_U32 flags,
+ OMX_TICKS timestamp, OMX_TICKS origTimestamp, int fenceFd) = 0;
+
virtual status_t getExtensionIndex(
- node_id node,
const char *parameter_name,
OMX_INDEXTYPE *index) = 0;
- enum InternalOptionType {
- INTERNAL_OPTION_SUSPEND, // data is a bool
- INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY, // data is an int64_t
- INTERNAL_OPTION_MAX_TIMESTAMP_GAP, // data is int64_t
- INTERNAL_OPTION_MAX_FPS, // data is float
- INTERNAL_OPTION_START_TIME, // data is an int64_t
- INTERNAL_OPTION_TIME_LAPSE, // data is an int64_t[2]
- INTERNAL_OPTION_COLOR_ASPECTS, // data is ColorAspects
- INTERNAL_OPTION_TIME_OFFSET, // data is an int64_t
- };
- virtual status_t setInternalOption(
- node_id node,
- OMX_U32 port_index,
- InternalOptionType type,
- const void *data,
- size_t size) = 0;
+ virtual status_t dispatchMessage(const omx_message &msg) = 0;
+
+ // TODO: this is temporary, will be removed when quirks move to OMX side
+ virtual status_t setQuirks(OMX_U32 quirks) = 0;
};
struct omx_message {
@@ -210,7 +183,6 @@
FRAME_RENDERED,
} type;
- IOMX::node_id node;
int fenceFd; // used for EMPTY_BUFFER_DONE and FILL_BUFFER_DONE; client must close this
union {
@@ -219,6 +191,8 @@
OMX_EVENTTYPE event;
OMX_U32 data1;
OMX_U32 data2;
+ OMX_U32 data3;
+ OMX_U32 data4;
} event_data;
// if type == EMPTY_BUFFER_DONE
@@ -258,10 +232,17 @@
virtual status_t onTransact(
uint32_t code, const Parcel &data, Parcel *reply,
uint32_t flags = 0);
+};
+
+class BnOMXNode : public BnInterface<IOMXNode> {
+public:
+ virtual status_t onTransact(
+ uint32_t code, const Parcel &data, Parcel *reply,
+ uint32_t flags = 0);
protected:
// check if the codec is secure.
- virtual bool isSecure(IOMX::node_id node) {
+ virtual bool isSecure() const {
return false;
}
};
diff --git a/include/media/MediaCodecBuffer.h b/include/media/MediaCodecBuffer.h
new file mode 100644
index 0000000..2df81dd
--- /dev/null
+++ b/include/media/MediaCodecBuffer.h
@@ -0,0 +1,72 @@
+/*
+ * 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 MEDIA_CODEC_BUFFER_H_
+
+#define MEDIA_CODEC_BUFFER_H_
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+struct ABuffer;
+struct AMessage;
+class MediaBufferBase;
+
+/**
+ * Buffers used by MediaCodec.
+ */
+class MediaCodecBuffer : public RefBase {
+public:
+ MediaCodecBuffer(const sp<AMessage> &format, const sp<ABuffer> &buffer);
+
+ /**
+ * MediaCodec will release all references to the buffer when it's done using
+ * it, so the destructor should return the buffer to the owner, such as OMX
+ * components, buffer allocators, surfaces, etc.
+ */
+ virtual ~MediaCodecBuffer() = default;
+
+ // ABuffer-like interface
+ uint8_t *base();
+ uint8_t *data();
+ size_t capacity() const;
+ size_t size() const;
+ size_t offset() const;
+ // Default implementation calls ABuffer::setRange() and returns OK.
+ virtual status_t setRange(size_t offset, size_t size);
+ // TODO: These can be removed if we finish replacing all MediaBuffer's.
+ MediaBufferBase *getMediaBufferBase();
+ void setMediaBufferBase(MediaBufferBase *mediaBuffer);
+
+ // TODO: Specify each field for meta/format.
+ sp<AMessage> meta();
+ sp<AMessage> format();
+
+private:
+ MediaCodecBuffer() = delete;
+
+ const sp<AMessage> mMeta;
+ const sp<AMessage> mFormat;
+ const sp<ABuffer> mBuffer;
+ MediaBufferBase *mMediaBufferBase;
+};
+
+} // namespace android
+
+#endif // MEDIA_CODEC_BUFFER_H_
diff --git a/include/media/MediaDefs.h b/include/media/MediaDefs.h
new file mode 100644
index 0000000..5f2a32d
--- /dev/null
+++ b/include/media/MediaDefs.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2009 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 MEDIA_DEFS_H_
+
+#define MEDIA_DEFS_H_
+
+namespace android {
+
+extern const char *MEDIA_MIMETYPE_IMAGE_JPEG;
+
+extern const char *MEDIA_MIMETYPE_VIDEO_VP8;
+extern const char *MEDIA_MIMETYPE_VIDEO_VP9;
+extern const char *MEDIA_MIMETYPE_VIDEO_AVC;
+extern const char *MEDIA_MIMETYPE_VIDEO_HEVC;
+extern const char *MEDIA_MIMETYPE_VIDEO_MPEG4;
+extern const char *MEDIA_MIMETYPE_VIDEO_H263;
+extern const char *MEDIA_MIMETYPE_VIDEO_MPEG2;
+extern const char *MEDIA_MIMETYPE_VIDEO_RAW;
+extern const char *MEDIA_MIMETYPE_VIDEO_DOLBY_VISION;
+
+extern const char *MEDIA_MIMETYPE_AUDIO_AMR_NB;
+extern const char *MEDIA_MIMETYPE_AUDIO_AMR_WB;
+extern const char *MEDIA_MIMETYPE_AUDIO_MPEG; // layer III
+extern const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I;
+extern const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II;
+extern const char *MEDIA_MIMETYPE_AUDIO_MIDI;
+extern const char *MEDIA_MIMETYPE_AUDIO_AAC;
+extern const char *MEDIA_MIMETYPE_AUDIO_QCELP;
+extern const char *MEDIA_MIMETYPE_AUDIO_VORBIS;
+extern const char *MEDIA_MIMETYPE_AUDIO_OPUS;
+extern const char *MEDIA_MIMETYPE_AUDIO_G711_ALAW;
+extern const char *MEDIA_MIMETYPE_AUDIO_G711_MLAW;
+extern const char *MEDIA_MIMETYPE_AUDIO_RAW;
+extern const char *MEDIA_MIMETYPE_AUDIO_FLAC;
+extern const char *MEDIA_MIMETYPE_AUDIO_AAC_ADTS;
+extern const char *MEDIA_MIMETYPE_AUDIO_MSGSM;
+extern const char *MEDIA_MIMETYPE_AUDIO_AC3;
+extern const char *MEDIA_MIMETYPE_AUDIO_EAC3;
+
+extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG4;
+extern const char *MEDIA_MIMETYPE_CONTAINER_WAV;
+extern const char *MEDIA_MIMETYPE_CONTAINER_OGG;
+extern const char *MEDIA_MIMETYPE_CONTAINER_MATROSKA;
+extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG2TS;
+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;
+extern const char *MEDIA_MIMETYPE_TEXT_CEA_608;
+extern const char *MEDIA_MIMETYPE_TEXT_CEA_708;
+extern const char *MEDIA_MIMETYPE_DATA_TIMED_ID3;
+
+// These are values exported to JAVA API that need to be in sync with
+// frameworks/base/media/java/android/media/AudioFormat.java. Unfortunately,
+// they are not defined in frameworks/av, so defining them here.
+enum AudioEncoding {
+ kAudioEncodingPcm16bit = 2,
+ kAudioEncodingPcm8bit = 3,
+ kAudioEncodingPcmFloat = 4,
+};
+
+} // namespace android
+
+#endif // MEDIA_DEFS_H_
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index 5195993..59dfd18 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -25,9 +25,8 @@
namespace android {
class ICameraRecordingProxy;
-class Surface;
-class IGraphicBufferConsumer;
class IGraphicBufferProducer;
+struct PersistentSurface;
struct MediaRecorderBase {
MediaRecorderBase(const String16 &opPackageName)
@@ -59,7 +58,7 @@
virtual status_t reset() = 0;
virtual status_t getMaxAmplitude(int *max) = 0;
virtual status_t dump(int fd, const Vector<String16>& args) const = 0;
- virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface) = 0;
+ virtual status_t setInputSurface(const sp<PersistentSurface>& surface) = 0;
virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() const = 0;
diff --git a/include/media/MidiDeviceInfo.h b/include/media/MidiDeviceInfo.h
new file mode 100644
index 0000000..5b4a241
--- /dev/null
+++ b/include/media/MidiDeviceInfo.h
@@ -0,0 +1,81 @@
+/*
+ * 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_MEDIA_MIDI_DEVICE_INFO_H
+#define ANDROID_MEDIA_MIDI_DEVICE_INFO_H
+
+#include <binder/Parcelable.h>
+#include <binder/PersistableBundle.h>
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
+namespace android {
+namespace media {
+namespace midi {
+
+class MidiDeviceInfo : public Parcelable {
+public:
+ MidiDeviceInfo() = default;
+ virtual ~MidiDeviceInfo() = default;
+ MidiDeviceInfo(const MidiDeviceInfo& midiDeviceInfo) = default;
+
+ status_t writeToParcel(Parcel* parcel) const override;
+ status_t readFromParcel(const Parcel* parcel) override;
+
+ int getType() const { return mType; }
+ int getUid() const { return mId; }
+ bool isPrivate() const { return mIsPrivate; }
+ const Vector<String16>& getInputPortNames() const { return mInputPortNames; }
+ const Vector<String16>& getOutputPortNames() const { return mOutputPortNames; }
+ String16 getProperty(const char* propertyName);
+
+ // The constants need to be kept in sync with MidiDeviceInfo.java
+ enum {
+ TYPE_USB = 1,
+ TYPE_VIRTUAL = 2,
+ TYPE_BLUETOOTH = 3,
+ };
+ static const char* const PROPERTY_NAME;
+ static const char* const PROPERTY_MANUFACTURER;
+ static const char* const PROPERTY_PRODUCT;
+ static const char* const PROPERTY_VERSION;
+ static const char* const PROPERTY_SERIAL_NUMBER;
+ static const char* const PROPERTY_ALSA_CARD;
+ static const char* const PROPERTY_ALSA_DEVICE;
+
+ friend bool operator==(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs);
+ friend bool operator!=(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs) {
+ return !(lhs == rhs);
+ }
+
+private:
+ status_t readStringVector(
+ const Parcel* parcel, Vector<String16> *vectorPtr, size_t defaultLength);
+ status_t writeStringVector(Parcel* parcel, const Vector<String16>& vector) const;
+
+ int32_t mType;
+ int32_t mId;
+ Vector<String16> mInputPortNames;
+ Vector<String16> mOutputPortNames;
+ os::PersistableBundle mProperties;
+ bool mIsPrivate;
+};
+
+} // namespace midi
+} // namespace media
+} // namespace android
+
+#endif // ANDROID_MEDIA_MIDI_DEVICE_INFO_H
diff --git a/include/media/OMXFenceParcelable.h b/include/media/OMXFenceParcelable.h
new file mode 100644
index 0000000..c9da301
--- /dev/null
+++ b/include/media/OMXFenceParcelable.h
@@ -0,0 +1,64 @@
+/*
+ * 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 _OMX_FENCE_PARCELABLE_
+#define _OMX_FENCE_PARCELABLE_
+
+#include <binder/Parcel.h>
+
+namespace android {
+
+struct OMXFenceParcelable : public Parcelable {
+ OMXFenceParcelable() : mFenceFd(-1) {}
+ OMXFenceParcelable(int fenceFd) : mFenceFd(fenceFd) {}
+
+ int get() const { return mFenceFd; }
+
+ status_t readFromParcel(const Parcel* parcel) override;
+ status_t writeToParcel(Parcel* parcel) const override;
+
+private:
+ // Disable copy ctor and operator=
+ OMXFenceParcelable(const OMXFenceParcelable &);
+ OMXFenceParcelable &operator=(const OMXFenceParcelable &);
+
+ int mFenceFd;
+};
+
+inline status_t OMXFenceParcelable::readFromParcel(const Parcel* parcel) {
+ int32_t haveFence;
+ status_t err = parcel->readInt32(&haveFence);
+ if (err == OK && haveFence) {
+ int fd = ::dup(parcel->readFileDescriptor());
+ if (fd < 0) {
+ return fd;
+ }
+ mFenceFd = fd;
+ }
+ return err;
+}
+
+inline status_t OMXFenceParcelable::writeToParcel(Parcel* parcel) const {
+ status_t err = parcel->writeInt32(mFenceFd >= 0);
+ if (err == OK && mFenceFd >= 0) {
+ err = parcel->writeFileDescriptor(mFenceFd, true /* takeOwnership */);
+ }
+ return err;
+}
+
+} // namespace android
+
+#endif // _OMX_FENCE_PARCELABLE_
diff --git a/include/media/audiohal/DeviceHalInterface.h b/include/media/audiohal/DeviceHalInterface.h
new file mode 100644
index 0000000..2f7ed3a
--- /dev/null
+++ b/include/media/audiohal/DeviceHalInterface.h
@@ -0,0 +1,120 @@
+/*
+ * 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_DEVICE_HAL_INTERFACE_H
+#define ANDROID_HARDWARE_DEVICE_HAL_INTERFACE_H
+
+#include <system/audio.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+
+namespace android {
+
+class StreamInHalInterface;
+class StreamOutHalInterface;
+
+class DeviceHalInterface : public RefBase
+{
+ public:
+ // Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
+ virtual status_t getSupportedDevices(uint32_t *devices) = 0;
+
+ // Get the hardware module version.
+ virtual status_t getVersion(uint32_t *version) = 0;
+
+ // Check to see if the audio hardware interface has been initialized.
+ virtual status_t initCheck() = 0;
+
+ // Set the audio volume of a voice call. Range is between 0.0 and 1.0.
+ virtual status_t setVoiceVolume(float volume) = 0;
+
+ // Set the audio volume for all audio activities other than voice call.
+ virtual status_t setMasterVolume(float volume) = 0;
+
+ // Get the current master volume value for the HAL.
+ virtual status_t getMasterVolume(float *volume) = 0;
+
+ // Called when the audio mode changes.
+ virtual status_t setMode(audio_mode_t mode) = 0;
+
+ // Muting control.
+ virtual status_t setMicMute(bool state) = 0;
+ virtual status_t getMicMute(bool *state) = 0;
+ virtual status_t setMasterMute(bool state) = 0;
+ virtual status_t getMasterMute(bool *state) = 0;
+
+ // Set global audio parameters.
+ virtual status_t setParameters(const String8& kvPairs) = 0;
+
+ // Get global audio parameters.
+ virtual status_t getParameters(const String8& keys, String8 *values) = 0;
+
+ // Returns audio input buffer size according to parameters passed.
+ virtual status_t getInputBufferSize(const struct audio_config *config,
+ size_t *size) = 0;
+
+ // Creates and opens the audio hardware output stream. The stream is closed
+ // by releasing all references to the returned object.
+ virtual status_t openOutputStream(
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ audio_output_flags_t flags,
+ struct audio_config *config,
+ const char *address,
+ sp<StreamOutHalInterface> *outStream) = 0;
+
+ // Creates and opens the audio hardware input stream. The stream is closed
+ // by releasing all references to the returned object.
+ virtual status_t openInputStream(
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ struct audio_config *config,
+ audio_input_flags_t flags,
+ const char *address,
+ audio_source_t source,
+ sp<StreamInHalInterface> *inStream) = 0;
+
+ // Creates an audio patch between several source and sink ports.
+ virtual status_t createAudioPatch(
+ unsigned int num_sources,
+ const struct audio_port_config *sources,
+ unsigned int num_sinks,
+ const struct audio_port_config *sinks,
+ audio_patch_handle_t *patch) = 0;
+
+ // Releases an audio patch.
+ virtual status_t releaseAudioPatch(audio_patch_handle_t patch) = 0;
+
+ // Fills the list of supported attributes for a given audio port.
+ virtual status_t getAudioPort(struct audio_port *port) = 0;
+
+ // Set audio port configuration.
+ virtual status_t setAudioPortConfig(const struct audio_port_config *config) = 0;
+
+ virtual status_t dump(int fd) = 0;
+
+ protected:
+ // Subclasses can not be constructed directly by clients.
+ DeviceHalInterface() {}
+
+ // The destructor automatically closes the device.
+ virtual ~DeviceHalInterface() {}
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_DEVICE_HAL_INTERFACE_H
diff --git a/include/media/audiohal/DevicesFactoryHalInterface.h b/include/media/audiohal/DevicesFactoryHalInterface.h
new file mode 100644
index 0000000..823a0da
--- /dev/null
+++ b/include/media/audiohal/DevicesFactoryHalInterface.h
@@ -0,0 +1,44 @@
+/*
+ * 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_DEVICES_FACTORY_HAL_INTERFACE_H
+#define ANDROID_HARDWARE_DEVICES_FACTORY_HAL_INTERFACE_H
+
+#include <media/audiohal/DeviceHalInterface.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class DevicesFactoryHalInterface : public RefBase
+{
+ public:
+ virtual ~DevicesFactoryHalInterface() {}
+
+ // Opens a device with the specified name. To close the device, it is
+ // necessary to release references to the returned object.
+ virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device) = 0;
+
+ static sp<DevicesFactoryHalInterface> create();
+
+ protected:
+ // Subclasses can not be constructed directly by clients.
+ DevicesFactoryHalInterface() {}
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_DEVICES_FACTORY_HAL_INTERFACE_H
diff --git a/include/media/audiohal/EffectHalInterface.h b/include/media/audiohal/EffectHalInterface.h
new file mode 100644
index 0000000..4bde112
--- /dev/null
+++ b/include/media/audiohal/EffectHalInterface.h
@@ -0,0 +1,55 @@
+/*
+ * 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_EFFECT_HAL_INTERFACE_H
+#define ANDROID_HARDWARE_EFFECT_HAL_INTERFACE_H
+
+#include <hardware/audio_effect.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class EffectHalInterface : public RefBase
+{
+ public:
+ // Effect process function. Takes input samples as specified
+ // in input buffer descriptor and output processed samples as specified
+ // in output buffer descriptor.
+ virtual status_t process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) = 0;
+
+ // Process reverse stream function. This function is used to pass
+ // a reference stream to the effect engine.
+ virtual status_t processReverse(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) = 0;
+
+ // Send a command and receive a response to/from effect engine.
+ virtual status_t command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
+ uint32_t *replySize, void *pReplyData) = 0;
+
+ // Returns the effect descriptor.
+ virtual status_t getDescriptor(effect_descriptor_t *pDescriptor) = 0;
+
+ protected:
+ // Subclasses can not be constructed directly by clients.
+ EffectHalInterface() {}
+
+ // The destructor automatically releases the effect.
+ virtual ~EffectHalInterface() {}
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_EFFECT_HAL_INTERFACE_H
diff --git a/include/media/audiohal/EffectsFactoryHalInterface.h b/include/media/audiohal/EffectsFactoryHalInterface.h
new file mode 100644
index 0000000..1588dab
--- /dev/null
+++ b/include/media/audiohal/EffectsFactoryHalInterface.h
@@ -0,0 +1,63 @@
+/*
+ * 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_EFFECTS_FACTORY_HAL_INTERFACE_H
+#define ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_INTERFACE_H
+
+#include <hardware/audio_effect.h>
+#include <media/audiohal/EffectHalInterface.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class EffectsFactoryHalInterface : public RefBase
+{
+ public:
+ // Returns the number of different effects in all loaded libraries.
+ virtual status_t queryNumberEffects(uint32_t *pNumEffects) = 0;
+
+ // Returns a descriptor of the next available effect.
+ virtual status_t getDescriptor(uint32_t index,
+ effect_descriptor_t *pDescriptor) = 0;
+
+ virtual status_t getDescriptor(const effect_uuid_t *pEffectUuid,
+ effect_descriptor_t *pDescriptor) = 0;
+
+ // Creates an effect engine of the specified type.
+ // To release the effect engine, it is necessary to release references
+ // to the returned effect object.
+ virtual status_t createEffect(const effect_uuid_t *pEffectUuid,
+ int32_t sessionId, int32_t ioId,
+ sp<EffectHalInterface> *effect) = 0;
+
+ virtual status_t dumpEffects(int fd) = 0;
+
+ static sp<EffectsFactoryHalInterface> create();
+
+ // Helper function to compare effect uuid to EFFECT_UUID_NULL.
+ static bool isNullUuid(const effect_uuid_t *pEffectUuid);
+
+ protected:
+ // Subclasses can not be constructed directly by clients.
+ EffectsFactoryHalInterface() {}
+
+ virtual ~EffectsFactoryHalInterface() {}
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_INTERFACE_H
diff --git a/include/media/audiohal/StreamHalInterface.h b/include/media/audiohal/StreamHalInterface.h
new file mode 100644
index 0000000..0772d8f
--- /dev/null
+++ b/include/media/audiohal/StreamHalInterface.h
@@ -0,0 +1,153 @@
+/*
+ * 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_STREAM_HAL_INTERFACE_H
+#define ANDROID_HARDWARE_STREAM_HAL_INTERFACE_H
+
+#include <media/audiohal/EffectHalInterface.h>
+#include <system/audio.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+
+namespace android {
+
+class StreamHalInterface : public virtual RefBase
+{
+ public:
+ // Return the sampling rate in Hz - eg. 44100.
+ virtual status_t getSampleRate(uint32_t *rate) = 0;
+
+ // Return size of input/output buffer in bytes for this stream - eg. 4800.
+ virtual status_t getBufferSize(size_t *size) = 0;
+
+ // Return the channel mask.
+ virtual status_t getChannelMask(audio_channel_mask_t *mask) = 0;
+
+ // Return the audio format - e.g. AUDIO_FORMAT_PCM_16_BIT.
+ virtual status_t getFormat(audio_format_t *format) = 0;
+
+ // Convenience method.
+ virtual status_t getAudioProperties(
+ uint32_t *sampleRate, audio_channel_mask_t *mask, audio_format_t *format) = 0;
+
+ // Set audio stream parameters.
+ virtual status_t setParameters(const String8& kvPairs) = 0;
+
+ // Get audio stream parameters.
+ virtual status_t getParameters(const String8& keys, String8 *values) = 0;
+
+ // Return the frame size (number of bytes per sample) of a stream.
+ virtual status_t getFrameSize(size_t *size) = 0;
+
+ // Add or remove the effect on the stream.
+ virtual status_t addEffect(sp<EffectHalInterface> effect) = 0;
+ virtual status_t removeEffect(sp<EffectHalInterface> effect) = 0;
+
+ // Put the audio hardware input/output into standby mode.
+ virtual status_t standby() = 0;
+
+ virtual status_t dump(int fd) = 0;
+
+ protected:
+ // Subclasses can not be constructed directly by clients.
+ StreamHalInterface() {}
+
+ // The destructor automatically closes the stream.
+ virtual ~StreamHalInterface() {}
+};
+
+class StreamOutHalInterfaceCallback : public virtual RefBase {
+ public:
+ virtual void onWriteReady() {}
+ virtual void onDrainReady() {}
+ virtual void onError() {}
+
+ protected:
+ StreamOutHalInterfaceCallback() {}
+ virtual ~StreamOutHalInterfaceCallback() {}
+};
+
+class StreamOutHalInterface : public virtual StreamHalInterface {
+ public:
+ // Return the audio hardware driver estimated latency in milliseconds.
+ virtual status_t getLatency(uint32_t *latency) = 0;
+
+ // Use this method in situations where audio mixing is done in the hardware.
+ virtual status_t setVolume(float left, float right) = 0;
+
+ // Write audio buffer to driver.
+ virtual status_t write(const void *buffer, size_t bytes, size_t *written) = 0;
+
+ // Return the number of audio frames written by the audio dsp to DAC since
+ // the output has exited standby.
+ virtual status_t getRenderPosition(uint32_t *dspFrames) = 0;
+
+ // Get the local time at which the next write to the audio driver will be presented.
+ virtual status_t getNextWriteTimestamp(int64_t *timestamp) = 0;
+
+ // Set the callback for notifying completion of non-blocking write and drain.
+ // The callback must be owned by someone else. The output stream does not own it
+ // to avoid strong pointer loops.
+ virtual status_t setCallback(wp<StreamOutHalInterfaceCallback> callback) = 0;
+
+ // Returns whether pause and resume operations are supported.
+ virtual status_t supportsPauseAndResume(bool *supportsPause, bool *supportsResume) = 0;
+
+ // Notifies to the audio driver to resume playback following a pause.
+ virtual status_t pause() = 0;
+
+ // Notifies to the audio driver to resume playback following a pause.
+ virtual status_t resume() = 0;
+
+ // Returns whether drain operation is supported.
+ virtual status_t supportsDrain(bool *supportsDrain) = 0;
+
+ // Requests notification when data buffered by the driver/hardware has been played.
+ virtual status_t drain(bool earlyNotify) = 0;
+
+ // Notifies to the audio driver to flush the queued data.
+ virtual status_t flush() = 0;
+
+ // Return a recent count of the number of audio frames presented to an external observer.
+ virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp) = 0;
+
+ protected:
+ virtual ~StreamOutHalInterface() {}
+};
+
+class StreamInHalInterface : public virtual StreamHalInterface {
+ public:
+ // Set the input gain for the audio driver.
+ virtual status_t setGain(float gain) = 0;
+
+ // Read audio buffer in from driver.
+ virtual status_t read(void *buffer, size_t bytes, size_t *read) = 0;
+
+ // Return the amount of input frames lost in the audio driver.
+ virtual status_t getInputFramesLost(uint32_t *framesLost) = 0;
+
+ // Return a recent count of the number of audio frames received and
+ // the clock time associated with that frame count.
+ virtual status_t getCapturePosition(int64_t *frames, int64_t *time) = 0;
+
+ protected:
+ virtual ~StreamInHalInterface() {}
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_STREAM_HAL_INTERFACE_H
diff --git a/include/media/nbaio/AudioStreamInSource.h b/include/media/nbaio/AudioStreamInSource.h
index a6e7992..508e0fe 100644
--- a/include/media/nbaio/AudioStreamInSource.h
+++ b/include/media/nbaio/AudioStreamInSource.h
@@ -17,16 +17,17 @@
#ifndef ANDROID_AUDIO_STREAM_IN_SOURCE_H
#define ANDROID_AUDIO_STREAM_IN_SOURCE_H
-#include <hardware/audio.h>
#include "NBAIO.h"
namespace android {
+class StreamInHalInterface;
+
// not multi-thread safe
class AudioStreamInSource : public NBAIO_Source {
public:
- AudioStreamInSource(audio_stream_in *stream);
+ AudioStreamInSource(sp<StreamInHalInterface> stream);
virtual ~AudioStreamInSource();
// NBAIO_Port interface
@@ -50,11 +51,11 @@
// NBAIO_Sink end
#if 0 // until necessary
- audio_stream_in *stream() const { return mStream; }
+ sp<StreamInHalInterface> stream() const { return mStream; }
#endif
private:
- audio_stream_in * const mStream;
+ sp<StreamInHalInterface> mStream;
size_t mStreamBufferSizeBytes; // as reported by get_buffer_size()
int64_t mFramesOverrun;
int64_t mOverruns;
diff --git a/include/media/nbaio/AudioStreamOutSink.h b/include/media/nbaio/AudioStreamOutSink.h
index e86b018..56052a6 100644
--- a/include/media/nbaio/AudioStreamOutSink.h
+++ b/include/media/nbaio/AudioStreamOutSink.h
@@ -17,16 +17,17 @@
#ifndef ANDROID_AUDIO_STREAM_OUT_SINK_H
#define ANDROID_AUDIO_STREAM_OUT_SINK_H
-#include <hardware/audio.h>
#include "NBAIO.h"
namespace android {
+class StreamOutHalInterface;
+
// not multi-thread safe
class AudioStreamOutSink : public NBAIO_Sink {
public:
- AudioStreamOutSink(audio_stream_out *stream);
+ AudioStreamOutSink(sp<StreamOutHalInterface> stream);
virtual ~AudioStreamOutSink();
// NBAIO_Port interface
@@ -52,11 +53,11 @@
// NBAIO_Sink end
#if 0 // until necessary
- audio_stream_out *stream() const { return mStream; }
+ sp<StreamOutHalInterface> stream() const { return mStream; }
#endif
private:
- audio_stream_out * const mStream;
+ sp<StreamOutHalInterface> mStream;
size_t mStreamBufferSizeBytes; // as reported by get_buffer_size()
};
diff --git a/include/media/nbaio/NBAIO.h b/include/media/nbaio/NBAIO.h
index 120de4f..3fd97ac 100644
--- a/include/media/nbaio/NBAIO.h
+++ b/include/media/nbaio/NBAIO.h
@@ -35,13 +35,16 @@
// In addition to the usual status_t
enum {
- NEGOTIATE = 0x80000010, // Must (re-)negotiate format. For negotiate() only, the offeree
- // doesn't accept offers, and proposes counter-offers
- OVERRUN = 0x80000011, // availableToRead(), read(), or readVia() detected lost input due
- // to overrun; an event is counted and the caller should re-try
- UNDERRUN = 0x80000012, // availableToWrite(), write(), or writeVia() detected a gap in
- // output due to underrun (not being called often enough, or with
- // enough data); an event is counted and the caller should re-try
+ NEGOTIATE = (UNKNOWN_ERROR + 0x100), // Must (re-)negotiate format. For negotiate() only,
+ // the offeree doesn't accept offers, and proposes
+ // counter-offers
+ OVERRUN = (UNKNOWN_ERROR + 0x101), // availableToRead(), read(), or readVia() detected
+ // lost input due to overrun; an event is counted and
+ // the caller should re-try
+ UNDERRUN = (UNKNOWN_ERROR + 0x102), // availableToWrite(), write(), or writeVia() detected
+ // a gap in output due to underrun (not being called
+ // often enough, or with enough data); an event is
+ // counted and the caller should re-try
};
// Negotiation of format is based on the data provider and data sink, or the data consumer and
@@ -266,6 +269,17 @@
// One or more frames were lost due to overrun, try again to read more recent data.
virtual ssize_t read(void *buffer, size_t count) = 0;
+ // Flush data from buffer. There is no notion of overrun as all data is dropped.
+ // Flushed frames also count towards frames read.
+ //
+ // Return value:
+ // >= 0 Number of frames successfully flushed
+ // < 0 status_t error occurred
+ // Errors:
+ // NEGOTIATE (Re-)negotiation is needed.
+ // INVALID_OPERATION Not implemented
+ virtual ssize_t flush() { return INVALID_OPERATION; }
+
// Transfer data from source using a series of callbacks. More suitable for zero-fill,
// synthesis, and non-contiguous transfers (e.g. circular buffer or readv).
// Inputs:
diff --git a/include/media/nbaio/PipeReader.h b/include/media/nbaio/PipeReader.h
index 7c733ad..00c2b3c 100644
--- a/include/media/nbaio/PipeReader.h
+++ b/include/media/nbaio/PipeReader.h
@@ -47,6 +47,8 @@
virtual ssize_t read(void *buffer, size_t count);
+ virtual ssize_t flush();
+
// NBAIO_Source end
#if 0 // until necessary
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 7b3e71c..c02742c 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -35,6 +35,7 @@
namespace android {
struct ABuffer;
+class MediaCodecBuffer;
struct MemoryDealer;
struct DescribeColorFormat2Params;
struct DataConverter;
@@ -74,7 +75,7 @@
struct PortDescription : public CodecBase::PortDescription {
size_t countBuffers();
IOMX::buffer_id bufferIDAt(size_t index) const;
- sp<ABuffer> bufferAt(size_t index) const;
+ sp<MediaCodecBuffer> bufferAt(size_t index) const;
sp<NativeHandle> handleAt(size_t index) const;
sp<RefBase> memRefAt(size_t index) const;
@@ -82,22 +83,18 @@
friend struct ACodec;
Vector<IOMX::buffer_id> mBufferIDs;
- Vector<sp<ABuffer> > mBuffers;
+ Vector<sp<MediaCodecBuffer>> mBuffers;
Vector<sp<NativeHandle> > mHandles;
Vector<sp<RefBase> > mMemRefs;
PortDescription();
void addBuffer(
- IOMX::buffer_id id, const sp<ABuffer> &buffer,
+ IOMX::buffer_id id, const sp<MediaCodecBuffer> &buffer,
const sp<NativeHandle> &handle, const sp<RefBase> &memRef);
DISALLOW_EVIL_CONSTRUCTORS(PortDescription);
};
- static bool isFlexibleColorFormat(
- const sp<IOMX> &omx, IOMX::node_id node,
- uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent);
-
// Returns 0 if configuration is not supported. NOTE: this is treated by
// some OMX components as auto level, and by others as invalid level.
static int /* OMX_VIDEO_AVCLEVELTYPE */ getAVCLevelFor(
@@ -190,11 +187,12 @@
Status mStatus;
unsigned mDequeuedAt;
- sp<ABuffer> mData; // the client's buffer; if not using data conversion, this is the
- // codec buffer; otherwise, it is allocated separately
- sp<RefBase> mMemRef; // and a reference to the IMemory, so it does not go away
- sp<ABuffer> mCodecData; // the codec's buffer
- sp<RefBase> mCodecRef; // and a reference to the IMemory
+ sp<MediaCodecBuffer> mData; // the client's buffer; if not using data conversion, this is
+ // the codec buffer; otherwise, it is allocated separately
+ sp<RefBase> mMemRef; // and a reference to the IMemory, so it does not go away
+ sp<MediaCodecBuffer> mCodecData; // the codec's buffer
+ sp<RefBase> mCodecRef; // and a reference to the IMemory
+
sp<GraphicBuffer> mGraphicBuffer;
sp<NativeHandle> mNativeHandle;
int mFenceFd;
@@ -208,6 +206,8 @@
// Log error, if the current fence is not a read/write fence.
void checkReadFence(const char *dbg);
void checkWriteFence(const char *dbg);
+
+ sp<MediaCodecBuffer> alloc(const sp<AMessage> &format);
};
static const char *_asString(BufferInfo::Status s);
@@ -242,10 +242,9 @@
AString mComponentName;
uint32_t mFlags;
- uint32_t mQuirks;
sp<IOMX> mOMX;
- sp<IBinder> mNodeBinder;
- IOMX::node_id mNode;
+ sp<IOMXNode> mOMXNode;
+ int32_t mNodeGeneration;
sp<MemoryDealer> mDealer[2];
bool mUsingNativeWindow;
@@ -294,13 +293,12 @@
size_t mNumUndequeuedBuffers;
sp<DataConverter> mConverter[2];
+ sp<IGraphicBufferSource> mGraphicBufferSource;
int64_t mRepeatFrameDelayUs;
int64_t mMaxPtsGapUs;
float mMaxFps;
-
int64_t mTimePerFrameUs;
int64_t mTimePerCaptureUs;
-
bool mCreateInputBuffersSuspended;
bool mTunneled;
@@ -342,9 +340,6 @@
ssize_t *index = NULL);
status_t setComponentRole(bool isEncoder, const char *mime);
- static const char *getComponentRole(bool isEncoder, const char *mime);
- static status_t setComponentRole(
- const sp<IOMX> &omx, IOMX::node_id node, const char *role);
status_t configureCodec(const char *mime, const sp<AMessage> &msg);
@@ -552,11 +547,6 @@
OMX_ERRORTYPE error = OMX_ErrorUndefined,
status_t internalError = UNKNOWN_ERROR);
- static bool describeDefaultColorFormat(DescribeColorFormat2Params &describeParams);
- static bool describeColorFormat(
- const sp<IOMX> &omx, IOMX::node_id node,
- DescribeColorFormat2Params &describeParams);
-
status_t requestIDRFrame();
status_t setParameters(const sp<AMessage> ¶ms);
diff --git a/include/media/stagefright/CodecBase.h b/include/media/stagefright/CodecBase.h
index be2835d..13f82f0 100644
--- a/include/media/stagefright/CodecBase.h
+++ b/include/media/stagefright/CodecBase.h
@@ -34,8 +34,9 @@
namespace android {
-struct ABuffer;
+class MediaCodecBuffer;
struct PersistentSurface;
+class Surface;
struct CodecBase : public AHandler, /* static */ ColorUtils {
enum {
@@ -88,7 +89,7 @@
struct PortDescription : public RefBase {
virtual size_t countBuffers() = 0;
virtual IOMX::buffer_id bufferIDAt(size_t index) const = 0;
- virtual sp<ABuffer> bufferAt(size_t index) const = 0;
+ virtual sp<MediaCodecBuffer> bufferAt(size_t index) const = 0;
virtual sp<NativeHandle> handleAt(size_t index) const { return NULL; };
virtual sp<RefBase> memRefAt(size_t index) const { return NULL; }
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index 497974d..e3e5c2d 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -35,6 +35,7 @@
struct CodecBase;
class IBatteryStats;
struct ICrypto;
+class MediaCodecBuffer;
class IMemory;
struct MemoryDealer;
class IResourceManagerClient;
@@ -149,14 +150,14 @@
status_t getOutputFormat(sp<AMessage> *format) const;
status_t getInputFormat(sp<AMessage> *format) const;
- status_t getWidevineLegacyBuffers(Vector<sp<ABuffer> > *buffers) const;
+ status_t getWidevineLegacyBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const;
- status_t getInputBuffers(Vector<sp<ABuffer> > *buffers) const;
- status_t getOutputBuffers(Vector<sp<ABuffer> > *buffers) const;
+ status_t getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const;
+ status_t getOutputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const;
- status_t getOutputBuffer(size_t index, sp<ABuffer> *buffer);
+ status_t getOutputBuffer(size_t index, sp<MediaCodecBuffer> *buffer);
status_t getOutputFormat(size_t index, sp<AMessage> *format);
- status_t getInputBuffer(size_t index, sp<ABuffer> *buffer);
+ status_t getInputBuffer(size_t index, sp<MediaCodecBuffer> *buffer);
status_t setSurface(const sp<Surface> &nativeWindow);
@@ -253,10 +254,10 @@
struct BufferInfo {
uint32_t mBufferID;
- sp<ABuffer> mData;
+ sp<MediaCodecBuffer> mData;
sp<NativeHandle> mNativeHandle;
sp<RefBase> mMemRef;
- sp<ABuffer> mEncryptedData;
+ sp<MediaCodecBuffer> mEncryptedData;
sp<IMemory> mSharedEncryptedBuffer;
sp<AMessage> mNotify;
sp<AMessage> mFormat;
@@ -367,7 +368,7 @@
status_t getBufferAndFormat(
size_t portIndex, size_t index,
- sp<ABuffer> *buffer, sp<AMessage> *format);
+ sp<MediaCodecBuffer> *buffer, sp<AMessage> *format);
bool handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest = false);
bool handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest = false);
@@ -389,7 +390,7 @@
status_t onSetParameters(const sp<AMessage> ¶ms);
- status_t amendOutputFormatWithCodecSpecificData(const sp<ABuffer> &buffer);
+ status_t amendOutputFormatWithCodecSpecificData(const sp<MediaCodecBuffer> &buffer);
void updateBatteryStat();
bool isExecuting() const;
diff --git a/include/media/stagefright/MediaCodecList.h b/include/media/stagefright/MediaCodecList.h
index 44dbde0..430bc16 100644
--- a/include/media/stagefright/MediaCodecList.h
+++ b/include/media/stagefright/MediaCodecList.h
@@ -115,7 +115,6 @@
Vector<sp<MediaCodecInfo> > mCodecInfos;
sp<MediaCodecInfo> mCurrentInfo;
- sp<IOMX> mOMX;
MediaCodecList();
~MediaCodecList();
diff --git a/include/media/stagefright/MediaCodecSource.h b/include/media/stagefright/MediaCodecSource.h
index 18b1955..f9a46a9 100644
--- a/include/media/stagefright/MediaCodecSource.h
+++ b/include/media/stagefright/MediaCodecSource.h
@@ -21,8 +21,7 @@
#include <media/stagefright/foundation/AHandlerReflector.h>
#include <media/stagefright/foundation/Mutexed.h>
#include <media/stagefright/MediaSource.h>
-
-#include <gui/IGraphicBufferConsumer.h>
+#include <media/stagefright/PersistentSurface.h>
namespace android {
@@ -44,7 +43,7 @@
const sp<ALooper> &looper,
const sp<AMessage> &format,
const sp<MediaSource> &source,
- const sp<IGraphicBufferConsumer> &consumer = NULL,
+ const sp<PersistentSurface> &persistentSurface = NULL,
uint32_t flags = 0);
bool isVideo() const { return mIsVideo; }
@@ -88,7 +87,7 @@
const sp<ALooper> &looper,
const sp<AMessage> &outputFormat,
const sp<MediaSource> &source,
- const sp<IGraphicBufferConsumer> &consumer,
+ const sp<PersistentSurface> &persistentSurface,
uint32_t flags = 0);
status_t onStart(MetaData *params);
@@ -121,7 +120,7 @@
int32_t mEncoderDataSpace;
sp<AMessage> mEncoderActivityNotify;
sp<IGraphicBufferProducer> mGraphicBufferProducer;
- sp<IGraphicBufferConsumer> mGraphicBufferConsumer;
+ sp<PersistentSurface> mPersistentSurface;
List<MediaBuffer *> mInputBufferQueue;
List<size_t> mAvailEncoderInputIndices;
List<int64_t> mDecodingTimeQueue; // decoding time (us) for video
diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h
index 5f2a32d..359fb69 100644
--- a/include/media/stagefright/MediaDefs.h
+++ b/include/media/stagefright/MediaDefs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -14,69 +14,18 @@
* limitations under the License.
*/
-#ifndef MEDIA_DEFS_H_
-#define MEDIA_DEFS_H_
+#ifndef STAGEFRIGHT_MEDIA_DEFS_H_
+#define STAGEFRIGHT_MEDIA_DEFS_H_
-namespace android {
+/*
+ * Please, DO NOT USE!
+ *
+ * This file is here only for legacy reasons. Instead, include directly
+ * the header below.
+ *
+ */
-extern const char *MEDIA_MIMETYPE_IMAGE_JPEG;
+#include <media/MediaDefs.h>
-extern const char *MEDIA_MIMETYPE_VIDEO_VP8;
-extern const char *MEDIA_MIMETYPE_VIDEO_VP9;
-extern const char *MEDIA_MIMETYPE_VIDEO_AVC;
-extern const char *MEDIA_MIMETYPE_VIDEO_HEVC;
-extern const char *MEDIA_MIMETYPE_VIDEO_MPEG4;
-extern const char *MEDIA_MIMETYPE_VIDEO_H263;
-extern const char *MEDIA_MIMETYPE_VIDEO_MPEG2;
-extern const char *MEDIA_MIMETYPE_VIDEO_RAW;
-extern const char *MEDIA_MIMETYPE_VIDEO_DOLBY_VISION;
-
-extern const char *MEDIA_MIMETYPE_AUDIO_AMR_NB;
-extern const char *MEDIA_MIMETYPE_AUDIO_AMR_WB;
-extern const char *MEDIA_MIMETYPE_AUDIO_MPEG; // layer III
-extern const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I;
-extern const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II;
-extern const char *MEDIA_MIMETYPE_AUDIO_MIDI;
-extern const char *MEDIA_MIMETYPE_AUDIO_AAC;
-extern const char *MEDIA_MIMETYPE_AUDIO_QCELP;
-extern const char *MEDIA_MIMETYPE_AUDIO_VORBIS;
-extern const char *MEDIA_MIMETYPE_AUDIO_OPUS;
-extern const char *MEDIA_MIMETYPE_AUDIO_G711_ALAW;
-extern const char *MEDIA_MIMETYPE_AUDIO_G711_MLAW;
-extern const char *MEDIA_MIMETYPE_AUDIO_RAW;
-extern const char *MEDIA_MIMETYPE_AUDIO_FLAC;
-extern const char *MEDIA_MIMETYPE_AUDIO_AAC_ADTS;
-extern const char *MEDIA_MIMETYPE_AUDIO_MSGSM;
-extern const char *MEDIA_MIMETYPE_AUDIO_AC3;
-extern const char *MEDIA_MIMETYPE_AUDIO_EAC3;
-
-extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG4;
-extern const char *MEDIA_MIMETYPE_CONTAINER_WAV;
-extern const char *MEDIA_MIMETYPE_CONTAINER_OGG;
-extern const char *MEDIA_MIMETYPE_CONTAINER_MATROSKA;
-extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG2TS;
-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;
-extern const char *MEDIA_MIMETYPE_TEXT_CEA_608;
-extern const char *MEDIA_MIMETYPE_TEXT_CEA_708;
-extern const char *MEDIA_MIMETYPE_DATA_TIMED_ID3;
-
-// These are values exported to JAVA API that need to be in sync with
-// frameworks/base/media/java/android/media/AudioFormat.java. Unfortunately,
-// they are not defined in frameworks/av, so defining them here.
-enum AudioEncoding {
- kAudioEncodingPcm16bit = 2,
- kAudioEncodingPcm8bit = 3,
- kAudioEncodingPcmFloat = 4,
-};
-
-} // namespace android
-
-#endif // MEDIA_DEFS_H_
+#endif // STAGEFRIGHT_MEDIA_DEFS_H_
diff --git a/include/media/stagefright/MediaFilter.h b/include/media/stagefright/MediaFilter.h
index d0a572c..6aa87e8 100644
--- a/include/media/stagefright/MediaFilter.h
+++ b/include/media/stagefright/MediaFilter.h
@@ -21,7 +21,6 @@
namespace android {
-struct ABuffer;
struct GraphicBufferListener;
struct MemoryDealer;
struct SimpleFilter;
@@ -51,7 +50,7 @@
struct PortDescription : public CodecBase::PortDescription {
virtual size_t countBuffers();
virtual IOMX::buffer_id bufferIDAt(size_t index) const;
- virtual sp<ABuffer> bufferAt(size_t index) const;
+ virtual sp<MediaCodecBuffer> bufferAt(size_t index) const;
protected:
PortDescription();
@@ -60,9 +59,9 @@
friend struct MediaFilter;
Vector<IOMX::buffer_id> mBufferIDs;
- Vector<sp<ABuffer> > mBuffers;
+ Vector<sp<MediaCodecBuffer> > mBuffers;
- void addBuffer(IOMX::buffer_id id, const sp<ABuffer> &buffer);
+ void addBuffer(IOMX::buffer_id id, const sp<MediaCodecBuffer> &buffer);
DISALLOW_EVIL_CONSTRUCTORS(PortDescription);
};
@@ -82,7 +81,7 @@
int32_t mOutputFlags;
Status mStatus;
- sp<ABuffer> mData;
+ sp<MediaCodecBuffer> mData;
};
enum State {
diff --git a/include/media/stagefright/OMXClient.h b/include/media/stagefright/OMXClient.h
index 2f14d06..6973405 100644
--- a/include/media/stagefright/OMXClient.h
+++ b/include/media/stagefright/OMXClient.h
@@ -18,10 +18,10 @@
#define OMX_CLIENT_H_
-#include <media/IOMX.h>
-
namespace android {
+class IOMX;
+
class OMXClient {
public:
OMXClient();
diff --git a/include/media/stagefright/PersistentSurface.h b/include/media/stagefright/PersistentSurface.h
index a35b9f1..d8b75a2 100644
--- a/include/media/stagefright/PersistentSurface.h
+++ b/include/media/stagefright/PersistentSurface.h
@@ -19,29 +19,46 @@
#define PERSISTENT_SURFACE_H_
#include <gui/IGraphicBufferProducer.h>
-#include <gui/IGraphicBufferConsumer.h>
+#include <android/IGraphicBufferSource.h>
#include <media/stagefright/foundation/ABase.h>
+#include <binder/Parcel.h>
namespace android {
struct PersistentSurface : public RefBase {
+ PersistentSurface() {}
+
PersistentSurface(
const sp<IGraphicBufferProducer>& bufferProducer,
- const sp<IGraphicBufferConsumer>& bufferConsumer) :
+ const sp<IGraphicBufferSource>& bufferSource) :
mBufferProducer(bufferProducer),
- mBufferConsumer(bufferConsumer) { }
+ mBufferSource(bufferSource) { }
sp<IGraphicBufferProducer> getBufferProducer() const {
return mBufferProducer;
}
- sp<IGraphicBufferConsumer> getBufferConsumer() const {
- return mBufferConsumer;
+ sp<IGraphicBufferSource> getBufferSource() const {
+ return mBufferSource;
+ }
+
+ status_t writeToParcel(Parcel *parcel) const {
+ parcel->writeStrongBinder(IInterface::asBinder(mBufferProducer));
+ parcel->writeStrongBinder(IInterface::asBinder(mBufferSource));
+ return NO_ERROR;
+ }
+
+ status_t readFromParcel(const Parcel *parcel) {
+ mBufferProducer = interface_cast<IGraphicBufferProducer>(
+ parcel->readStrongBinder());
+ mBufferSource = interface_cast<IGraphicBufferSource>(
+ parcel->readStrongBinder());
+ return NO_ERROR;
}
private:
- const sp<IGraphicBufferProducer> mBufferProducer;
- const sp<IGraphicBufferConsumer> mBufferConsumer;
+ sp<IGraphicBufferProducer> mBufferProducer;
+ sp<IGraphicBufferSource> mBufferSource;
DISALLOW_EVIL_CONSTRUCTORS(PersistentSurface);
};
diff --git a/include/media/stagefright/SkipCutBuffer.h b/include/media/stagefright/SkipCutBuffer.h
index 61f9949..0fb5690 100644
--- a/include/media/stagefright/SkipCutBuffer.h
+++ b/include/media/stagefright/SkipCutBuffer.h
@@ -18,6 +18,7 @@
#define SKIP_CUT_BUFFER_H_
+#include <media/MediaCodecBuffer.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/foundation/ABuffer.h>
@@ -39,6 +40,7 @@
// After this, the caller should continue processing the buffer as usual.
void submit(MediaBuffer *buffer);
void submit(const sp<ABuffer>& buffer); // same as above, but with an ABuffer
+ void submit(const sp<MediaCodecBuffer>& buffer); // same as above, but with an ABuffer
void clear();
size_t size(); // how many bytes are currently stored in the buffer
@@ -48,6 +50,8 @@
private:
void write(const char *src, size_t num);
size_t read(char *dst, size_t num);
+ template <typename T>
+ void submitInternal(const sp<T>& buffer);
int32_t mSkip;
int32_t mFrontPadding;
int32_t mBackPadding;
diff --git a/include/media/stagefright/foundation/ColorUtils.h b/include/media/stagefright/foundation/ColorUtils.h
index 2368b82..b889a02 100644
--- a/include/media/stagefright/foundation/ColorUtils.h
+++ b/include/media/stagefright/foundation/ColorUtils.h
@@ -138,6 +138,12 @@
int32_t primaries, int32_t transfer, int32_t coeffs, bool fullRange,
ColorAspects &aspects);
+ // unpack a uint32_t to a full ColorAspects struct
+ static ColorAspects unpackToColorAspects(uint32_t packed);
+
+ // pack a full ColorAspects struct into a uint32_t
+ static uint32_t packToU32(const ColorAspects &aspects);
+
// updates Unspecified color aspects to their defaults based on the video size
static void setDefaultCodecColorAspectsIfNeeded(
ColorAspects &aspects, int32_t width, int32_t height);
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
new file mode 100644
index 0000000..e943eed
--- /dev/null
+++ b/media/libaudiohal/Android.bp
@@ -0,0 +1,24 @@
+cc_library_shared {
+ name: "libaudiohal",
+
+ srcs: [
+ "DeviceHalLocal.cpp",
+ "DevicesFactoryHalLocal.cpp",
+ "EffectHalLocal.cpp",
+ "EffectsFactoryHalLocal.cpp",
+ "StreamHalLocal.cpp",
+ ],
+
+ shared_libs: [
+ "libcutils",
+ "libhardware",
+ "liblog",
+ "libeffects",
+ "libutils",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+}
diff --git a/media/libaudiohal/DeviceHalLocal.cpp b/media/libaudiohal/DeviceHalLocal.cpp
new file mode 100644
index 0000000..c5df8c8
--- /dev/null
+++ b/media/libaudiohal/DeviceHalLocal.cpp
@@ -0,0 +1,175 @@
+/*
+ * 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 "DeviceHalLocal"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+
+#include "DeviceHalLocal.h"
+#include "StreamHalLocal.h"
+
+namespace android {
+
+DeviceHalLocal::DeviceHalLocal(audio_hw_device_t *dev)
+ : mDev(dev) {
+}
+
+DeviceHalLocal::~DeviceHalLocal() {
+ int status = audio_hw_device_close(mDev);
+ ALOGW_IF(status, "Error closing audio hw device %p: %s", mDev, strerror(-status));
+ mDev = 0;
+}
+
+status_t DeviceHalLocal::getSupportedDevices(uint32_t *devices) {
+ if (mDev->get_supported_devices == NULL) return INVALID_OPERATION;
+ *devices = mDev->get_supported_devices(mDev);
+ return OK;
+}
+
+status_t DeviceHalLocal::getVersion(uint32_t *version) {
+ *version = mDev->common.version;
+ return OK;
+}
+
+status_t DeviceHalLocal::initCheck() {
+ return mDev->init_check(mDev);
+}
+
+status_t DeviceHalLocal::setVoiceVolume(float volume) {
+ return mDev->set_voice_volume(mDev, volume);
+}
+
+status_t DeviceHalLocal::setMasterVolume(float volume) {
+ if (mDev->set_master_volume == NULL) return INVALID_OPERATION;
+ return mDev->set_master_volume(mDev, volume);
+}
+
+status_t DeviceHalLocal::getMasterVolume(float *volume) {
+ if (mDev->get_master_volume == NULL) return INVALID_OPERATION;
+ return mDev->get_master_volume(mDev, volume);
+}
+
+status_t DeviceHalLocal::setMode(audio_mode_t mode) {
+ return mDev->set_mode(mDev, mode);
+}
+
+status_t DeviceHalLocal::setMicMute(bool state) {
+ return mDev->set_mic_mute(mDev, state);
+}
+
+status_t DeviceHalLocal::getMicMute(bool *state) {
+ return mDev->get_mic_mute(mDev, state);
+}
+
+status_t DeviceHalLocal::setMasterMute(bool state) {
+ if (mDev->set_master_mute == NULL) return INVALID_OPERATION;
+ return mDev->set_master_mute(mDev, state);
+}
+
+status_t DeviceHalLocal::getMasterMute(bool *state) {
+ if (mDev->get_master_mute == NULL) return INVALID_OPERATION;
+ return mDev->get_master_mute(mDev, state);
+}
+
+status_t DeviceHalLocal::setParameters(const String8& kvPairs) {
+ return mDev->set_parameters(mDev, kvPairs.string());
+}
+
+status_t DeviceHalLocal::getParameters(const String8& keys, String8 *values) {
+ char *halValues = mDev->get_parameters(mDev, keys.string());
+ if (halValues != NULL) {
+ values->setTo(halValues);
+ free(halValues);
+ } else {
+ values->clear();
+ }
+ return OK;
+}
+
+status_t DeviceHalLocal::getInputBufferSize(
+ const struct audio_config *config, size_t *size) {
+ *size = mDev->get_input_buffer_size(mDev, config);
+ return OK;
+}
+
+status_t DeviceHalLocal::openOutputStream(
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ audio_output_flags_t flags,
+ struct audio_config *config,
+ const char *address,
+ sp<StreamOutHalInterface> *outStream) {
+ audio_stream_out_t *halStream;
+ int openResut = mDev->open_output_stream(
+ mDev, handle, devices, flags, config, &halStream, address);
+ if (openResut == OK) {
+ *outStream = new StreamOutHalLocal(halStream, this);
+ }
+ return openResut;
+}
+
+status_t DeviceHalLocal::openInputStream(
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ struct audio_config *config,
+ audio_input_flags_t flags,
+ const char *address,
+ audio_source_t source,
+ sp<StreamInHalInterface> *inStream) {
+ audio_stream_in_t *halStream;
+ int openResult = mDev->open_input_stream(
+ mDev, handle, devices, config, &halStream, flags, address, source);
+ if (openResult == OK) {
+ *inStream = new StreamInHalLocal(halStream, this);
+ }
+ return openResult;
+}
+
+status_t DeviceHalLocal::createAudioPatch(
+ unsigned int num_sources,
+ const struct audio_port_config *sources,
+ unsigned int num_sinks,
+ const struct audio_port_config *sinks,
+ audio_patch_handle_t *patch) {
+ return mDev->create_audio_patch(mDev, num_sources, sources, num_sinks, sinks, patch);
+}
+
+status_t DeviceHalLocal::releaseAudioPatch(audio_patch_handle_t patch) {
+ return mDev->release_audio_patch(mDev, patch);
+}
+
+status_t DeviceHalLocal::getAudioPort(struct audio_port *port) {
+ return mDev->get_audio_port(mDev, port);
+}
+
+status_t DeviceHalLocal::setAudioPortConfig(const struct audio_port_config *config) {
+ return mDev->set_audio_port_config(mDev, config);
+}
+
+status_t DeviceHalLocal::dump(int fd) {
+ return mDev->dump(mDev, fd);
+}
+
+void DeviceHalLocal::closeOutputStream(struct audio_stream_out *stream_out) {
+ mDev->close_output_stream(mDev, stream_out);
+}
+
+void DeviceHalLocal::closeInputStream(struct audio_stream_in *stream_in) {
+ mDev->close_input_stream(mDev, stream_in);
+}
+
+} // namespace android
diff --git a/media/libaudiohal/DeviceHalLocal.h b/media/libaudiohal/DeviceHalLocal.h
new file mode 100644
index 0000000..eba360c
--- /dev/null
+++ b/media/libaudiohal/DeviceHalLocal.h
@@ -0,0 +1,122 @@
+/*
+ * 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_DEVICE_HAL_LOCAL_H
+#define ANDROID_HARDWARE_DEVICE_HAL_LOCAL_H
+
+#include <hardware/audio.h>
+#include <media/audiohal/DeviceHalInterface.h>
+
+namespace android {
+
+class DeviceHalLocal : public DeviceHalInterface
+{
+ public:
+ // Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
+ virtual status_t getSupportedDevices(uint32_t *devices);
+
+ // Get the hardware module version.
+ virtual status_t getVersion(uint32_t *version);
+
+ // Check to see if the audio hardware interface has been initialized.
+ virtual status_t initCheck();
+
+ // Set the audio volume of a voice call. Range is between 0.0 and 1.0.
+ virtual status_t setVoiceVolume(float volume);
+
+ // Set the audio volume for all audio activities other than voice call.
+ virtual status_t setMasterVolume(float volume);
+
+ // Get the current master volume value for the HAL.
+ virtual status_t getMasterVolume(float *volume);
+
+ // Called when the audio mode changes.
+ virtual status_t setMode(audio_mode_t mode);
+
+ // Muting control.
+ virtual status_t setMicMute(bool state);
+ virtual status_t getMicMute(bool *state);
+ virtual status_t setMasterMute(bool state);
+ virtual status_t getMasterMute(bool *state);
+
+ // Set global audio parameters.
+ virtual status_t setParameters(const String8& kvPairs);
+
+ // Get global audio parameters.
+ virtual status_t getParameters(const String8& keys, String8 *values);
+
+ // Returns audio input buffer size according to parameters passed.
+ virtual status_t getInputBufferSize(const struct audio_config *config,
+ size_t *size);
+
+ // Creates and opens the audio hardware output stream. The stream is closed
+ // by releasing all references to the returned object.
+ virtual status_t openOutputStream(
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ audio_output_flags_t flags,
+ struct audio_config *config,
+ const char *address,
+ sp<StreamOutHalInterface> *outStream);
+
+ // Creates and opens the audio hardware input stream. The stream is closed
+ // by releasing all references to the returned object.
+ virtual status_t openInputStream(
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ struct audio_config *config,
+ audio_input_flags_t flags,
+ const char *address,
+ audio_source_t source,
+ sp<StreamInHalInterface> *inStream);
+
+ // Creates an audio patch between several source and sink ports.
+ virtual status_t createAudioPatch(
+ unsigned int num_sources,
+ const struct audio_port_config *sources,
+ unsigned int num_sinks,
+ const struct audio_port_config *sinks,
+ audio_patch_handle_t *patch);
+
+ // Releases an audio patch.
+ virtual status_t releaseAudioPatch(audio_patch_handle_t patch);
+
+ // Fills the list of supported attributes for a given audio port.
+ virtual status_t getAudioPort(struct audio_port *port);
+
+ // Set audio port configuration.
+ virtual status_t setAudioPortConfig(const struct audio_port_config *config);
+
+ virtual status_t dump(int fd);
+
+ void closeOutputStream(struct audio_stream_out *stream_out);
+ void closeInputStream(struct audio_stream_in *stream_in);
+
+ private:
+ audio_hw_device_t *mDev;
+
+ friend class DevicesFactoryHalLocal;
+
+ // Can not be constructed directly by clients.
+ explicit DeviceHalLocal(audio_hw_device_t *dev);
+
+ // The destructor automatically closes the device.
+ virtual ~DeviceHalLocal();
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_DEVICE_HAL_LOCAL_H
diff --git a/media/libaudiohal/DevicesFactoryHalLocal.cpp b/media/libaudiohal/DevicesFactoryHalLocal.cpp
new file mode 100644
index 0000000..cd9a9e7
--- /dev/null
+++ b/media/libaudiohal/DevicesFactoryHalLocal.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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 "DevicesFactoryHalLocal"
+//#define LOG_NDEBUG 0
+
+#include <string.h>
+
+#include <hardware/audio.h>
+#include <utils/Log.h>
+
+#include "DeviceHalLocal.h"
+#include "DevicesFactoryHalLocal.h"
+
+namespace android {
+
+// static
+sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() {
+ return new DevicesFactoryHalLocal();
+}
+
+static status_t load_audio_interface(const char *if_name, audio_hw_device_t **dev)
+{
+ const hw_module_t *mod;
+ int rc;
+
+ rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
+ if (rc) {
+ ALOGE("%s couldn't load audio hw module %s.%s (%s)", __func__,
+ AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
+ goto out;
+ }
+ rc = audio_hw_device_open(mod, dev);
+ if (rc) {
+ ALOGE("%s couldn't open audio hw device in %s.%s (%s)", __func__,
+ AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
+ goto out;
+ }
+ if ((*dev)->common.version < AUDIO_DEVICE_API_VERSION_MIN) {
+ ALOGE("%s wrong audio hw device version %04x", __func__, (*dev)->common.version);
+ rc = BAD_VALUE;
+ audio_hw_device_close(*dev);
+ goto out;
+ }
+ return OK;
+
+out:
+ *dev = NULL;
+ return rc;
+}
+
+status_t DevicesFactoryHalLocal::openDevice(const char *name, sp<DeviceHalInterface> *device) {
+ audio_hw_device_t *dev;
+ status_t rc = load_audio_interface(name, &dev);
+ if (rc == OK) {
+ *device = new DeviceHalLocal(dev);
+ }
+ return rc;
+}
+
+} // namespace android
diff --git a/media/libaudiohal/DevicesFactoryHalLocal.h b/media/libaudiohal/DevicesFactoryHalLocal.h
new file mode 100644
index 0000000..690cd34
--- /dev/null
+++ b/media/libaudiohal/DevicesFactoryHalLocal.h
@@ -0,0 +1,46 @@
+/*
+ * 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_DEVICES_FACTORY_HAL_LOCAL_H
+#define ANDROID_HARDWARE_DEVICES_FACTORY_HAL_LOCAL_H
+
+#include <media/audiohal/DevicesFactoryHalInterface.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+#include "DeviceHalLocal.h"
+
+namespace android {
+
+class DevicesFactoryHalLocal : public DevicesFactoryHalInterface
+{
+ public:
+ virtual ~DevicesFactoryHalLocal() {}
+
+ // Opens a device with the specified name. To close the device, it is
+ // necessary to release references to the returned object.
+ virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device);
+
+ private:
+ friend class DevicesFactoryHalInterface;
+
+ // Can not be constructed directly by clients.
+ DevicesFactoryHalLocal() {}
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_DEVICES_FACTORY_HAL_LOCAL_H
diff --git a/media/libaudiohal/EffectHalLocal.cpp b/media/libaudiohal/EffectHalLocal.cpp
new file mode 100644
index 0000000..56a365c
--- /dev/null
+++ b/media/libaudiohal/EffectHalLocal.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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 "EffectHalLocal"
+//#define LOG_NDEBUG 0
+
+#include <media/EffectsFactoryApi.h>
+#include <utils/Log.h>
+
+#include "EffectHalLocal.h"
+
+namespace android {
+
+EffectHalLocal::EffectHalLocal(effect_handle_t handle)
+ : mHandle(handle) {
+}
+
+EffectHalLocal::~EffectHalLocal() {
+ int status = EffectRelease(mHandle);
+ ALOGW_IF(status, "Error releasing effect %p: %s", mHandle, strerror(-status));
+ mHandle = 0;
+}
+
+status_t EffectHalLocal::process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) {
+ return (*mHandle)->process(mHandle, inBuffer, outBuffer);
+}
+
+status_t EffectHalLocal::processReverse(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) {
+ return (*mHandle)->process_reverse(mHandle, inBuffer, outBuffer);
+}
+
+status_t EffectHalLocal::command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
+ uint32_t *replySize, void *pReplyData) {
+ return (*mHandle)->command(mHandle, cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+}
+
+status_t EffectHalLocal::getDescriptor(effect_descriptor_t *pDescriptor) {
+ return (*mHandle)->get_descriptor(mHandle, pDescriptor);
+}
+
+} // namespace android
diff --git a/media/libaudiohal/EffectHalLocal.h b/media/libaudiohal/EffectHalLocal.h
new file mode 100644
index 0000000..2777e46
--- /dev/null
+++ b/media/libaudiohal/EffectHalLocal.h
@@ -0,0 +1,59 @@
+/*
+ * 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_EFFECT_HAL_LOCAL_H
+#define ANDROID_HARDWARE_EFFECT_HAL_LOCAL_H
+
+#include <media/audiohal/EffectHalInterface.h>
+
+namespace android {
+
+class EffectHalLocal : public EffectHalInterface
+{
+ public:
+ // Effect process function. Takes input samples as specified
+ // in input buffer descriptor and output processed samples as specified
+ // in output buffer descriptor.
+ virtual status_t process(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer);
+
+ // Process reverse stream function. This function is used to pass
+ // a reference stream to the effect engine.
+ virtual status_t processReverse(audio_buffer_t *inBuffer, audio_buffer_t *outBuffer);
+
+ // Send a command and receive a response to/from effect engine.
+ virtual status_t command(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData,
+ uint32_t *replySize, void *pReplyData);
+
+ // Returns the effect descriptor.
+ virtual status_t getDescriptor(effect_descriptor_t *pDescriptor);
+
+ effect_handle_t handle() const { return mHandle; }
+
+ private:
+ effect_handle_t mHandle;
+
+ friend class EffectsFactoryHalLocal;
+
+ // Can not be constructed directly by clients.
+ explicit EffectHalLocal(effect_handle_t handle);
+
+ // The destructor automatically releases the effect.
+ virtual ~EffectHalLocal();
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_EFFECT_HAL_LOCAL_H
diff --git a/media/libaudiohal/EffectsFactoryHalLocal.cpp b/media/libaudiohal/EffectsFactoryHalLocal.cpp
new file mode 100644
index 0000000..bbdef5d
--- /dev/null
+++ b/media/libaudiohal/EffectsFactoryHalLocal.cpp
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+#include <media/EffectsFactoryApi.h>
+
+#include "EffectHalLocal.h"
+#include "EffectsFactoryHalLocal.h"
+
+namespace android {
+
+// static
+sp<EffectsFactoryHalInterface> EffectsFactoryHalInterface::create() {
+ return new EffectsFactoryHalLocal();
+}
+
+// static
+bool EffectsFactoryHalInterface::isNullUuid(const effect_uuid_t *pEffectUuid) {
+ return EffectIsNullUuid(pEffectUuid);
+}
+
+status_t EffectsFactoryHalLocal::queryNumberEffects(uint32_t *pNumEffects) {
+ return EffectQueryNumberEffects(pNumEffects);
+}
+
+status_t EffectsFactoryHalLocal::getDescriptor(
+ uint32_t index, effect_descriptor_t *pDescriptor) {
+ return EffectQueryEffect(index, pDescriptor);
+}
+
+status_t EffectsFactoryHalLocal::getDescriptor(
+ const effect_uuid_t *pEffectUuid, effect_descriptor_t *pDescriptor) {
+ return EffectGetDescriptor(pEffectUuid, pDescriptor);
+}
+
+status_t EffectsFactoryHalLocal::createEffect(
+ const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t ioId,
+ sp<EffectHalInterface> *effect) {
+ effect_handle_t handle;
+ int result = EffectCreate(pEffectUuid, sessionId, ioId, &handle);
+ if (result == 0) {
+ *effect = new EffectHalLocal(handle);
+ }
+ return result;
+}
+
+status_t EffectsFactoryHalLocal::dumpEffects(int fd) {
+ return EffectDumpEffects(fd);
+}
+
+} // namespace android
diff --git a/media/libaudiohal/EffectsFactoryHalLocal.h b/media/libaudiohal/EffectsFactoryHalLocal.h
new file mode 100644
index 0000000..d5b81be
--- /dev/null
+++ b/media/libaudiohal/EffectsFactoryHalLocal.h
@@ -0,0 +1,57 @@
+/*
+ * 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_EFFECTS_FACTORY_HAL_LOCAL_H
+#define ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_LOCAL_H
+
+#include <media/audiohal/EffectsFactoryHalInterface.h>
+
+namespace android {
+
+class EffectsFactoryHalLocal : public EffectsFactoryHalInterface
+{
+ public:
+ // Returns the number of different effects in all loaded libraries.
+ virtual status_t queryNumberEffects(uint32_t *pNumEffects);
+
+ // Returns a descriptor of the next available effect.
+ virtual status_t getDescriptor(uint32_t index,
+ effect_descriptor_t *pDescriptor);
+
+ virtual status_t getDescriptor(const effect_uuid_t *pEffectUuid,
+ effect_descriptor_t *pDescriptor);
+
+ // Creates an effect engine of the specified type.
+ // To release the effect engine, it is necessary to release references
+ // to the returned effect object.
+ virtual status_t createEffect(const effect_uuid_t *pEffectUuid,
+ int32_t sessionId, int32_t ioId,
+ sp<EffectHalInterface> *effect);
+
+ virtual status_t dumpEffects(int fd);
+
+ private:
+ friend class EffectsFactoryHalInterface;
+
+ // Can not be constructed directly by clients.
+ EffectsFactoryHalLocal() {}
+
+ virtual ~EffectsFactoryHalLocal() {}
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_LOCAL_H
diff --git a/media/libaudiohal/StreamHalLocal.cpp b/media/libaudiohal/StreamHalLocal.cpp
new file mode 100644
index 0000000..12a1222
--- /dev/null
+++ b/media/libaudiohal/StreamHalLocal.cpp
@@ -0,0 +1,258 @@
+/*
+ * 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 "StreamHalLocal"
+//#define LOG_NDEBUG 0
+
+#include <hardware/audio.h>
+#include <utils/Log.h>
+
+#include "DeviceHalLocal.h"
+#include "EffectHalLocal.h"
+#include "StreamHalLocal.h"
+
+namespace android {
+
+StreamHalLocal::StreamHalLocal(audio_stream_t *stream, sp<DeviceHalLocal> device)
+ : mDevice(device), mStream(stream) {
+}
+
+StreamHalLocal::~StreamHalLocal() {
+ mStream = 0;
+ mDevice.clear();
+}
+
+status_t StreamHalLocal::getSampleRate(uint32_t *rate) {
+ *rate = mStream->get_sample_rate(mStream);
+ return OK;
+}
+
+status_t StreamHalLocal::getBufferSize(size_t *size) {
+ *size = mStream->get_buffer_size(mStream);
+ return OK;
+}
+
+status_t StreamHalLocal::getChannelMask(audio_channel_mask_t *mask) {
+ *mask = mStream->get_channels(mStream);
+ return OK;
+}
+
+status_t StreamHalLocal::getFormat(audio_format_t *format) {
+ *format = mStream->get_format(mStream);
+ return OK;
+}
+
+status_t StreamHalLocal::getAudioProperties(
+ uint32_t *sampleRate, audio_channel_mask_t *mask, audio_format_t *format) {
+ *sampleRate = mStream->get_sample_rate(mStream);
+ *mask = mStream->get_channels(mStream);
+ *format = mStream->get_format(mStream);
+ return OK;
+}
+
+status_t StreamHalLocal::setParameters(const String8& kvPairs) {
+ return mStream->set_parameters(mStream, kvPairs.string());
+}
+
+status_t StreamHalLocal::getParameters(const String8& keys, String8 *values) {
+ char *halValues = mStream->get_parameters(mStream, keys.string());
+ if (halValues != NULL) {
+ values->setTo(halValues);
+ free(halValues);
+ } else {
+ values->clear();
+ }
+ return OK;
+}
+
+status_t StreamHalLocal::addEffect(sp<EffectHalInterface> effect) {
+ return mStream->add_audio_effect(mStream,
+ static_cast<EffectHalLocal*>(effect.get())->handle());
+}
+
+status_t StreamHalLocal::removeEffect(sp<EffectHalInterface> effect) {
+ return mStream->remove_audio_effect(mStream,
+ static_cast<EffectHalLocal*>(effect.get())->handle());
+}
+
+status_t StreamHalLocal::standby() {
+ return mStream->standby(mStream);
+}
+
+status_t StreamHalLocal::dump(int fd) {
+ return mStream->dump(mStream, fd);
+}
+
+StreamOutHalLocal::StreamOutHalLocal(audio_stream_out_t *stream, sp<DeviceHalLocal> device)
+ : StreamHalLocal(&stream->common, device), mStream(stream) {
+}
+
+StreamOutHalLocal::~StreamOutHalLocal() {
+ mCallback.clear();
+ mDevice->closeOutputStream(mStream);
+ mStream = 0;
+}
+
+status_t StreamOutHalLocal::getFrameSize(size_t *size) {
+ *size = audio_stream_out_frame_size(mStream);
+ return OK;
+}
+
+status_t StreamOutHalLocal::getLatency(uint32_t *latency) {
+ *latency = mStream->get_latency(mStream);
+ return OK;
+}
+
+status_t StreamOutHalLocal::setVolume(float left, float right) {
+ if (mStream->set_volume == NULL) return INVALID_OPERATION;
+ return mStream->set_volume(mStream, left, right);
+}
+
+status_t StreamOutHalLocal::write(const void *buffer, size_t bytes, size_t *written) {
+ ssize_t writeResult = mStream->write(mStream, buffer, bytes);
+ if (writeResult > 0) {
+ *written = writeResult;
+ return OK;
+ } else {
+ *written = 0;
+ return writeResult;
+ }
+}
+
+status_t StreamOutHalLocal::getRenderPosition(uint32_t *dspFrames) {
+ return mStream->get_render_position(mStream, dspFrames);
+}
+
+status_t StreamOutHalLocal::getNextWriteTimestamp(int64_t *timestamp) {
+ if (mStream->get_next_write_timestamp == NULL) return INVALID_OPERATION;
+ return mStream->get_next_write_timestamp(mStream, timestamp);
+}
+
+status_t StreamOutHalLocal::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
+ if (mStream->set_callback == NULL) return INVALID_OPERATION;
+ status_t result = mStream->set_callback(mStream, StreamOutHalLocal::asyncCallback, this);
+ if (result == OK) {
+ mCallback = callback;
+ }
+ return result;
+}
+
+// static
+int StreamOutHalLocal::asyncCallback(stream_callback_event_t event, void*, void *cookie) {
+ // We act as if we gave a wp<StreamOutHalLocal> to HAL. This way we should handle
+ // correctly the case when the callback is invoked while StreamOutHalLocal's destructor is
+ // already running, because the destructor is invoked after the refcount has been atomically
+ // decremented.
+ wp<StreamOutHalLocal> weakSelf(reinterpret_cast<StreamOutHalLocal*>(cookie));
+ sp<StreamOutHalLocal> self = weakSelf.promote();
+ if (self == 0) return 0;
+ sp<StreamOutHalInterfaceCallback> callback = self->mCallback.promote();
+ if (callback == 0) return 0;
+ ALOGV("asyncCallback() event %d", event);
+ switch (event) {
+ case STREAM_CBK_EVENT_WRITE_READY:
+ callback->onWriteReady();
+ break;
+ case STREAM_CBK_EVENT_DRAIN_READY:
+ callback->onDrainReady();
+ break;
+ case STREAM_CBK_EVENT_ERROR:
+ callback->onError();
+ break;
+ default:
+ ALOGW("asyncCallback() unknown event %d", event);
+ break;
+ }
+ return 0;
+}
+
+status_t StreamOutHalLocal::supportsPauseAndResume(bool *supportsPause, bool *supportsResume) {
+ *supportsPause = mStream->pause != NULL;
+ *supportsResume = mStream->resume != NULL;
+ return OK;
+}
+
+status_t StreamOutHalLocal::pause() {
+ if (mStream->pause == NULL) return INVALID_OPERATION;
+ return mStream->pause(mStream);
+}
+
+status_t StreamOutHalLocal::resume() {
+ if (mStream->resume == NULL) return INVALID_OPERATION;
+ return mStream->resume(mStream);
+}
+
+status_t StreamOutHalLocal::supportsDrain(bool *supportsDrain) {
+ *supportsDrain = mStream->drain != NULL;
+ return OK;
+}
+
+status_t StreamOutHalLocal::drain(bool earlyNotify) {
+ if (mStream->drain == NULL) return INVALID_OPERATION;
+ return mStream->drain(mStream, earlyNotify ? AUDIO_DRAIN_EARLY_NOTIFY : AUDIO_DRAIN_ALL);
+}
+
+status_t StreamOutHalLocal::flush() {
+ if (mStream->flush == NULL) return INVALID_OPERATION;
+ return mStream->flush(mStream);
+}
+
+status_t StreamOutHalLocal::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
+ if (mStream->get_presentation_position == NULL) return INVALID_OPERATION;
+ return mStream->get_presentation_position(mStream, frames, timestamp);
+}
+
+
+StreamInHalLocal::StreamInHalLocal(audio_stream_in_t *stream, sp<DeviceHalLocal> device)
+ : StreamHalLocal(&stream->common, device), mStream(stream) {
+}
+
+StreamInHalLocal::~StreamInHalLocal() {
+ mDevice->closeInputStream(mStream);
+ mStream = 0;
+}
+
+status_t StreamInHalLocal::getFrameSize(size_t *size) {
+ *size = audio_stream_in_frame_size(mStream);
+ return OK;
+}
+
+status_t StreamInHalLocal::setGain(float gain) {
+ return mStream->set_gain(mStream, gain);
+}
+
+status_t StreamInHalLocal::read(void *buffer, size_t bytes, size_t *read) {
+ ssize_t readResult = mStream->read(mStream, buffer, bytes);
+ if (readResult > 0) {
+ *read = readResult;
+ return OK;
+ } else {
+ *read = 0;
+ return readResult;
+ }
+}
+
+status_t StreamInHalLocal::getInputFramesLost(uint32_t *framesLost) {
+ *framesLost = mStream->get_input_frames_lost(mStream);
+ return OK;
+}
+
+status_t StreamInHalLocal::getCapturePosition(int64_t *frames, int64_t *time) {
+ if (mStream->get_capture_position == NULL) return INVALID_OPERATION;
+ return mStream->get_capture_position(mStream, frames, time);
+}
+
+} // namespace android
diff --git a/media/libaudiohal/StreamHalLocal.h b/media/libaudiohal/StreamHalLocal.h
new file mode 100644
index 0000000..1df18cc
--- /dev/null
+++ b/media/libaudiohal/StreamHalLocal.h
@@ -0,0 +1,163 @@
+/*
+ * 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_STREAM_HAL_LOCAL_H
+#define ANDROID_HARDWARE_STREAM_HAL_LOCAL_H
+
+#include <media/audiohal/StreamHalInterface.h>
+
+namespace android {
+
+class DeviceHalLocal;
+
+class StreamHalLocal : public virtual StreamHalInterface
+{
+ public:
+ // Return the sampling rate in Hz - eg. 44100.
+ virtual status_t getSampleRate(uint32_t *rate);
+
+ // Return size of input/output buffer in bytes for this stream - eg. 4800.
+ virtual status_t getBufferSize(size_t *size);
+
+ // Return the channel mask.
+ virtual status_t getChannelMask(audio_channel_mask_t *mask);
+
+ // Return the audio format - e.g. AUDIO_FORMAT_PCM_16_BIT.
+ virtual status_t getFormat(audio_format_t *format);
+
+ // Convenience method.
+ virtual status_t getAudioProperties(
+ uint32_t *sampleRate, audio_channel_mask_t *mask, audio_format_t *format);
+
+ // Set audio stream parameters.
+ virtual status_t setParameters(const String8& kvPairs);
+
+ // Get audio stream parameters.
+ virtual status_t getParameters(const String8& keys, String8 *values);
+
+ // Add or remove the effect on the stream.
+ virtual status_t addEffect(sp<EffectHalInterface> effect);
+ virtual status_t removeEffect(sp<EffectHalInterface> effect);
+
+ // Put the audio hardware input/output into standby mode.
+ virtual status_t standby();
+
+ virtual status_t dump(int fd);
+
+ protected:
+ // Subclasses can not be constructed directly by clients.
+ StreamHalLocal(audio_stream_t *stream, sp<DeviceHalLocal> device);
+
+ // The destructor automatically closes the stream.
+ virtual ~StreamHalLocal();
+
+ sp<DeviceHalLocal> mDevice;
+
+ private:
+ audio_stream_t *mStream;
+};
+
+class StreamOutHalLocal : public StreamOutHalInterface, public StreamHalLocal {
+ public:
+ // Return the frame size (number of bytes per sample) of a stream.
+ virtual status_t getFrameSize(size_t *size);
+
+ // Return the audio hardware driver estimated latency in milliseconds.
+ virtual status_t getLatency(uint32_t *latency);
+
+ // Use this method in situations where audio mixing is done in the hardware.
+ virtual status_t setVolume(float left, float right);
+
+ // Write audio buffer to driver.
+ virtual status_t write(const void *buffer, size_t bytes, size_t *written);
+
+ // Return the number of audio frames written by the audio dsp to DAC since
+ // the output has exited standby.
+ virtual status_t getRenderPosition(uint32_t *dspFrames);
+
+ // Get the local time at which the next write to the audio driver will be presented.
+ virtual status_t getNextWriteTimestamp(int64_t *timestamp);
+
+ // Set the callback for notifying completion of non-blocking write and drain.
+ virtual status_t setCallback(wp<StreamOutHalInterfaceCallback> callback);
+
+ // Returns whether pause and resume operations are supported.
+ virtual status_t supportsPauseAndResume(bool *supportsPause, bool *supportsResume);
+
+ // Notifies to the audio driver to resume playback following a pause.
+ virtual status_t pause();
+
+ // Notifies to the audio driver to resume playback following a pause.
+ virtual status_t resume();
+
+ // Returns whether drain operation is supported.
+ virtual status_t supportsDrain(bool *supportsDrain);
+
+ // Requests notification when data buffered by the driver/hardware has been played.
+ virtual status_t drain(bool earlyNotify);
+
+ // Notifies to the audio driver to flush the queued data.
+ virtual status_t flush();
+
+ // Return a recent count of the number of audio frames presented to an external observer.
+ virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp);
+
+ private:
+ audio_stream_out_t *mStream;
+ wp<StreamOutHalInterfaceCallback> mCallback;
+
+ friend class DeviceHalLocal;
+
+ // Can not be constructed directly by clients.
+ StreamOutHalLocal(audio_stream_out_t *stream, sp<DeviceHalLocal> device);
+
+ virtual ~StreamOutHalLocal();
+
+ static int asyncCallback(stream_callback_event_t event, void *param, void *cookie);
+};
+
+class StreamInHalLocal : public StreamInHalInterface, public StreamHalLocal {
+ public:
+ // Return the frame size (number of bytes per sample) of a stream.
+ virtual status_t getFrameSize(size_t *size);
+
+ // Set the input gain for the audio driver.
+ virtual status_t setGain(float gain);
+
+ // Read audio buffer in from driver.
+ virtual status_t read(void *buffer, size_t bytes, size_t *read);
+
+ // Return the amount of input frames lost in the audio driver.
+ virtual status_t getInputFramesLost(uint32_t *framesLost);
+
+ // Return a recent count of the number of audio frames received and
+ // the clock time associated with that frame count.
+ virtual status_t getCapturePosition(int64_t *frames, int64_t *time);
+
+ private:
+ audio_stream_in_t *mStream;
+
+ friend class DeviceHalLocal;
+
+ // Can not be constructed directly by clients.
+ StreamInHalLocal(audio_stream_in_t *stream, sp<DeviceHalLocal> device);
+
+ virtual ~StreamInHalLocal();
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_STREAM_HAL_LOCAL_H
diff --git a/media/libeffects/downmix/Android.mk b/media/libeffects/downmix/Android.mk
index e0ca8af..78601d5 100644
--- a/media/libeffects/downmix/Android.mk
+++ b/media/libeffects/downmix/Android.mk
@@ -20,5 +20,6 @@
$(call include-path-for, audio-utils)
LOCAL_CFLAGS += -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c
index 9823c55..6cbe78d 100644
--- a/media/libeffects/downmix/EffectDownmix.c
+++ b/media/libeffects/downmix/EffectDownmix.c
@@ -389,7 +389,6 @@
downmix_module_t *pDwmModule = (downmix_module_t *) self;
downmix_object_t *pDownmixer;
- int retsize;
if (pDwmModule == NULL || pDwmModule->context.state == DOWNMIX_STATE_UNINITIALIZED) {
return -EINVAL;
diff --git a/media/libeffects/loudness/Android.mk b/media/libeffects/loudness/Android.mk
index 55d0611..3db4a79 100644
--- a/media/libeffects/loudness/Android.mk
+++ b/media/libeffects/loudness/Android.mk
@@ -8,6 +8,7 @@
dsp/core/dynamic_range_compression.cpp
LOCAL_CFLAGS+= -O2 -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror
LOCAL_SHARED_LIBRARIES := \
libcutils \
diff --git a/media/libeffects/loudness/EffectLoudnessEnhancer.cpp b/media/libeffects/loudness/EffectLoudnessEnhancer.cpp
index a5a1a3f..11c6133 100644
--- a/media/libeffects/loudness/EffectLoudnessEnhancer.cpp
+++ b/media/libeffects/loudness/EffectLoudnessEnhancer.cpp
@@ -194,7 +194,6 @@
effect_handle_t *pHandle) {
ALOGV("LELib_Create()");
int ret;
- int i;
if (pHandle == NULL || uuid == NULL) {
return -EINVAL;
@@ -311,7 +310,6 @@
void *pCmdData, uint32_t *replySize, void *pReplyData) {
LoudnessEnhancerContext * pContext = (LoudnessEnhancerContext *)self;
- int retsize;
if (pContext == NULL || pContext->mState == LOUDNESS_ENHANCER_STATE_UNINITIALIZED) {
return -EINVAL;
diff --git a/media/libeffects/lvm/lib/Android.mk b/media/libeffects/lvm/lib/Android.mk
index bb56c75..afc87bb 100644
--- a/media/libeffects/lvm/lib/Android.mk
+++ b/media/libeffects/lvm/lib/Android.mk
@@ -120,6 +120,7 @@
$(LOCAL_PATH)/StereoWidening/lib
LOCAL_CFLAGS += -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror
include $(BUILD_STATIC_LIBRARY)
@@ -177,4 +178,5 @@
$(LOCAL_PATH)/Common/src
LOCAL_CFLAGS += -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror
include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libeffects/lvm/wrapper/Android.mk b/media/libeffects/lvm/wrapper/Android.mk
index 4e38e3d..9051587 100644
--- a/media/libeffects/lvm/wrapper/Android.mk
+++ b/media/libeffects/lvm/wrapper/Android.mk
@@ -10,6 +10,7 @@
Bundle/EffectBundle.cpp
LOCAL_CFLAGS += -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror
LOCAL_MODULE:= libbundlewrapper
@@ -40,6 +41,7 @@
Reverb/EffectReverb.cpp
LOCAL_CFLAGS += -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror
LOCAL_MODULE:= libreverbwrapper
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index d7b5f65..8aed146 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -501,8 +501,6 @@
//----------------------------------------------------------------------------
int LvmBundle_init(EffectContext *pContext){
- int status;
-
ALOGV("\tLvmBundle_init start");
pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
@@ -716,7 +714,6 @@
int frameCount,
EffectContext *pContext){
- LVM_ControlParams_t ActiveParams; /* Current control Parameters */
LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
LVM_INT16 *pOutTmp;
@@ -1040,7 +1037,6 @@
void LvmEffect_free(EffectContext *pContext){
LVM_ReturnStatus_en LvmStatus=LVM_SUCCESS; /* Function call status */
- LVM_ControlParams_t params; /* Control Parameters */
LVM_MemTab_t MemTab;
/* Free the algorithm memory */
@@ -2007,8 +2003,6 @@
int status = 0;
int32_t *pParamTemp = (int32_t *)pParam;
int32_t param = *pParamTemp++;
- int32_t param2;
- char *name;
//ALOGV("\tBassBoost_getParameter start");
@@ -2125,7 +2119,6 @@
int status = 0;
int32_t *pParamTemp = (int32_t *)pParam;
int32_t param = *pParamTemp++;
- char *name;
//ALOGV("\tVirtualizer_getParameter start");
@@ -2282,7 +2275,6 @@
uint32_t *pValueSize,
void *pValue){
int status = 0;
- int bMute = 0;
int32_t *pParamTemp = (int32_t *)pParam;
int32_t param = *pParamTemp++;
int32_t param2;
@@ -2540,10 +2532,8 @@
uint32_t *pValueSize,
void *pValue){
int status = 0;
- int bMute = 0;
int32_t *pParamTemp = (int32_t *)pParam;
int32_t param = *pParamTemp++;;
- char *name;
//ALOGV("\tVolume_getParameter start");
@@ -2873,11 +2863,8 @@
audio_buffer_t *inBuffer,
audio_buffer_t *outBuffer){
EffectContext * pContext = (EffectContext *) self;
- LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
int status = 0;
int processStatus = 0;
- LVM_INT16 *in = (LVM_INT16 *)inBuffer->raw;
- LVM_INT16 *out = (LVM_INT16 *)outBuffer->raw;
//ALOGV("\tEffect_process Start : Enabled = %d Called = %d (%8d %8d %8d)",
//pContext->pBundledContext->NumberEffectsEnabled,pContext->pBundledContext->NumberEffectsCalled,
@@ -3006,7 +2993,6 @@
uint32_t *replySize,
void *pReplyData){
EffectContext * pContext = (EffectContext *) self;
- int retsize;
//ALOGV("\t\nEffect_command start");
@@ -3390,7 +3376,6 @@
int16_t leftdB, rightdB;
int16_t maxdB, pandB;
int32_t vol_ret[2] = {1<<24,1<<24}; // Apply no volume
- int status = 0;
LVM_ControlParams_t ActiveParams; /* Current control Parameters */
LVM_ReturnStatus_en LvmStatus=LVM_SUCCESS; /* Function call status */
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index f7dcdda..f8b1a8e 100644
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -326,6 +326,7 @@
} \
}
+#if 0
//----------------------------------------------------------------------------
// MonoTo2I_32()
//----------------------------------------------------------------------------
@@ -384,6 +385,7 @@
return;
}
+#endif
static inline int16_t clamp16(int32_t sample)
{
@@ -559,7 +561,6 @@
void Reverb_free(ReverbContext *pContext){
LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
- LVREV_ControlParams_st params; /* Control Parameters */
LVREV_MemoryTable_st MemTab;
/* Free the algorithm memory */
@@ -708,8 +709,6 @@
//----------------------------------------------------------------------------
int Reverb_init(ReverbContext *pContext){
- int status;
-
ALOGV("\tReverb_init start");
CHECK_ARG(pContext != NULL);
@@ -1542,7 +1541,6 @@
int status = 0;
int32_t *pParamTemp = (int32_t *)pParam;
int32_t param = *pParamTemp++;
- char *name;
t_reverb_settings *pProperties;
//ALOGV("\tReverb_getParameter start");
@@ -1898,7 +1896,6 @@
uint32_t *replySize,
void *pReplyData){
android::ReverbContext * pContext = (android::ReverbContext *) self;
- int retsize;
LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
diff --git a/media/libeffects/preprocessing/Android.mk b/media/libeffects/preprocessing/Android.mk
index bd67aa1..60030ac 100644
--- a/media/libeffects/preprocessing/Android.mk
+++ b/media/libeffects/preprocessing/Android.mk
@@ -28,5 +28,6 @@
-DWEBRTC_POSIX
LOCAL_CFLAGS += -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index f48bac1..ccfd29c 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -933,7 +933,6 @@
int Session_SetConfig(preproc_session_t *session, effect_config_t *config)
{
- uint32_t sr;
uint32_t inCnl = audio_channel_count_from_in_mask(config->inputCfg.channels);
uint32_t outCnl = audio_channel_count_from_in_mask(config->outputCfg.channels);
@@ -1153,7 +1152,6 @@
preproc_session_t *PreProc_GetSession(int32_t procId, int32_t sessionId, int32_t ioId)
{
size_t i;
- int free = -1;
for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
if (sSessions[i].io == ioId) {
if (sSessions[i].createdMsk & (1 << procId)) {
@@ -1210,7 +1208,6 @@
audio_buffer_t *outBuffer)
{
preproc_effect_t * effect = (preproc_effect_t *)self;
- int status = 0;
if (effect == NULL){
ALOGV("PreProcessingFx_Process() ERROR effect == NULL");
@@ -1402,8 +1399,6 @@
void *pReplyData)
{
preproc_effect_t * effect = (preproc_effect_t *) self;
- int retsize;
- int status;
if (effect == NULL){
return -EINVAL;
@@ -1777,7 +1772,6 @@
audio_buffer_t *outBuffer __unused)
{
preproc_effect_t * effect = (preproc_effect_t *)self;
- int status = 0;
if (effect == NULL){
ALOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL");
@@ -1926,7 +1920,6 @@
int PreProcessingLib_Release(effect_handle_t interface)
{
- int status;
ALOGV("EffectRelease start %p", interface);
if (PreProc_Init() != 0) {
return sInitStatus;
diff --git a/media/libeffects/proxy/Android.mk b/media/libeffects/proxy/Android.mk
index 2ba452e..0acf1c0 100644
--- a/media/libeffects/proxy/Android.mk
+++ b/media/libeffects/proxy/Android.mk
@@ -23,6 +23,7 @@
EffectProxy.cpp
LOCAL_CFLAGS+= -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror
LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libdl libeffects
diff --git a/media/libeffects/proxy/EffectProxy.cpp b/media/libeffects/proxy/EffectProxy.cpp
index 62d3fd3..b16a98b 100644
--- a/media/libeffects/proxy/EffectProxy.cpp
+++ b/media/libeffects/proxy/EffectProxy.cpp
@@ -44,12 +44,6 @@
};
-static const effect_descriptor_t *const gDescriptors[] =
-{
- &gProxyDescriptor,
-};
-
-
int EffectProxyCreate(const effect_uuid_t *uuid,
int32_t sessionId,
int32_t ioId,
diff --git a/media/libeffects/visualizer/Android.mk b/media/libeffects/visualizer/Android.mk
index c92c543..ddcc565 100644
--- a/media/libeffects/visualizer/Android.mk
+++ b/media/libeffects/visualizer/Android.mk
@@ -7,6 +7,7 @@
EffectVisualizer.cpp
LOCAL_CFLAGS+= -O2 -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror
LOCAL_SHARED_LIBRARIES := \
libcutils \
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index 21fddb1..4c71907 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -233,7 +233,6 @@
int32_t /*ioId*/,
effect_handle_t *pHandle) {
int ret;
- int i;
if (pHandle == NULL || uuid == NULL) {
return -EINVAL;
@@ -415,7 +414,6 @@
void *pCmdData, uint32_t *replySize, void *pReplyData) {
VisualizerContext * pContext = (VisualizerContext *)self;
- int retsize;
if (pContext == NULL || pContext->mState == VISUALIZER_STATE_UNINITIALIZED) {
return -EINVAL;
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 202b5f8..0b1bb2b 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -2,7 +2,14 @@
include $(CLEAR_VARS)
+LOCAL_AIDL_INCLUDES := \
+ frameworks/av/media/libmedia/aidl
+
LOCAL_SRC_FILES:= \
+ aidl/android/IGraphicBufferSource.aidl \
+ aidl/android/IOMXBufferSource.aidl
+
+LOCAL_SRC_FILES += \
AudioTrack.cpp \
AudioTrackShared.cpp \
IAudioFlinger.cpp \
@@ -36,12 +43,15 @@
IResourceManagerClient.cpp \
IResourceManagerService.cpp \
IStreamSource.cpp \
+ MediaCodecBuffer.cpp \
MediaCodecInfo.cpp \
+ MediaDefs.cpp \
MediaUtils.cpp \
Metadata.cpp \
mediarecorder.cpp \
IMediaMetadataRetriever.cpp \
mediametadataretriever.cpp \
+ MidiDeviceInfo.cpp \
MidiIoWrapper.cpp \
ToneGenerator.cpp \
JetPlayer.cpp \
@@ -83,11 +93,15 @@
$(TOP)/frameworks/native/include/media/openmax \
$(TOP)/frameworks/av/include/media/ \
$(TOP)/frameworks/av/media/libstagefright \
+ $(TOP)/frameworks/av/media/libmedia/aidl \
$(call include-path-for, audio-effects) \
$(call include-path-for, audio-utils)
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+ frameworks/av/include/media \
+ frameworks/av/media/libmedia/aidl
+
LOCAL_CFLAGS += -Werror -Wno-error=deprecated-declarations -Wall
-LOCAL_CLANG := true
LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libmedia/ICrypto.cpp b/media/libmedia/ICrypto.cpp
index 7b261be..8ba80c6 100644
--- a/media/libmedia/ICrypto.cpp
+++ b/media/libmedia/ICrypto.cpp
@@ -302,6 +302,10 @@
int32_t offset = data.readInt32();
int32_t numSubSamples = data.readInt32();
+ if (numSubSamples < 0 || numSubSamples > 0xffff) {
+ reply->writeInt32(BAD_VALUE);
+ return OK;
+ }
CryptoPlugin::SubSample *subSamples =
new CryptoPlugin::SubSample[numSubSamples];
diff --git a/media/libmedia/IMediaCodecService.cpp b/media/libmedia/IMediaCodecService.cpp
index dcf2b27..2d62419 100644
--- a/media/libmedia/IMediaCodecService.cpp
+++ b/media/libmedia/IMediaCodecService.cpp
@@ -33,7 +33,7 @@
class BpMediaCodecService : public BpInterface<IMediaCodecService>
{
public:
- BpMediaCodecService(const sp<IBinder>& impl)
+ explicit BpMediaCodecService(const sp<IBinder>& impl)
: BpInterface<IMediaCodecService>(impl)
{
}
diff --git a/media/libmedia/IMediaDrmService.cpp b/media/libmedia/IMediaDrmService.cpp
index 9b6ecfd..84812dc 100644
--- a/media/libmedia/IMediaDrmService.cpp
+++ b/media/libmedia/IMediaDrmService.cpp
@@ -37,7 +37,7 @@
class BpMediaDrmService: public BpInterface<IMediaDrmService>
{
public:
- BpMediaDrmService(const sp<IBinder>& impl)
+ explicit BpMediaDrmService(const sp<IBinder>& impl)
: BpInterface<IMediaDrmService>(impl)
{
}
diff --git a/media/libmedia/IMediaExtractor.cpp b/media/libmedia/IMediaExtractor.cpp
index e8ad75b..eb88efd 100644
--- a/media/libmedia/IMediaExtractor.cpp
+++ b/media/libmedia/IMediaExtractor.cpp
@@ -43,7 +43,7 @@
class BpMediaExtractor : public BpInterface<IMediaExtractor> {
public:
- BpMediaExtractor(const sp<IBinder>& impl)
+ explicit BpMediaExtractor(const sp<IBinder>& impl)
: BpInterface<IMediaExtractor>(impl)
{
}
diff --git a/media/libmedia/IMediaExtractorService.cpp b/media/libmedia/IMediaExtractorService.cpp
index d170c22..8b00d85 100644
--- a/media/libmedia/IMediaExtractorService.cpp
+++ b/media/libmedia/IMediaExtractorService.cpp
@@ -33,7 +33,7 @@
class BpMediaExtractorService : public BpInterface<IMediaExtractorService>
{
public:
- BpMediaExtractorService(const sp<IBinder>& impl)
+ explicit BpMediaExtractorService(const sp<IBinder>& impl)
: BpInterface<IMediaExtractorService>(impl)
{
}
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index a6860e2..5599830 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -29,6 +29,7 @@
#include <media/IMediaRecorder.h>
#include <gui/Surface.h>
#include <gui/IGraphicBufferProducer.h>
+#include <media/stagefright/PersistentSurface.h>
namespace android {
@@ -79,12 +80,12 @@
return reply.readInt32();
}
- status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface)
+ status_t setInputSurface(const sp<PersistentSurface>& surface)
{
ALOGV("setInputSurface(%p)", surface.get());
Parcel data, reply;
data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(surface));
+ surface->writeToParcel(&data);
remote()->transact(SET_INPUT_SURFACE, data, &reply);
return reply.readInt32();
}
@@ -490,8 +491,8 @@
case SET_INPUT_SURFACE: {
ALOGV("SET_INPUT_SURFACE");
CHECK_INTERFACE(IMediaRecorder, data, reply);
- sp<IGraphicBufferConsumer> surface = interface_cast<IGraphicBufferConsumer>(
- data.readStrongBinder());
+ sp<PersistentSurface> surface = new PersistentSurface();
+ surface->readFromParcel(&data);
reply->writeInt32(setInputSurface(surface));
return NO_ERROR;
} break;
diff --git a/media/libmedia/IMediaSource.cpp b/media/libmedia/IMediaSource.cpp
index 595bad9..fdbc869 100644
--- a/media/libmedia/IMediaSource.cpp
+++ b/media/libmedia/IMediaSource.cpp
@@ -67,7 +67,7 @@
class BpMediaSource : public BpInterface<IMediaSource> {
public:
- BpMediaSource(const sp<IBinder>& impl)
+ explicit BpMediaSource(const sp<IBinder>& impl)
: BpInterface<IMediaSource>(impl), mBuffersSinceStop(0)
{
}
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index ddfb6f1..1901d8c 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -27,11 +27,14 @@
#include <media/openmax/OMX_IndexExt.h>
#include <utils/NativeHandle.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <android/IGraphicBufferSource.h>
+#include <android/IOMXBufferSource.h>
+
namespace android {
enum {
CONNECT = IBinder::FIRST_CALL_TRANSACTION,
- LIVES_LOCALLY,
LIST_NODES,
ALLOCATE_NODE,
FREE_NODE,
@@ -40,28 +43,26 @@
SET_PARAMETER,
GET_CONFIG,
SET_CONFIG,
- GET_STATE,
ENABLE_NATIVE_BUFFERS,
USE_BUFFER,
USE_GRAPHIC_BUFFER,
CREATE_INPUT_SURFACE,
- CREATE_PERSISTENT_INPUT_SURFACE,
SET_INPUT_SURFACE,
- SIGNAL_END_OF_INPUT_STREAM,
STORE_META_DATA_IN_BUFFERS,
PREPARE_FOR_ADAPTIVE_PLAYBACK,
ALLOC_SECURE_BUFFER,
- ALLOC_BUFFER_WITH_BACKUP,
FREE_BUFFER,
FILL_BUFFER,
EMPTY_BUFFER,
+ EMPTY_GRAPHIC_BUFFER,
GET_EXTENSION_INDEX,
OBSERVER_ON_MSG,
GET_GRAPHIC_BUFFER_USAGE,
- SET_INTERNAL_OPTION,
UPDATE_GRAPHIC_BUFFER_IN_META,
CONFIGURE_VIDEO_TUNNEL_MODE,
UPDATE_NATIVE_HANDLE_IN_META,
+ DISPATCH_MESSAGE,
+ SET_QUIRKS,
};
class BpOMX : public BpInterface<IOMX> {
@@ -70,16 +71,6 @@
: BpInterface<IOMX>(impl) {
}
- virtual bool livesLocally(node_id node, pid_t pid) {
- Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
- data.writeInt32(pid);
- remote()->transact(LIVES_LOCALLY, data, &reply);
-
- return reply.readInt32() != 0;
- }
-
virtual status_t listNodes(List<ComponentInfo> *list) {
list->clear();
@@ -104,8 +95,7 @@
virtual status_t allocateNode(
const char *name, const sp<IOMXObserver> &observer,
- sp<IBinder> *nodeBinder,
- node_id *node) {
+ sp<IOMXNode> *omxNode) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
data.writeCString(name);
@@ -114,31 +104,58 @@
status_t err = reply.readInt32();
if (err == OK) {
- *node = (node_id)reply.readInt32();
- if (nodeBinder != NULL) {
- *nodeBinder = remote();
- }
+ *omxNode = IOMXNode::asInterface(reply.readStrongBinder());
} else {
- *node = 0;
+ omxNode->clear();
}
return err;
}
- virtual status_t freeNode(node_id node) {
+ virtual status_t createInputSurface(
+ sp<IGraphicBufferProducer> *bufferProducer,
+ sp<IGraphicBufferSource> *bufferSource) {
Parcel data, reply;
+ status_t err;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ err = remote()->transact(CREATE_INPUT_SURFACE, data, &reply);
+ if (err != OK) {
+ ALOGW("binder transaction failed: %d", err);
+ return err;
+ }
+
+ err = reply.readInt32();
+ if (err != OK) {
+ return err;
+ }
+
+ *bufferProducer = IGraphicBufferProducer::asInterface(
+ reply.readStrongBinder());
+ *bufferSource = IGraphicBufferSource::asInterface(
+ reply.readStrongBinder());
+
+ return err;
+ }
+};
+
+class BpOMXNode : public BpInterface<IOMXNode> {
+public:
+ explicit BpOMXNode(const sp<IBinder> &impl)
+ : BpInterface<IOMXNode>(impl) {
+ }
+
+ virtual status_t freeNode() {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
remote()->transact(FREE_NODE, data, &reply);
return reply.readInt32();
}
virtual status_t sendCommand(
- node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
+ OMX_COMMANDTYPE cmd, OMX_S32 param) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
data.writeInt32(cmd);
data.writeInt32(param);
remote()->transact(SEND_COMMAND, data, &reply);
@@ -147,11 +164,10 @@
}
virtual status_t getParameter(
- node_id node, OMX_INDEXTYPE index,
+ OMX_INDEXTYPE index,
void *params, size_t size) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
data.writeInt32(index);
data.writeInt64(size);
data.write(params, size);
@@ -168,11 +184,10 @@
}
virtual status_t setParameter(
- node_id node, OMX_INDEXTYPE index,
+ OMX_INDEXTYPE index,
const void *params, size_t size) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
data.writeInt32(index);
data.writeInt64(size);
data.write(params, size);
@@ -182,11 +197,10 @@
}
virtual status_t getConfig(
- node_id node, OMX_INDEXTYPE index,
+ OMX_INDEXTYPE index,
void *params, size_t size) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
data.writeInt32(index);
data.writeInt64(size);
data.write(params, size);
@@ -203,11 +217,10 @@
}
virtual status_t setConfig(
- node_id node, OMX_INDEXTYPE index,
+ OMX_INDEXTYPE index,
const void *params, size_t size) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
data.writeInt32(index);
data.writeInt64(size);
data.write(params, size);
@@ -216,22 +229,10 @@
return reply.readInt32();
}
- virtual status_t getState(
- node_id node, OMX_STATETYPE* state) {
- Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
- remote()->transact(GET_STATE, data, &reply);
-
- *state = static_cast<OMX_STATETYPE>(reply.readInt32());
- return reply.readInt32();
- }
-
virtual status_t enableNativeBuffers(
- node_id node, OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable) {
+ OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
data.writeInt32(port_index);
data.writeInt32((uint32_t)graphic);
data.writeInt32((uint32_t)enable);
@@ -242,10 +243,9 @@
}
virtual status_t getGraphicBufferUsage(
- node_id node, OMX_U32 port_index, OMX_U32* usage) {
+ OMX_U32 port_index, OMX_U32* usage) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
data.writeInt32(port_index);
remote()->transact(GET_GRAPHIC_BUFFER_USAGE, data, &reply);
@@ -255,11 +255,10 @@
}
virtual status_t useBuffer(
- node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
+ OMX_U32 port_index, const sp<IMemory> ¶ms,
buffer_id *buffer, OMX_U32 allottedSize) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
data.writeInt32(port_index);
data.writeStrongBinder(IInterface::asBinder(params));
data.writeInt32(allottedSize);
@@ -279,11 +278,10 @@
virtual status_t useGraphicBuffer(
- node_id node, OMX_U32 port_index,
+ OMX_U32 port_index,
const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
data.writeInt32(port_index);
data.write(*graphicBuffer);
remote()->transact(USE_GRAPHIC_BUFFER, data, &reply);
@@ -301,11 +299,10 @@
}
virtual status_t updateGraphicBufferInMeta(
- node_id node, OMX_U32 port_index,
+ OMX_U32 port_index,
const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
data.writeInt32(port_index);
data.write(*graphicBuffer);
data.writeInt32((int32_t)buffer);
@@ -316,11 +313,10 @@
}
virtual status_t updateNativeHandleInMeta(
- node_id node, OMX_U32 port_index,
+ OMX_U32 port_index,
const sp<NativeHandle> &nativeHandle, buffer_id buffer) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
data.writeInt32(port_index);
data.writeInt32(nativeHandle != NULL);
if (nativeHandle != NULL) {
@@ -333,108 +329,29 @@
return err;
}
- virtual status_t createInputSurface(
- node_id node, OMX_U32 port_index, android_dataspace dataSpace,
- sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
- Parcel data, reply;
- status_t err;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
- data.writeInt32(port_index);
- data.writeInt32(dataSpace);
- err = remote()->transact(CREATE_INPUT_SURFACE, data, &reply);
- if (err != OK) {
- ALOGW("binder transaction failed: %d", err);
- return err;
- }
-
- // read type even if createInputSurface failed
- int negotiatedType = reply.readInt32();
- if (type != NULL) {
- *type = (MetadataBufferType)negotiatedType;
- }
-
- err = reply.readInt32();
- if (err != OK) {
- return err;
- }
-
- *bufferProducer = IGraphicBufferProducer::asInterface(
- reply.readStrongBinder());
-
- return err;
- }
-
- virtual status_t createPersistentInputSurface(
- sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferConsumer> *bufferConsumer) {
- Parcel data, reply;
- status_t err;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- err = remote()->transact(CREATE_PERSISTENT_INPUT_SURFACE, data, &reply);
- if (err != OK) {
- ALOGW("binder transaction failed: %d", err);
- return err;
- }
-
- err = reply.readInt32();
- if (err != OK) {
- return err;
- }
-
- *bufferProducer = IGraphicBufferProducer::asInterface(
- reply.readStrongBinder());
- *bufferConsumer = IGraphicBufferConsumer::asInterface(
- reply.readStrongBinder());
-
- return err;
- }
-
virtual status_t setInputSurface(
- node_id node, OMX_U32 port_index,
- const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type) {
+ const sp<IOMXBufferSource> &bufferSource) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- status_t err;
- data.writeInt32((int32_t)node);
- data.writeInt32(port_index);
- data.writeStrongBinder(IInterface::asBinder(bufferConsumer));
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
- err = remote()->transact(SET_INPUT_SURFACE, data, &reply);
+ data.writeStrongBinder(IInterface::asBinder(bufferSource));
+
+ status_t err = remote()->transact(SET_INPUT_SURFACE, data, &reply);
if (err != OK) {
ALOGW("binder transaction failed: %d", err);
return err;
}
- // read type even if setInputSurface failed
- int negotiatedType = reply.readInt32();
- if (type != NULL) {
- *type = (MetadataBufferType)negotiatedType;
- }
+ err = reply.readInt32();
- return reply.readInt32();
- }
-
- virtual status_t signalEndOfInputStream(node_id node) {
- Parcel data, reply;
- status_t err;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
- err = remote()->transact(SIGNAL_END_OF_INPUT_STREAM, data, &reply);
- if (err != OK) {
- ALOGW("binder transaction failed: %d", err);
- return err;
- }
-
- return reply.readInt32();
+ return err;
}
virtual status_t storeMetaDataInBuffers(
- node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
+ OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
data.writeInt32(port_index);
data.writeInt32((int32_t)enable);
data.writeInt32(type == NULL ? kMetadataBufferTypeANWBuffer : *type);
@@ -451,11 +368,10 @@
}
virtual status_t prepareForAdaptivePlayback(
- node_id node, OMX_U32 port_index, OMX_BOOL enable,
+ OMX_U32 port_index, OMX_BOOL enable,
OMX_U32 max_width, OMX_U32 max_height) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
data.writeInt32(port_index);
data.writeInt32((int32_t)enable);
data.writeInt32(max_width);
@@ -467,11 +383,10 @@
}
virtual status_t configureVideoTunnelMode(
- node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
+ OMX_U32 portIndex, OMX_BOOL tunneled,
OMX_U32 audioHwSync, native_handle_t **sidebandHandle ) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
data.writeInt32(portIndex);
data.writeInt32((int32_t)tunneled);
data.writeInt32(audioHwSync);
@@ -486,11 +401,10 @@
virtual status_t allocateSecureBuffer(
- node_id node, OMX_U32 port_index, size_t size,
+ OMX_U32 port_index, size_t size,
buffer_id *buffer, void **buffer_data, sp<NativeHandle> *native_handle) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
data.writeInt32(port_index);
data.writeInt64(size);
remote()->transact(ALLOC_SECURE_BUFFER, data, &reply);
@@ -514,34 +428,10 @@
return err;
}
- virtual status_t allocateBufferWithBackup(
- node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
- buffer_id *buffer, OMX_U32 allottedSize) {
- Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
- data.writeInt32(port_index);
- data.writeStrongBinder(IInterface::asBinder(params));
- data.writeInt32(allottedSize);
- remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply);
-
- status_t err = reply.readInt32();
- if (err != OK) {
- *buffer = 0;
-
- return err;
- }
-
- *buffer = (buffer_id)reply.readInt32();
-
- return err;
- }
-
virtual status_t freeBuffer(
- node_id node, OMX_U32 port_index, buffer_id buffer) {
+ OMX_U32 port_index, buffer_id buffer) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
data.writeInt32(port_index);
data.writeInt32((int32_t)buffer);
remote()->transact(FREE_BUFFER, data, &reply);
@@ -549,10 +439,9 @@
return reply.readInt32();
}
- virtual status_t fillBuffer(node_id node, buffer_id buffer, int fenceFd) {
+ virtual status_t fillBuffer(buffer_id buffer, int fenceFd) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
data.writeInt32((int32_t)buffer);
data.writeInt32(fenceFd >= 0);
if (fenceFd >= 0) {
@@ -564,13 +453,11 @@
}
virtual status_t emptyBuffer(
- node_id node,
buffer_id buffer,
OMX_U32 range_offset, OMX_U32 range_length,
OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
data.writeInt32((int32_t)buffer);
data.writeInt32(range_offset);
data.writeInt32(range_length);
@@ -585,13 +472,31 @@
return reply.readInt32();
}
+ virtual status_t emptyGraphicBuffer(
+ buffer_id buffer,
+ const sp<GraphicBuffer> &graphicBuffer, OMX_U32 flags,
+ OMX_TICKS timestamp, OMX_TICKS origTimestamp, int fenceFd) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
+ data.writeInt32((int32_t)buffer);
+ data.write(*graphicBuffer);
+ data.writeInt32(flags);
+ data.writeInt64(timestamp);
+ data.writeInt64(origTimestamp);
+ data.writeInt32(fenceFd >= 0);
+ if (fenceFd >= 0) {
+ data.writeFileDescriptor(fenceFd, true /* takeOwnership */);
+ }
+ remote()->transact(EMPTY_GRAPHIC_BUFFER, data, &reply);
+
+ return reply.readInt32();
+ }
+
virtual status_t getExtensionIndex(
- node_id node,
const char *parameter_name,
OMX_INDEXTYPE *index) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
data.writeCString(parameter_name);
remote()->transact(GET_EXTENSION_INDEX, data, &reply);
@@ -606,26 +511,34 @@
return err;
}
- virtual status_t setInternalOption(
- node_id node,
- OMX_U32 port_index,
- InternalOptionType type,
- const void *optionData,
- size_t size) {
+ virtual status_t dispatchMessage(const omx_message &msg) {
Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- data.writeInt32((int32_t)node);
- data.writeInt32(port_index);
- data.writeInt64(size);
- data.write(optionData, size);
- data.writeInt32(type);
- remote()->transact(SET_INTERNAL_OPTION, data, &reply);
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
+ data.writeInt32(msg.fenceFd >= 0);
+ if (msg.fenceFd >= 0) {
+ data.writeFileDescriptor(msg.fenceFd, true /* takeOwnership */);
+ }
+ data.writeInt32(msg.type);
+ data.write(&msg.u, sizeof(msg.u));
+
+ remote()->transact(DISPATCH_MESSAGE, data, &reply);
+
+ return reply.readInt32();
+ }
+
+ virtual status_t setQuirks(OMX_U32 quirks) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
+ data.writeInt32(quirks);
+
+ remote()->transact(SET_QUIRKS, data, &reply);
return reply.readInt32();
}
};
IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX");
+IMPLEMENT_META_INTERFACE(OMXNode, "android.hardware.IOMXNode");
////////////////////////////////////////////////////////////////////////////////
@@ -638,16 +551,6 @@
status_t BnOMX::onTransact(
uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
switch (code) {
- case LIVES_LOCALLY:
- {
- CHECK_OMX_INTERFACE(IOMX, data, reply);
- node_id node = (node_id)data.readInt32();
- pid_t pid = (pid_t)data.readInt32();
- reply->writeInt32(livesLocally(node, pid));
-
- return OK;
- }
-
case LIST_NODES:
{
CHECK_OMX_INTERFACE(IOMX, data, reply);
@@ -686,40 +589,62 @@
return NO_ERROR;
}
- node_id node;
+ sp<IOMXNode> omxNode;
- status_t err = allocateNode(name, observer,
- NULL /* nodeBinder */, &node);
+ status_t err = allocateNode(name, observer, &omxNode);
+
reply->writeInt32(err);
if (err == OK) {
- reply->writeInt32((int32_t)node);
+ reply->writeStrongBinder(IInterface::asBinder(omxNode));
}
return NO_ERROR;
}
- case FREE_NODE:
+ case CREATE_INPUT_SURFACE:
{
CHECK_OMX_INTERFACE(IOMX, data, reply);
- node_id node = (node_id)data.readInt32();
+ sp<IGraphicBufferProducer> bufferProducer;
+ sp<IGraphicBufferSource> bufferSource;
+ status_t err = createInputSurface(&bufferProducer, &bufferSource);
- reply->writeInt32(freeNode(node));
+ reply->writeInt32(err);
+
+ if (err == OK) {
+ reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
+ reply->writeStrongBinder(IInterface::asBinder(bufferSource));
+ }
+
+ return NO_ERROR;
+ }
+
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+status_t BnOMXNode::onTransact(
+ uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
+ switch (code) {
+ case FREE_NODE:
+ {
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
+
+ reply->writeInt32(freeNode());
return NO_ERROR;
}
case SEND_COMMAND:
{
- CHECK_OMX_INTERFACE(IOMX, data, reply);
-
- node_id node = (node_id)data.readInt32();
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
OMX_COMMANDTYPE cmd =
static_cast<OMX_COMMANDTYPE>(data.readInt32());
OMX_S32 param = data.readInt32();
- reply->writeInt32(sendCommand(node, cmd, param));
+ reply->writeInt32(sendCommand(cmd, param));
return NO_ERROR;
}
@@ -728,11 +653,9 @@
case SET_PARAMETER:
case GET_CONFIG:
case SET_CONFIG:
- case SET_INTERNAL_OPTION:
{
- CHECK_OMX_INTERFACE(IOMX, data, reply);
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
- node_id node = (node_id)data.readInt32();
OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
size_t size = data.readInt64();
@@ -742,8 +665,7 @@
size_t pageSize = 0;
size_t allocSize = 0;
bool isUsageBits = (index == (OMX_INDEXTYPE) OMX_IndexParamConsumerUsageBits);
- if ((isUsageBits && size < 4) ||
- (!isUsageBits && code != SET_INTERNAL_OPTION && size < 8)) {
+ if ((isUsageBits && size < 4) || (!isUsageBits && size < 8)) {
// we expect the structure to contain at least the size and
// version, 8 bytes total
ALOGE("b/27207275 (%zu) (%d/%d)", size, int(index), int(code));
@@ -765,8 +687,7 @@
} else {
err = NOT_ENOUGH_DATA;
OMX_U32 declaredSize = *(OMX_U32*)params;
- if (code != SET_INTERNAL_OPTION &&
- index != (OMX_INDEXTYPE) OMX_IndexParamConsumerUsageBits &&
+ if (index != (OMX_INDEXTYPE) OMX_IndexParamConsumerUsageBits &&
declaredSize > size) {
// the buffer says it's bigger than it actually is
ALOGE("b/27207275 (%u/%zu)", declaredSize, size);
@@ -781,26 +702,17 @@
} else {
switch (code) {
case GET_PARAMETER:
- err = getParameter(node, index, params, size);
+ err = getParameter(index, params, size);
break;
case SET_PARAMETER:
- err = setParameter(node, index, params, size);
+ err = setParameter(index, params, size);
break;
case GET_CONFIG:
- err = getConfig(node, index, params, size);
+ err = getConfig(index, params, size);
break;
case SET_CONFIG:
- err = setConfig(node, index, params, size);
+ err = setConfig(index, params, size);
break;
- case SET_INTERNAL_OPTION:
- {
- InternalOptionType type =
- (InternalOptionType)data.readInt32();
-
- err = setInternalOption(node, index, type, params, size);
- break;
- }
-
default:
TRESPASS();
}
@@ -826,30 +738,15 @@
return NO_ERROR;
}
- case GET_STATE:
- {
- CHECK_OMX_INTERFACE(IOMX, data, reply);
-
- node_id node = (node_id)data.readInt32();
- OMX_STATETYPE state = OMX_StateInvalid;
-
- status_t err = getState(node, &state);
- reply->writeInt32(state);
- reply->writeInt32(err);
-
- return NO_ERROR;
- }
-
case ENABLE_NATIVE_BUFFERS:
{
- CHECK_OMX_INTERFACE(IOMX, data, reply);
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
- node_id node = (node_id)data.readInt32();
OMX_U32 port_index = data.readInt32();
OMX_BOOL graphic = (OMX_BOOL)data.readInt32();
OMX_BOOL enable = (OMX_BOOL)data.readInt32();
- status_t err = enableNativeBuffers(node, port_index, graphic, enable);
+ status_t err = enableNativeBuffers(port_index, graphic, enable);
reply->writeInt32(err);
return NO_ERROR;
@@ -857,13 +754,12 @@
case GET_GRAPHIC_BUFFER_USAGE:
{
- CHECK_OMX_INTERFACE(IOMX, data, reply);
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
- node_id node = (node_id)data.readInt32();
OMX_U32 port_index = data.readInt32();
OMX_U32 usage = 0;
- status_t err = getGraphicBufferUsage(node, port_index, &usage);
+ status_t err = getGraphicBufferUsage(port_index, &usage);
reply->writeInt32(err);
reply->writeInt32(usage);
@@ -872,9 +768,8 @@
case USE_BUFFER:
{
- CHECK_OMX_INTERFACE(IOMX, data, reply);
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
- node_id node = (node_id)data.readInt32();
OMX_U32 port_index = data.readInt32();
sp<IMemory> params =
interface_cast<IMemory>(data.readStrongBinder());
@@ -887,7 +782,7 @@
}
buffer_id buffer;
- status_t err = useBuffer(node, port_index, params, &buffer, allottedSize);
+ status_t err = useBuffer(port_index, params, &buffer, allottedSize);
reply->writeInt32(err);
if (err == OK) {
@@ -899,16 +794,15 @@
case USE_GRAPHIC_BUFFER:
{
- CHECK_OMX_INTERFACE(IOMX, data, reply);
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
- node_id node = (node_id)data.readInt32();
OMX_U32 port_index = data.readInt32();
sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
data.read(*graphicBuffer);
buffer_id buffer;
status_t err = useGraphicBuffer(
- node, port_index, graphicBuffer, &buffer);
+ port_index, graphicBuffer, &buffer);
reply->writeInt32(err);
if (err == OK) {
@@ -920,16 +814,15 @@
case UPDATE_GRAPHIC_BUFFER_IN_META:
{
- CHECK_OMX_INTERFACE(IOMX, data, reply);
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
- node_id node = (node_id)data.readInt32();
OMX_U32 port_index = data.readInt32();
sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
data.read(*graphicBuffer);
buffer_id buffer = (buffer_id)data.readInt32();
status_t err = updateGraphicBufferInMeta(
- node, port_index, graphicBuffer, buffer);
+ port_index, graphicBuffer, buffer);
reply->writeInt32(err);
return NO_ERROR;
@@ -937,9 +830,8 @@
case UPDATE_NATIVE_HANDLE_IN_META:
{
- CHECK_OMX_INTERFACE(IOMX, data, reply);
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
- node_id node = (node_id)data.readInt32();
OMX_U32 port_index = data.readInt32();
native_handle *handle = NULL;
if (data.readInt32()) {
@@ -948,92 +840,20 @@
buffer_id buffer = (buffer_id)data.readInt32();
status_t err = updateNativeHandleInMeta(
- node, port_index, NativeHandle::create(handle, true /* ownshandle */), buffer);
+ port_index, NativeHandle::create(handle, true /* ownshandle */), buffer);
reply->writeInt32(err);
return NO_ERROR;
}
- case CREATE_INPUT_SURFACE:
- {
- CHECK_OMX_INTERFACE(IOMX, data, reply);
-
- node_id node = (node_id)data.readInt32();
- OMX_U32 port_index = data.readInt32();
- android_dataspace dataSpace = (android_dataspace)data.readInt32();
-
- sp<IGraphicBufferProducer> bufferProducer;
- MetadataBufferType type = kMetadataBufferTypeInvalid;
- status_t err = createInputSurface(node, port_index, dataSpace, &bufferProducer, &type);
-
- if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
- android_errorWriteLog(0x534e4554, "26324358");
- }
-
- reply->writeInt32(type);
- reply->writeInt32(err);
-
- if (err == OK) {
- reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
- }
-
- return NO_ERROR;
- }
-
- case CREATE_PERSISTENT_INPUT_SURFACE:
- {
- CHECK_OMX_INTERFACE(IOMX, data, reply);
-
- sp<IGraphicBufferProducer> bufferProducer;
- sp<IGraphicBufferConsumer> bufferConsumer;
- status_t err = createPersistentInputSurface(
- &bufferProducer, &bufferConsumer);
-
- reply->writeInt32(err);
-
- if (err == OK) {
- reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
- reply->writeStrongBinder(IInterface::asBinder(bufferConsumer));
- }
-
- return NO_ERROR;
- }
-
case SET_INPUT_SURFACE:
{
- CHECK_OMX_INTERFACE(IOMX, data, reply);
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
- node_id node = (node_id)data.readInt32();
- OMX_U32 port_index = data.readInt32();
+ sp<IOMXBufferSource> bufferSource =
+ interface_cast<IOMXBufferSource>(data.readStrongBinder());
- sp<IGraphicBufferConsumer> bufferConsumer =
- interface_cast<IGraphicBufferConsumer>(data.readStrongBinder());
-
- MetadataBufferType type = kMetadataBufferTypeInvalid;
-
- status_t err = INVALID_OPERATION;
- if (bufferConsumer == NULL) {
- ALOGE("b/26392700");
- } else {
- err = setInputSurface(node, port_index, bufferConsumer, &type);
-
- if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
- android_errorWriteLog(0x534e4554, "26324358");
- }
- }
-
- reply->writeInt32(type);
- reply->writeInt32(err);
- return NO_ERROR;
- }
-
- case SIGNAL_END_OF_INPUT_STREAM:
- {
- CHECK_OMX_INTERFACE(IOMX, data, reply);
-
- node_id node = (node_id)data.readInt32();
-
- status_t err = signalEndOfInputStream(node);
+ status_t err = setInputSurface(bufferSource);
reply->writeInt32(err);
return NO_ERROR;
@@ -1041,14 +861,13 @@
case STORE_META_DATA_IN_BUFFERS:
{
- CHECK_OMX_INTERFACE(IOMX, data, reply);
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
- node_id node = (node_id)data.readInt32();
OMX_U32 port_index = data.readInt32();
OMX_BOOL enable = (OMX_BOOL)data.readInt32();
MetadataBufferType type = (MetadataBufferType)data.readInt32();
- status_t err = storeMetaDataInBuffers(node, port_index, enable, &type);
+ status_t err = storeMetaDataInBuffers(port_index, enable, &type);
reply->writeInt32(type);
reply->writeInt32(err);
@@ -1058,16 +877,15 @@
case PREPARE_FOR_ADAPTIVE_PLAYBACK:
{
- CHECK_OMX_INTERFACE(IOMX, data, reply);
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
- node_id node = (node_id)data.readInt32();
OMX_U32 port_index = data.readInt32();
OMX_BOOL enable = (OMX_BOOL)data.readInt32();
OMX_U32 max_width = data.readInt32();
OMX_U32 max_height = data.readInt32();
status_t err = prepareForAdaptivePlayback(
- node, port_index, enable, max_width, max_height);
+ port_index, enable, max_width, max_height);
reply->writeInt32(err);
return NO_ERROR;
@@ -1075,16 +893,15 @@
case CONFIGURE_VIDEO_TUNNEL_MODE:
{
- CHECK_OMX_INTERFACE(IOMX, data, reply);
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
- node_id node = (node_id)data.readInt32();
OMX_U32 port_index = data.readInt32();
OMX_BOOL tunneled = (OMX_BOOL)data.readInt32();
OMX_U32 audio_hw_sync = data.readInt32();
native_handle_t *sideband_handle = NULL;
status_t err = configureVideoTunnelMode(
- node, port_index, tunneled, audio_hw_sync, &sideband_handle);
+ port_index, tunneled, audio_hw_sync, &sideband_handle);
reply->writeInt32(err);
if(err == OK){
reply->writeNativeHandle(sideband_handle);
@@ -1095,11 +912,10 @@
case ALLOC_SECURE_BUFFER:
{
- CHECK_OMX_INTERFACE(IOMX, data, reply);
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
- node_id node = (node_id)data.readInt32();
OMX_U32 port_index = data.readInt32();
- if (!isSecure(node) || port_index != 0 /* kPortIndexInput */) {
+ if (!isSecure() || port_index != 0 /* kPortIndexInput */) {
ALOGE("b/24310423");
reply->writeInt32(INVALID_OPERATION);
return NO_ERROR;
@@ -1111,7 +927,7 @@
void *buffer_data = NULL;
sp<NativeHandle> native_handle;
status_t err = allocateSecureBuffer(
- node, port_index, size, &buffer, &buffer_data, &native_handle);
+ port_index, size, &buffer, &buffer_data, &native_handle);
reply->writeInt32(err);
if (err == OK) {
@@ -1125,65 +941,33 @@
return NO_ERROR;
}
- case ALLOC_BUFFER_WITH_BACKUP:
- {
- CHECK_OMX_INTERFACE(IOMX, data, reply);
-
- node_id node = (node_id)data.readInt32();
- OMX_U32 port_index = data.readInt32();
- sp<IMemory> params =
- interface_cast<IMemory>(data.readStrongBinder());
- OMX_U32 allottedSize = data.readInt32();
-
- if (params == NULL) {
- ALOGE("b/26392700");
- reply->writeInt32(INVALID_OPERATION);
- return NO_ERROR;
- }
-
- buffer_id buffer;
- status_t err = allocateBufferWithBackup(
- node, port_index, params, &buffer, allottedSize);
-
- reply->writeInt32(err);
-
- if (err == OK) {
- reply->writeInt32((int32_t)buffer);
- }
-
- return NO_ERROR;
- }
-
case FREE_BUFFER:
{
- CHECK_OMX_INTERFACE(IOMX, data, reply);
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
- node_id node = (node_id)data.readInt32();
OMX_U32 port_index = data.readInt32();
buffer_id buffer = (buffer_id)data.readInt32();
- reply->writeInt32(freeBuffer(node, port_index, buffer));
+ reply->writeInt32(freeBuffer(port_index, buffer));
return NO_ERROR;
}
case FILL_BUFFER:
{
- CHECK_OMX_INTERFACE(IOMX, data, reply);
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
- node_id node = (node_id)data.readInt32();
buffer_id buffer = (buffer_id)data.readInt32();
bool haveFence = data.readInt32();
int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
- reply->writeInt32(fillBuffer(node, buffer, fenceFd));
+ reply->writeInt32(fillBuffer(buffer, fenceFd));
return NO_ERROR;
}
case EMPTY_BUFFER:
{
- CHECK_OMX_INTERFACE(IOMX, data, reply);
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
- node_id node = (node_id)data.readInt32();
buffer_id buffer = (buffer_id)data.readInt32();
OMX_U32 range_offset = data.readInt32();
OMX_U32 range_length = data.readInt32();
@@ -1192,16 +976,34 @@
bool haveFence = data.readInt32();
int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
reply->writeInt32(emptyBuffer(
- node, buffer, range_offset, range_length, flags, timestamp, fenceFd));
+ buffer, range_offset, range_length, flags, timestamp, fenceFd));
+
+ return NO_ERROR;
+ }
+
+ case EMPTY_GRAPHIC_BUFFER:
+ {
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
+
+ buffer_id buffer = (buffer_id)data.readInt32();
+ sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
+ data.read(*graphicBuffer);
+ OMX_U32 flags = data.readInt32();
+ OMX_TICKS timestamp = data.readInt64();
+ OMX_TICKS origTimestamp = data.readInt64();
+ bool haveFence = data.readInt32();
+ int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
+ reply->writeInt32(emptyGraphicBuffer(
+ buffer, graphicBuffer, flags,
+ timestamp, origTimestamp, fenceFd));
return NO_ERROR;
}
case GET_EXTENSION_INDEX:
{
- CHECK_OMX_INTERFACE(IOMX, data, reply);
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
- node_id node = (node_id)data.readInt32();
const char *parameter_name = data.readCString();
if (parameter_name == NULL) {
@@ -1211,7 +1013,7 @@
}
OMX_INDEXTYPE index;
- status_t err = getExtensionIndex(node, parameter_name, &index);
+ status_t err = getExtensionIndex(parameter_name, &index);
reply->writeInt32(err);
@@ -1222,6 +1024,34 @@
return OK;
}
+ case DISPATCH_MESSAGE:
+ {
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
+ omx_message msg;
+ int haveFence = data.readInt32();
+ msg.fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
+ msg.type = (typeof(msg.type))data.readInt32();
+ status_t err = data.read(&msg.u, sizeof(msg.u));
+
+ if (err == OK) {
+ err = dispatchMessage(msg);
+ }
+ reply->writeInt32(err);
+
+ return NO_ERROR;
+ }
+
+ case SET_QUIRKS:
+ {
+ CHECK_OMX_INTERFACE(IOMXNode, data, reply);
+
+ OMX_U32 quirks = data.readInt32();
+
+ reply->writeInt32(setQuirks(quirks));
+
+ return NO_ERROR;
+ }
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
@@ -1238,14 +1068,12 @@
virtual void onMessages(const std::list<omx_message> &messages) {
Parcel data, reply;
std::list<omx_message>::const_iterator it = messages.cbegin();
- bool first = true;
+ if (messages.empty()) {
+ return;
+ }
+ data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor());
while (it != messages.cend()) {
const omx_message &msg = *it++;
- if (first) {
- data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor());
- data.writeInt32(msg.node);
- first = false;
- }
data.writeInt32(msg.fenceFd >= 0);
if (msg.fenceFd >= 0) {
data.writeFileDescriptor(msg.fenceFd, true /* takeOwnership */);
@@ -1254,10 +1082,8 @@
data.write(&msg.u, sizeof(msg.u));
ALOGV("onMessage writing message %d, size %zu", msg.type, sizeof(msg));
}
- if (!first) {
- data.writeInt32(-1); // mark end
- remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY);
- }
+ data.writeInt32(-1); // mark end
+ remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY);
}
};
@@ -1269,7 +1095,6 @@
case OBSERVER_ON_MSG:
{
CHECK_OMX_INTERFACE(IOMXObserver, data, reply);
- IOMX::node_id node = data.readInt32();
std::list<omx_message> messages;
status_t err = FAILED_TRANSACTION; // must receive at least one message
do {
@@ -1278,7 +1103,6 @@
break;
}
omx_message msg;
- msg.node = node;
msg.fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
msg.type = (typeof(msg.type))data.readInt32();
err = data.read(&msg.u, sizeof(msg.u));
diff --git a/media/libmedia/MediaCodecBuffer.cpp b/media/libmedia/MediaCodecBuffer.cpp
new file mode 100644
index 0000000..2d255be
--- /dev/null
+++ b/media/libmedia/MediaCodecBuffer.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaCodecBuffer"
+#include <utils/Log.h>
+
+#include <media/MediaCodecBuffer.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/MediaBufferBase.h>
+
+namespace android {
+
+MediaCodecBuffer::MediaCodecBuffer(const sp<AMessage> &format, const sp<ABuffer> &buffer)
+ : mMeta(new AMessage),
+ mFormat(format),
+ mBuffer(buffer),
+ mMediaBufferBase(nullptr) {
+}
+
+// ABuffer-like interface
+uint8_t *MediaCodecBuffer::base() {
+ return mBuffer->base();
+}
+
+uint8_t *MediaCodecBuffer::data() {
+ return mBuffer->data();
+}
+
+size_t MediaCodecBuffer::capacity() const {
+ return mBuffer->capacity();
+}
+
+size_t MediaCodecBuffer::size() const {
+ return mBuffer->size();
+}
+
+size_t MediaCodecBuffer::offset() const {
+ return mBuffer->offset();
+}
+
+status_t MediaCodecBuffer::setRange(size_t offset, size_t size) {
+ mBuffer->setRange(offset, size);
+ return OK;
+}
+
+MediaBufferBase *MediaCodecBuffer::getMediaBufferBase() {
+ if (mMediaBufferBase != NULL) {
+ mMediaBufferBase->add_ref();
+ }
+ return mMediaBufferBase;
+}
+
+void MediaCodecBuffer::setMediaBufferBase(MediaBufferBase *mediaBuffer) {
+ if (mMediaBufferBase != NULL) {
+ mMediaBufferBase->release();
+ }
+ mMediaBufferBase = mediaBuffer;
+}
+
+sp<AMessage> MediaCodecBuffer::meta() {
+ return mMeta;
+}
+
+sp<AMessage> MediaCodecBuffer::format() {
+ return mFormat;
+}
+
+} // namespace android
diff --git a/media/libmedia/MediaCodecInfo.cpp b/media/libmedia/MediaCodecInfo.cpp
index 1b3b3eb..62a7bdf 100644
--- a/media/libmedia/MediaCodecInfo.cpp
+++ b/media/libmedia/MediaCodecInfo.cpp
@@ -121,9 +121,11 @@
}
bool MediaCodecInfo::hasQuirk(const char *name) const {
- for (size_t ix = 0; ix < mQuirks.size(); ix++) {
- if (mQuirks.itemAt(ix).equalsIgnoreCase(name)) {
- return true;
+ if (name) {
+ for (size_t ix = 0; ix < mQuirks.size(); ix++) {
+ if (mQuirks.itemAt(ix).equalsIgnoreCase(name)) {
+ return true;
+ }
}
}
return false;
@@ -190,9 +192,11 @@
}
ssize_t MediaCodecInfo::getCapabilityIndex(const char *mime) const {
- for (size_t ix = 0; ix < mCaps.size(); ix++) {
- if (mCaps.keyAt(ix).equalsIgnoreCase(mime)) {
- return ix;
+ if (mime) {
+ for (size_t ix = 0; ix < mCaps.size(); ix++) {
+ if (mCaps.keyAt(ix).equalsIgnoreCase(mime)) {
+ return ix;
+ }
}
}
return -1;
diff --git a/media/libstagefright/MediaDefs.cpp b/media/libmedia/MediaDefs.cpp
similarity index 98%
rename from media/libstagefright/MediaDefs.cpp
rename to media/libmedia/MediaDefs.cpp
index 845462b..a2110c9 100644
--- a/media/libstagefright/MediaDefs.cpp
+++ b/media/libmedia/MediaDefs.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <media/stagefright/MediaDefs.h>
+#include <media/MediaDefs.h>
namespace android {
diff --git a/media/libmedia/MidiDeviceInfo.cpp b/media/libmedia/MidiDeviceInfo.cpp
new file mode 100644
index 0000000..02efc5f
--- /dev/null
+++ b/media/libmedia/MidiDeviceInfo.cpp
@@ -0,0 +1,138 @@
+/*
+ * 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 "MidiDeviceInfo"
+
+#include "MidiDeviceInfo.h"
+
+#include <binder/Parcel.h>
+#include <log/log.h>
+#include <utils/Errors.h>
+#include <utils/String16.h>
+
+namespace android {
+namespace media {
+namespace midi {
+
+// The constant values need to be kept in sync with MidiDeviceInfo.java.
+// static
+const char* const MidiDeviceInfo::PROPERTY_NAME = "name";
+const char* const MidiDeviceInfo::PROPERTY_MANUFACTURER = "manufacturer";
+const char* const MidiDeviceInfo::PROPERTY_PRODUCT = "product";
+const char* const MidiDeviceInfo::PROPERTY_VERSION = "version";
+const char* const MidiDeviceInfo::PROPERTY_SERIAL_NUMBER = "serial_number";
+const char* const MidiDeviceInfo::PROPERTY_ALSA_CARD = "alsa_card";
+const char* const MidiDeviceInfo::PROPERTY_ALSA_DEVICE = "alsa_device";
+
+String16 MidiDeviceInfo::getProperty(const char* propertyName) {
+ String16 value;
+ if (mProperties.getString(String16(propertyName), &value)) {
+ return value;
+ } else {
+ return String16();
+ }
+}
+
+#define RETURN_IF_FAILED(calledOnce) \
+ { \
+ status_t returnStatus = calledOnce; \
+ if (returnStatus) { \
+ ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
+ return returnStatus; \
+ } \
+ }
+
+status_t MidiDeviceInfo::writeToParcel(Parcel* parcel) const {
+ // Needs to be kept in sync with code in MidiDeviceInfo.java
+ RETURN_IF_FAILED(parcel->writeInt32(mType));
+ RETURN_IF_FAILED(parcel->writeInt32(mId));
+ RETURN_IF_FAILED(parcel->writeInt32((int32_t)mInputPortNames.size()));
+ RETURN_IF_FAILED(parcel->writeInt32((int32_t)mOutputPortNames.size()));
+ RETURN_IF_FAILED(writeStringVector(parcel, mInputPortNames));
+ RETURN_IF_FAILED(writeStringVector(parcel, mOutputPortNames));
+ RETURN_IF_FAILED(parcel->writeInt32(mIsPrivate ? 1 : 0));
+ RETURN_IF_FAILED(mProperties.writeToParcel(parcel));
+ // This corresponds to "extra" properties written by Java code
+ RETURN_IF_FAILED(mProperties.writeToParcel(parcel));
+ return OK;
+}
+
+status_t MidiDeviceInfo::readFromParcel(const Parcel* parcel) {
+ // Needs to be kept in sync with code in MidiDeviceInfo.java
+ RETURN_IF_FAILED(parcel->readInt32(&mType));
+ RETURN_IF_FAILED(parcel->readInt32(&mId));
+ int32_t inputPortCount;
+ RETURN_IF_FAILED(parcel->readInt32(&inputPortCount));
+ int32_t outputPortCount;
+ RETURN_IF_FAILED(parcel->readInt32(&outputPortCount));
+ RETURN_IF_FAILED(readStringVector(parcel, &mInputPortNames, inputPortCount));
+ RETURN_IF_FAILED(readStringVector(parcel, &mOutputPortNames, outputPortCount));
+ int32_t isPrivate;
+ RETURN_IF_FAILED(parcel->readInt32(&isPrivate));
+ mIsPrivate = isPrivate == 1;
+ RETURN_IF_FAILED(mProperties.readFromParcel(parcel));
+ // Ignore "extra" properties as they may contain Java Parcelables
+ return OK;
+}
+
+status_t MidiDeviceInfo::readStringVector(
+ const Parcel* parcel, Vector<String16> *vectorPtr, size_t defaultLength) {
+ std::unique_ptr<std::vector<std::unique_ptr<String16>>> v;
+ status_t result = parcel->readString16Vector(&v);
+ if (result != OK) return result;
+ vectorPtr->clear();
+ if (v.get() != nullptr) {
+ for (const auto& iter : *v) {
+ if (iter.get() != nullptr) {
+ vectorPtr->push_back(*iter);
+ } else {
+ vectorPtr->push_back(String16());
+ }
+ }
+ } else {
+ vectorPtr->resize(defaultLength);
+ }
+ return OK;
+}
+
+status_t MidiDeviceInfo::writeStringVector(Parcel* parcel, const Vector<String16>& vector) const {
+ std::vector<String16> v;
+ for (size_t i = 0; i < vector.size(); ++i) {
+ v.push_back(vector[i]);
+ }
+ return parcel->writeString16Vector(v);
+}
+
+// Vector does not define operator==
+static inline bool areVectorsEqual(const Vector<String16>& lhs, const Vector<String16>& rhs) {
+ if (lhs.size() != rhs.size()) return false;
+ for (size_t i = 0; i < lhs.size(); ++i) {
+ if (lhs[i] != rhs[i]) return false;
+ }
+ return true;
+}
+
+bool operator==(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs) {
+ return (lhs.mType == rhs.mType && lhs.mId == rhs.mId &&
+ areVectorsEqual(lhs.mInputPortNames, rhs.mInputPortNames) &&
+ areVectorsEqual(lhs.mOutputPortNames, rhs.mOutputPortNames) &&
+ lhs.mProperties == rhs.mProperties &&
+ lhs.mIsPrivate == rhs.mIsPrivate);
+}
+
+} // namespace midi
+} // namespace media
+} // namespace android
diff --git a/media/libmedia/aidl/android/IGraphicBufferSource.aidl b/media/libmedia/aidl/android/IGraphicBufferSource.aidl
new file mode 100644
index 0000000..e9bf739
--- /dev/null
+++ b/media/libmedia/aidl/android/IGraphicBufferSource.aidl
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package android;
+
+import android.IOMXNode;
+
+/**
+ * Binder interface for controlling a graphic buffer source.
+ *
+ * @hide
+ */
+interface IGraphicBufferSource {
+ void configure(IOMXNode omxNode, int dataSpace);
+ void setSuspend(boolean suspend);
+ void setRepeatPreviousFrameDelayUs(long repeatAfterUs);
+ void setMaxTimestampGapUs(long maxGapUs);
+ void setMaxFps(float maxFps);
+ void setTimeLapseConfig(long timePerFrameUs, long timePerCaptureUs);
+ void setStartTimeUs(long startTimeUs);
+ void setColorAspects(int aspects);
+ void setTimeOffsetUs(long timeOffsetsUs);
+ void signalEndOfInputStream();
+}
\ No newline at end of file
diff --git a/media/libmedia/aidl/android/IOMXBufferSource.aidl b/media/libmedia/aidl/android/IOMXBufferSource.aidl
new file mode 100644
index 0000000..a5bf448
--- /dev/null
+++ b/media/libmedia/aidl/android/IOMXBufferSource.aidl
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+package android;
+
+import android.OMXFenceParcelable;
+
+/**
+ * Binder interface for a buffer source to be used together with an OMX encoder
+ *
+ * @hide
+ */
+interface IOMXBufferSource {
+ /**
+ * This is called when OMX transitions to OMX_StateExecuting, which means
+ * we can start handing it buffers. If we already have buffers of data
+ * sitting in the BufferQueue, this will send them to the codec.
+ */
+ void onOmxExecuting();
+
+ /**
+ * This is called when OMX transitions to OMX_StateIdle, indicating that
+ * the codec is meant to return all buffers back to the client for them
+ * to be freed. Do NOT submit any more buffers to the component.
+ */
+ void onOmxIdle();
+
+ /**
+ * This is called when OMX transitions to OMX_StateLoaded, indicating that
+ * we are shutting down.
+ */
+ void onOmxLoaded();
+
+ /**
+ * A "codec buffer", i.e. a buffer that can be used to pass data into
+ * the encoder, has been allocated.
+ */
+ void onInputBufferAdded(int bufferID);
+
+ /**
+ * Called from OnEmptyBufferDone. If we have a BQ buffer available,
+ * fill it with a new frame of data; otherwise, just mark it as available.
+ *
+ * fenceParcel contains the fence's fd that the callee should wait on before
+ * using the buffer (or pass on to the user of the buffer, if the user supports
+ * fences). Callee takes ownership of the fence fd even if it fails.
+ */
+ void onInputBufferEmptied(int bufferID, in OMXFenceParcelable fenceParcel);
+}
\ No newline at end of file
diff --git a/media/libmedia/aidl/android/IOMXNode.aidl b/media/libmedia/aidl/android/IOMXNode.aidl
new file mode 100644
index 0000000..ec87fd2
--- /dev/null
+++ b/media/libmedia/aidl/android/IOMXNode.aidl
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+package android;
+
+/** @hide */
+interface IOMXNode {
+ // Stub for manual implementation
+}
diff --git a/media/libmedia/aidl/android/IOMXNode.h b/media/libmedia/aidl/android/IOMXNode.h
new file mode 100644
index 0000000..7b17614
--- /dev/null
+++ b/media/libmedia/aidl/android/IOMXNode.h
@@ -0,0 +1,17 @@
+/*
+ * 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.
+ */
+
+#include <media/IOMX.h>
diff --git a/media/libmedia/aidl/android/OMXFenceParcelable.aidl b/media/libmedia/aidl/android/OMXFenceParcelable.aidl
new file mode 100644
index 0000000..6d517e8
--- /dev/null
+++ b/media/libmedia/aidl/android/OMXFenceParcelable.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+package android;
+
+/** @hide */
+parcelable OMXFenceParcelable cpp_header "media/OMXFenceParcelable.h";
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 59c077a..6eb208c 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -361,7 +361,7 @@
return INVALID_OPERATION;
}
- return mMediaRecorder->setInputSurface(surface->getBufferConsumer());
+ return mMediaRecorder->setInputSurface(surface);
}
status_t MediaRecorder::setVideoFrameRate(int frames_per_second)
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index 98ccc42..5270dea 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -57,7 +57,6 @@
$(TOP)/external/tremolo/Tremolo \
LOCAL_CFLAGS += -Werror -Wno-error=deprecated-declarations -Wall
-LOCAL_CLANG := true
LOCAL_MODULE:= libmediaplayerservice
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 95c91d1..d45dbcd 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -684,10 +684,18 @@
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("media.extractor"));
+ if (binder == NULL) {
+ ALOGE("extractor service not available");
+ return NULL;
+ }
mExtractorDeathListener = new ServiceDeathNotifier(binder, p, MEDIAEXTRACTOR_PROCESS_DEATH);
binder->linkToDeath(mExtractorDeathListener);
binder = sm->getService(String16("media.codec"));
+ if (binder == NULL) {
+ ALOGE("codec service not available");
+ return NULL;
+ }
mCodecDeathListener = new ServiceDeathNotifier(binder, p, MEDIACODEC_PROCESS_DEATH);
binder->linkToDeath(mCodecDeathListener);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index d011d70..94ceae4 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -52,7 +52,7 @@
return ok;
}
-status_t MediaRecorderClient::setInputSurface(const sp<IGraphicBufferConsumer>& surface)
+status_t MediaRecorderClient::setInputSurface(const sp<PersistentSurface>& surface)
{
ALOGV("setInputSurface");
Mutex::Autolock lock(mLock);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index eceb653..12656cf 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -25,7 +25,6 @@
class MediaRecorderBase;
class MediaPlayerService;
class ICameraRecordingProxy;
-class IGraphicBufferProducer;
class MediaRecorderClient : public BnMediaRecorder
{
@@ -73,7 +72,7 @@
virtual status_t close();
virtual status_t release();
virtual status_t dump(int fd, const Vector<String16>& args);
- virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface);
+ virtual status_t setInputSurface(const sp<PersistentSurface>& surface);
virtual sp<IGraphicBufferProducer> querySurfaceMediaSource();
private:
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index cdb0a7b..279bc86 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -45,6 +45,7 @@
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/MediaCodecSource.h>
+#include <media/stagefright/PersistentSurface.h>
#include <media/MediaProfiles.h>
#include <camera/CameraParameters.h>
@@ -248,7 +249,7 @@
}
status_t StagefrightRecorder::setInputSurface(
- const sp<IGraphicBufferConsumer>& surface) {
+ const sp<PersistentSurface>& surface) {
mPersistentSurface = surface;
return OK;
@@ -884,7 +885,10 @@
case OUTPUT_FORMAT_RTP_AVP:
case OUTPUT_FORMAT_MPEG2TS:
{
- status = mWriter->start();
+ sp<MetaData> meta = new MetaData;
+ int64_t startTimeUs = systemTime() / 1000;
+ meta->setInt64(kKeyTime, startTimeUs);
+ status = mWriter->start(meta.get());
break;
}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 4dbd039..4c2e65c 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -38,9 +38,6 @@
class MetaData;
struct AudioSource;
class MediaProfiles;
-class IGraphicBufferConsumer;
-class IGraphicBufferProducer;
-class SurfaceMediaSource;
struct ALooper;
struct StagefrightRecorder : public MediaRecorderBase {
@@ -57,7 +54,7 @@
virtual status_t setVideoFrameRate(int frames_per_second);
virtual status_t setCamera(const sp<hardware::ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);
virtual status_t setPreviewSurface(const sp<IGraphicBufferProducer>& surface);
- virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface);
+ virtual status_t setInputSurface(const sp<PersistentSurface>& surface);
virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
virtual status_t setParameters(const String8 ¶ms);
virtual status_t setListener(const sp<IMediaRecorderClient> &listener);
@@ -78,7 +75,7 @@
sp<hardware::ICamera> mCamera;
sp<ICameraRecordingProxy> mCameraProxy;
sp<IGraphicBufferProducer> mPreviewSurface;
- sp<IGraphicBufferConsumer> mPersistentSurface;
+ sp<PersistentSurface> mPersistentSurface;
sp<IMediaRecorderClient> mListener;
String16 mClientName;
uid_t mClientUid;
diff --git a/media/libmediaplayerservice/nuplayer/Android.mk b/media/libmediaplayerservice/nuplayer/Android.mk
index 3ea2159..a0e633c 100644
--- a/media/libmediaplayerservice/nuplayer/Android.mk
+++ b/media/libmediaplayerservice/nuplayer/Android.mk
@@ -32,8 +32,6 @@
LOCAL_CFLAGS += -DENABLE_STAGEFRIGHT_EXPERIMENTS
endif
-LOCAL_CLANG := true
-
LOCAL_SHARED_LIBRARIES := libmedia
LOCAL_MODULE:= libstagefright_nuplayer
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 6b88404..4554472 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -666,7 +666,7 @@
timeUs = mVideoLastDequeueTimeUs;
}
readBuffer(trackType, timeUs, &actualTimeUs, formatChange);
- readBuffer(counterpartType, -1, NULL, formatChange);
+ readBuffer(counterpartType, -1, NULL, !formatChange);
ALOGV("timeUs %lld actualTimeUs %lld", (long long)timeUs, (long long)actualTimeUs);
break;
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
index 3fffdc1a..db24b33 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -304,8 +304,9 @@
notifyVideoSizeChanged();
}
- uint32_t flags = FLAG_CAN_PAUSE;
+ uint32_t flags = 0;
if (mLiveSession->isSeekable()) {
+ flags |= FLAG_CAN_PAUSE;
flags |= FLAG_CAN_SEEK;
flags |= FLAG_CAN_SEEK_BACKWARD;
flags |= FLAG_CAN_SEEK_FORWARD;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 4e16fba..7178661 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -39,6 +39,7 @@
#include <media/AudioResamplerPublic.h>
#include <media/AVSyncSettings.h>
+#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/foundation/ABuffer.h>
@@ -1666,12 +1667,12 @@
// allocate buffers to decrypt widevine source buffers
if (!audio && (mSourceFlags & Source::FLAG_SECURE)) {
- Vector<sp<ABuffer> > inputBufs;
+ 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<ABuffer> &buffer = inputBufs[i];
+ const sp<MediaCodecBuffer> &buffer = inputBufs[i];
MediaBuffer *mbuf = new MediaBuffer(buffer->data(), buffer->size());
mediaBufs.push(mbuf);
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.cpp
index 978d360..73b07bb 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.cpp
@@ -72,37 +72,37 @@
if (cc->mData1 >= 0x20 && cc->mData1 <= 0x7f) {
// 2 basic chars
- sprintf(tmp, "[%d]Basic: %c %c", cc->mType, cc->mData1, cc->mData2);
+ snprintf(tmp, sizeof(tmp), "[%d]Basic: %c %c", cc->mType, cc->mData1, cc->mData2);
} else if ((cc->mData1 == 0x11 || cc->mData1 == 0x19)
&& cc->mData2 >= 0x30 && cc->mData2 <= 0x3f) {
// 1 special char
- sprintf(tmp, "[%d]Special: %02x %02x", cc->mType, cc->mData1, cc->mData2);
+ snprintf(tmp, sizeof(tmp), "[%d]Special: %02x %02x", cc->mType, cc->mData1, cc->mData2);
} else if ((cc->mData1 == 0x12 || cc->mData1 == 0x1A)
&& cc->mData2 >= 0x20 && cc->mData2 <= 0x3f){
// 1 Spanish/French char
- sprintf(tmp, "[%d]Spanish: %02x %02x", cc->mType, cc->mData1, cc->mData2);
+ snprintf(tmp, sizeof(tmp), "[%d]Spanish: %02x %02x", cc->mType, cc->mData1, cc->mData2);
} else if ((cc->mData1 == 0x13 || cc->mData1 == 0x1B)
&& cc->mData2 >= 0x20 && cc->mData2 <= 0x3f){
// 1 Portuguese/German/Danish char
- sprintf(tmp, "[%d]German: %02x %02x", cc->mType, cc->mData1, cc->mData2);
+ snprintf(tmp, sizeof(tmp), "[%d]German: %02x %02x", cc->mType, cc->mData1, cc->mData2);
} else if ((cc->mData1 == 0x11 || cc->mData1 == 0x19)
&& cc->mData2 >= 0x20 && cc->mData2 <= 0x2f){
// Mid-Row Codes (Table 69)
- sprintf(tmp, "[%d]Mid-row: %02x %02x", cc->mType, cc->mData1, cc->mData2);
+ snprintf(tmp, sizeof(tmp), "[%d]Mid-row: %02x %02x", cc->mType, cc->mData1, cc->mData2);
} else if (((cc->mData1 == 0x14 || cc->mData1 == 0x1c)
&& cc->mData2 >= 0x20 && cc->mData2 <= 0x2f)
||
((cc->mData1 == 0x17 || cc->mData1 == 0x1f)
&& cc->mData2 >= 0x21 && cc->mData2 <= 0x23)){
// Misc Control Codes (Table 70)
- sprintf(tmp, "[%d]Ctrl: %02x %02x", cc->mType, cc->mData1, cc->mData2);
+ snprintf(tmp, sizeof(tmp), "[%d]Ctrl: %02x %02x", cc->mType, cc->mData1, cc->mData2);
} else if ((cc->mData1 & 0x70) == 0x10
&& (cc->mData2 & 0x40) == 0x40
&& ((cc->mData1 & 0x07) || !(cc->mData2 & 0x20)) ) {
// Preamble Address Codes (Table 71)
- sprintf(tmp, "[%d]PAC: %02x %02x", cc->mType, cc->mData1, cc->mData2);
+ snprintf(tmp, sizeof(tmp), "[%d]PAC: %02x %02x", cc->mType, cc->mData1, cc->mData2);
} else {
- sprintf(tmp, "[%d]Invalid: %02x %02x", cc->mType, cc->mData1, cc->mData2);
+ snprintf(tmp, sizeof(tmp), "[%d]Invalid: %02x %02x", cc->mType, cc->mData1, cc->mData2);
}
if (out.size() > 0) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index cf38efc..822f154 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -28,6 +28,7 @@
#include <cutils/properties.h>
#include <media/ICrypto.h>
+#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -417,7 +418,7 @@
}
void NuPlayer::Decoder::onGetInputBuffers(
- Vector<sp<ABuffer> > *dstBuffers) {
+ Vector<sp<MediaCodecBuffer> > *dstBuffers) {
CHECK_EQ((status_t)OK, mCodec->getWidevineLegacyBuffers(dstBuffers));
}
@@ -561,7 +562,7 @@
return false;
}
- sp<ABuffer> buffer;
+ sp<MediaCodecBuffer> buffer;
mCodec->getInputBuffer(index, &buffer);
if (buffer == NULL) {
@@ -628,7 +629,7 @@
int64_t timeUs,
int32_t flags) {
// CHECK_LT(bufferIx, mOutputBuffers.size());
- sp<ABuffer> buffer;
+ sp<MediaCodecBuffer> buffer;
mCodec->getOutputBuffer(index, &buffer);
if (index >= mOutputBuffers.size()) {
@@ -865,10 +866,11 @@
size_t bufferIx;
CHECK(msg->findSize("buffer-ix", &bufferIx));
CHECK_LT(bufferIx, mInputBuffers.size());
- sp<ABuffer> codecBuffer = mInputBuffers[bufferIx];
+ sp<MediaCodecBuffer> codecBuffer = mInputBuffers[bufferIx];
sp<ABuffer> buffer;
bool hasBuffer = msg->findBuffer("buffer", &buffer);
+ bool needsCopy = true;
// handle widevine classic source - that fills an arbitrary input buffer
MediaBuffer *mediaBuffer = NULL;
@@ -878,7 +880,7 @@
// likely filled another buffer than we requested: adjust buffer index
size_t ix;
for (ix = 0; ix < mInputBuffers.size(); ix++) {
- const sp<ABuffer> &buf = mInputBuffers[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]) {
@@ -891,11 +893,12 @@
// TRICKY: need buffer for the metadata, so instead, set
// codecBuffer to the same (though incorrect) buffer to
// avoid a memcpy into the codecBuffer
- codecBuffer = buffer;
+ codecBuffer = new MediaCodecBuffer(codecBuffer->format(), buffer);
codecBuffer->setRange(
mediaBuffer->range_offset(),
mediaBuffer->range_length());
bufferIx = ix;
+ needsCopy = false;
break;
}
}
@@ -955,7 +958,7 @@
}
// copy into codec buffer
- if (buffer != codecBuffer) {
+ if (needsCopy) {
if (buffer->size() > codecBuffer->capacity()) {
handleError(ERROR_BUFFER_TOO_SMALL);
mDequeuedInputBuffers.push_back(bufferIx);
@@ -998,7 +1001,7 @@
if (!mIsAudio) {
int64_t timeUs;
- sp<ABuffer> buffer = mOutputBuffers[bufferIx];
+ sp<MediaCodecBuffer> buffer = mOutputBuffers[bufferIx];
buffer->meta()->findInt64("timeUs", &timeUs);
if (mCCDecoder != NULL && mCCDecoder->isSelected()) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
index 0c619ed..8186862 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
@@ -23,6 +23,8 @@
namespace android {
+class MediaCodecBuffer;
+
struct NuPlayer::Decoder : public DecoderBase {
Decoder(const sp<AMessage> ¬ify,
const sp<Source> &source,
@@ -44,7 +46,7 @@
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<ABuffer> > *dstBuffers);
+ virtual void onGetInputBuffers(Vector<sp<MediaCodecBuffer> > *dstBuffers);
virtual void onResume(bool notifyComplete);
virtual void onFlush();
virtual void onShutdown(bool notifyComplete);
@@ -74,8 +76,8 @@
List<sp<AMessage> > mPendingInputMessages;
- Vector<sp<ABuffer> > mInputBuffers;
- Vector<sp<ABuffer> > mOutputBuffers;
+ Vector<sp<MediaCodecBuffer> > mInputBuffers;
+ Vector<sp<MediaCodecBuffer> > mOutputBuffers;
Vector<sp<ABuffer> > mCSDsForCurrentFormat;
Vector<sp<ABuffer> > mCSDsToSubmit;
Vector<bool> mInputBufferIsDequeued;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp
index 04bb61c..9c007ae 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp
@@ -23,6 +23,7 @@
#include "NuPlayerRenderer.h"
+#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -91,7 +92,7 @@
PostAndAwaitResponse(msg, &response);
}
-status_t NuPlayer::DecoderBase::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
+status_t NuPlayer::DecoderBase::getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
sp<AMessage> msg = new AMessage(kWhatGetInputBuffers, this);
msg->setPointer("buffers", buffers);
@@ -170,7 +171,7 @@
sp<AReplyToken> replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
- Vector<sp<ABuffer> > *dstBuffers;
+ Vector<sp<MediaCodecBuffer> > *dstBuffers;
CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
onGetInputBuffers(dstBuffers);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h
index 9966144..6f4ead6 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h
@@ -27,6 +27,7 @@
struct ABuffer;
struct MediaCodec;
class MediaBuffer;
+class MediaCodecBuffer;
class Surface;
struct NuPlayer::DecoderBase : public AHandler {
@@ -42,7 +43,7 @@
void setRenderer(const sp<Renderer> &renderer);
virtual status_t setVideoSurface(const sp<Surface> &) { return INVALID_OPERATION; }
- status_t getInputBuffers(Vector<sp<ABuffer> > *dstBuffers) const;
+ status_t getInputBuffers(Vector<sp<MediaCodecBuffer> > *dstBuffers) const;
void signalFlush();
void signalResume(bool notifyComplete);
void initiateShutdown();
@@ -70,7 +71,7 @@
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<ABuffer> > *dstBuffers) = 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;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
index f224635..e4767ff 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
@@ -25,6 +25,7 @@
#include "NuPlayerSource.h"
#include <media/ICrypto.h>
+#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -93,7 +94,7 @@
}
void NuPlayer::DecoderPassThrough::onGetInputBuffers(
- Vector<sp<ABuffer> > * /* dstBuffers */) {
+ Vector<sp<MediaCodecBuffer> > * /* dstBuffers */) {
ALOGE("onGetInputBuffers() called unexpectedly");
}
@@ -319,10 +320,9 @@
int32_t bufferSize = buffer->size();
mCachedBytes += bufferSize;
+ int64_t timeUs = 0;
+ CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
if (mSkipRenderingUntilMediaTimeUs >= 0) {
- int64_t timeUs = 0;
- CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
-
if (timeUs < mSkipRenderingUntilMediaTimeUs) {
ALOGV("[%s] dropping buffer at time %lld as requested.",
mComponentName.c_str(), (long long)timeUs);
@@ -343,7 +343,10 @@
reply->setInt32("generation", mBufferGeneration);
reply->setInt32("size", bufferSize);
- mRenderer->queueBuffer(true /* audio */, buffer, reply);
+ sp<MediaCodecBuffer> mcBuffer = new MediaCodecBuffer(nullptr, buffer);
+ mcBuffer->meta()->setInt64("timeUs", timeUs);
+
+ mRenderer->queueBuffer(true /* audio */, mcBuffer, reply);
++mPendingBuffersToDrain;
ALOGV("onInputBufferFilled: #ToDrain = %zu, cachedBytes = %zu",
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
index 5850efa..9af25ff 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
@@ -38,7 +38,7 @@
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<ABuffer> > *dstBuffers);
+ 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/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index b742762..b78bdfb 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -21,7 +21,6 @@
#include "NuPlayerRenderer.h"
#include <algorithm>
#include <cutils/properties.h>
-#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>
@@ -31,6 +30,7 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/Utils.h>
#include <media/stagefright/VideoFrameScheduler.h>
+#include <media/MediaCodecBuffer.h>
#include <inttypes.h>
@@ -156,12 +156,12 @@
void NuPlayer::Renderer::queueBuffer(
bool audio,
- const sp<ABuffer> &buffer,
+ const sp<MediaCodecBuffer> &buffer,
const sp<AMessage> ¬ifyConsumed) {
sp<AMessage> msg = new AMessage(kWhatQueueBuffer, this);
msg->setInt32("queueGeneration", getQueueGeneration(audio));
msg->setInt32("audio", static_cast<int32_t>(audio));
- msg->setBuffer("buffer", buffer);
+ msg->setObject("buffer", buffer);
msg->setMessage("notifyConsumed", notifyConsumed);
msg->post();
}
@@ -1368,8 +1368,9 @@
}
}
- sp<ABuffer> buffer;
- CHECK(msg->findBuffer("buffer", &buffer));
+ sp<RefBase> obj;
+ CHECK(msg->findObject("buffer", &obj));
+ sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
sp<AMessage> notifyConsumed;
CHECK(msg->findMessage("notifyConsumed", ¬ifyConsumed));
@@ -1395,8 +1396,8 @@
return;
}
- sp<ABuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
- sp<ABuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
+ sp<MediaCodecBuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
+ sp<MediaCodecBuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
// EOS signalled on either queue.
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index fe7f8fa..0bd3aa1 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -25,9 +25,9 @@
namespace android {
-struct ABuffer;
class AWakeLock;
struct MediaClock;
+class MediaCodecBuffer;
struct VideoFrameScheduler;
struct NuPlayer::Renderer : public AHandler {
@@ -46,7 +46,7 @@
void queueBuffer(
bool audio,
- const sp<ABuffer> &buffer,
+ const sp<MediaCodecBuffer> &buffer,
const sp<AMessage> ¬ifyConsumed);
void queueEOS(bool audio, status_t finalResult);
@@ -125,7 +125,7 @@
};
struct QueueEntry {
- sp<ABuffer> mBuffer;
+ sp<MediaCodecBuffer> mBuffer;
sp<AMessage> mNotifyConsumed;
size_t mOffset;
status_t mFinalResult;
diff --git a/media/libmediaplayerservice/tests/Android.mk b/media/libmediaplayerservice/tests/Android.mk
index ea75a97..c0b3265 100644
--- a/media/libmediaplayerservice/tests/Android.mk
+++ b/media/libmediaplayerservice/tests/Android.mk
@@ -20,7 +20,6 @@
frameworks/av/media/libmediaplayerservice \
LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
LOCAL_32_BIT_ONLY := true
diff --git a/media/libnbaio/Android.bp b/media/libnbaio/Android.bp
index 615b541..45ad16f 100644
--- a/media/libnbaio/Android.bp
+++ b/media/libnbaio/Android.bp
@@ -22,6 +22,7 @@
// static_libs: ["libsndfile"],
shared_libs: [
+ "libaudiohal",
"libaudioutils",
"libbinder",
"libcutils",
diff --git a/media/libnbaio/AudioStreamInSource.cpp b/media/libnbaio/AudioStreamInSource.cpp
index 2dc3050..1054b68 100644
--- a/media/libnbaio/AudioStreamInSource.cpp
+++ b/media/libnbaio/AudioStreamInSource.cpp
@@ -19,33 +19,38 @@
#include <cutils/compiler.h>
#include <utils/Log.h>
+#include <media/audiohal/StreamHalInterface.h>
#include <media/nbaio/AudioStreamInSource.h>
namespace android {
-AudioStreamInSource::AudioStreamInSource(audio_stream_in *stream) :
+AudioStreamInSource::AudioStreamInSource(sp<StreamInHalInterface> stream) :
NBAIO_Source(),
mStream(stream),
mStreamBufferSizeBytes(0),
mFramesOverrun(0),
mOverruns(0)
{
- ALOG_ASSERT(stream != NULL);
+ ALOG_ASSERT(stream != 0);
}
AudioStreamInSource::~AudioStreamInSource()
{
+ mStream.clear();
}
ssize_t AudioStreamInSource::negotiate(const NBAIO_Format offers[], size_t numOffers,
NBAIO_Format counterOffers[], size_t& numCounterOffers)
{
if (!Format_isValid(mFormat)) {
- mStreamBufferSizeBytes = mStream->common.get_buffer_size(&mStream->common);
- audio_format_t streamFormat = mStream->common.get_format(&mStream->common);
- uint32_t sampleRate = mStream->common.get_sample_rate(&mStream->common);
- audio_channel_mask_t channelMask =
- (audio_channel_mask_t) mStream->common.get_channels(&mStream->common);
+ status_t result;
+ result = mStream->getBufferSize(&mStreamBufferSizeBytes);
+ if (result != OK) return result;
+ audio_format_t streamFormat;
+ uint32_t sampleRate;
+ audio_channel_mask_t channelMask;
+ result = mStream->getAudioProperties(&sampleRate, &channelMask, &streamFormat);
+ if (result != OK) return result;
mFormat = Format_from_SR_C(sampleRate,
audio_channel_count_from_in_mask(channelMask), streamFormat);
mFrameSize = Format_frameSize(mFormat);
@@ -55,11 +60,14 @@
int64_t AudioStreamInSource::framesOverrun()
{
- uint32_t framesOverrun = mStream->get_input_frames_lost(mStream);
- if (framesOverrun > 0) {
+ uint32_t framesOverrun;
+ status_t result = mStream->getInputFramesLost(&framesOverrun);
+ if (result == OK && framesOverrun > 0) {
mFramesOverrun += framesOverrun;
// FIXME only increment for contiguous ranges
++mOverruns;
+ } else if (result != OK) {
+ ALOGE("Error when retrieving lost frames count from HAL: %d", result);
}
return mFramesOverrun;
}
@@ -69,12 +77,14 @@
if (CC_UNLIKELY(!Format_isValid(mFormat))) {
return NEGOTIATE;
}
- ssize_t bytesRead = mStream->read(mStream, buffer, count * mFrameSize);
- if (bytesRead > 0) {
+ size_t bytesRead;
+ status_t result = mStream->read(buffer, count * mFrameSize, &bytesRead);
+ if (result == OK && bytesRead > 0) {
size_t framesRead = bytesRead / mFrameSize;
mFramesRead += framesRead;
return framesRead;
} else {
+ ALOGE_IF(result != OK, "Error while reading data from HAL: %d", result);
return bytesRead;
}
}
diff --git a/media/libnbaio/AudioStreamOutSink.cpp b/media/libnbaio/AudioStreamOutSink.cpp
index ee44678..cbff87d 100644
--- a/media/libnbaio/AudioStreamOutSink.cpp
+++ b/media/libnbaio/AudioStreamOutSink.cpp
@@ -18,31 +18,36 @@
//#define LOG_NDEBUG 0
#include <utils/Log.h>
+#include <media/audiohal/StreamHalInterface.h>
#include <media/nbaio/AudioStreamOutSink.h>
namespace android {
-AudioStreamOutSink::AudioStreamOutSink(audio_stream_out *stream) :
+AudioStreamOutSink::AudioStreamOutSink(sp<StreamOutHalInterface> stream) :
NBAIO_Sink(),
mStream(stream),
mStreamBufferSizeBytes(0)
{
- ALOG_ASSERT(stream != NULL);
+ ALOG_ASSERT(stream != 0);
}
AudioStreamOutSink::~AudioStreamOutSink()
{
+ mStream.clear();
}
ssize_t AudioStreamOutSink::negotiate(const NBAIO_Format offers[], size_t numOffers,
NBAIO_Format counterOffers[], size_t& numCounterOffers)
{
if (!Format_isValid(mFormat)) {
- mStreamBufferSizeBytes = mStream->common.get_buffer_size(&mStream->common);
- audio_format_t streamFormat = mStream->common.get_format(&mStream->common);
- uint32_t sampleRate = mStream->common.get_sample_rate(&mStream->common);
- audio_channel_mask_t channelMask =
- (audio_channel_mask_t) mStream->common.get_channels(&mStream->common);
+ status_t result;
+ result = mStream->getBufferSize(&mStreamBufferSizeBytes);
+ if (result != OK) return result;
+ audio_format_t streamFormat;
+ uint32_t sampleRate;
+ audio_channel_mask_t channelMask;
+ result = mStream->getAudioProperties(&sampleRate, &channelMask, &streamFormat);
+ if (result != OK) return result;
mFormat = Format_from_SR_C(sampleRate,
audio_channel_count_from_out_mask(channelMask), streamFormat);
mFrameSize = Format_frameSize(mFormat);
@@ -56,25 +61,24 @@
return NEGOTIATE;
}
ALOG_ASSERT(Format_isValid(mFormat));
- ssize_t ret = mStream->write(mStream, buffer, count * mFrameSize);
- if (ret > 0) {
- ret /= mFrameSize;
- mFramesWritten += ret;
+ size_t written;
+ status_t ret = mStream->write(buffer, count * mFrameSize, &written);
+ if (ret == OK && written > 0) {
+ written /= mFrameSize;
+ mFramesWritten += written;
+ return written;
} else {
// FIXME verify HAL implementations are returning the correct error codes e.g. WOULD_BLOCK
+ ALOGE_IF(ret != OK, "Error while writing data to HAL: %d", ret);
+ return ret;
}
- return ret;
}
status_t AudioStreamOutSink::getTimestamp(ExtendedTimestamp ×tamp)
{
- if (mStream->get_presentation_position == NULL) {
- return INVALID_OPERATION;
- }
-
uint64_t position64;
struct timespec time;
- if (mStream->get_presentation_position(mStream, &position64, &time) != OK) {
+ if (mStream->getPresentationPosition(&position64, &time) != OK) {
return INVALID_OPERATION;
}
timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = position64;
diff --git a/media/libnbaio/PipeReader.cpp b/media/libnbaio/PipeReader.cpp
index a879647..fdea68e 100644
--- a/media/libnbaio/PipeReader.cpp
+++ b/media/libnbaio/PipeReader.cpp
@@ -45,6 +45,7 @@
ALOG_ASSERT(readers > 0);
}
+__attribute__((no_sanitize("integer")))
ssize_t PipeReader::availableToRead()
{
if (CC_UNLIKELY(!mNegotiated)) {
@@ -54,16 +55,16 @@
// read() is not multi-thread safe w.r.t. itself, so no mutex or atomic op needed to read mFront
size_t avail = rear - mFront;
if (CC_UNLIKELY(avail > mPipe.mMaxFrames)) {
- // Discard 1/16 of the most recent data in pipe to avoid another overrun immediately
- int32_t oldFront = mFront;
- mFront = rear - mPipe.mMaxFrames + (mPipe.mMaxFrames >> 4);
- mFramesOverrun += (size_t) (mFront - oldFront);
+ // Discard all data in pipe to avoid another overrun immediately
+ mFront = rear;
+ mFramesOverrun += avail;
++mOverruns;
return OVERRUN;
}
return avail;
}
+__attribute__((no_sanitize("integer")))
ssize_t PipeReader::read(void *buffer, size_t count)
{
ssize_t avail = availableToRead();
@@ -97,4 +98,19 @@
return red;
}
+__attribute__((no_sanitize("integer")))
+ssize_t PipeReader::flush()
+{
+ if (CC_UNLIKELY(!mNegotiated)) {
+ return NEGOTIATE;
+ }
+ const int32_t rear = android_atomic_acquire_load(&mPipe.mRear);
+ const size_t flushed = rear - mFront;
+ // We don't check if flushed > mPipe.mMaxFrames (an overrun occurred) as the
+ // distinction is unimportant; all data is dropped.
+ mFront = rear;
+ mFramesRead += flushed; // we consider flushed frames as read.
+ return flushed;
+}
+
} // namespace android
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index e7057ce..478de35 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -53,10 +53,13 @@
#include "include/avc_utils.h"
#include "include/DataConverter.h"
+#include "include/SharedMemoryBuffer.h"
#include "omx/OMXUtils.h"
namespace android {
+using binder::Status;
+
enum {
kMaxIndicesToCheck = 32, // used when enumerating supported formats and profiles
};
@@ -90,6 +93,21 @@
}
}
+static inline status_t statusFromBinderStatus(const Status &status) {
+ if (status.isOk()) {
+ return OK;
+ }
+ status_t err;
+ if ((err = status.serviceSpecificErrorCode()) != OK) {
+ return err;
+ }
+ if ((err = status.transactionError()) != OK) {
+ return err;
+ }
+ // Other exception
+ return UNKNOWN_ERROR;
+}
+
// checks and converts status_t to a non-side-effect status_t
static inline status_t makeNoSideEffectStatus(status_t err) {
switch (err) {
@@ -136,15 +154,10 @@
}
sp<AMessage> notify = mNotify->dup();
- bool first = true;
sp<MessageList> msgList = new MessageList();
for (std::list<omx_message>::const_iterator it = messages.cbegin();
it != messages.cend(); ++it) {
const omx_message &omx_msg = *it;
- if (first) {
- notify->setInt32("node", omx_msg.node);
- first = false;
- }
sp<AMessage> msg = new AMessage;
msg->setInt32("type", omx_msg.type);
@@ -495,8 +508,7 @@
ACodec::ACodec()
: mSampleRate(0),
- mQuirks(0),
- mNode(0),
+ mNodeGeneration(0),
mUsingNativeWindow(false),
mNativeWindowUsageBits(0),
mLastNativeWindowDataSpace(HAL_DATASPACE_UNKNOWN),
@@ -793,8 +805,8 @@
InitOMXParams(&def);
def.nPortIndex = portIndex;
- err = mOMX->getParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err == OK) {
MetadataBufferType type =
@@ -853,6 +865,7 @@
size_t totalSize = def.nBufferCountActual * (alignedSize + alignedConvSize);
mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
+ const sp<AMessage> &format = portIndex == kPortIndexInput ? mInputFormat : mOutputFormat;
for (OMX_U32 i = 0; i < def.nBufferCountActual && err == OK; ++i) {
sp<IMemory> mem = mDealer[portIndex]->allocate(bufSize);
if (mem == NULL || mem->pointer() == NULL) {
@@ -865,18 +878,13 @@
info.mRenderInfo = NULL;
info.mNativeHandle = NULL;
- uint32_t requiresAllocateBufferBit =
- (portIndex == kPortIndexInput)
- ? kRequiresAllocateBufferOnInputPorts
- : kRequiresAllocateBufferOnOutputPorts;
-
if (portIndex == kPortIndexInput && (mFlags & kFlagIsSecure)) {
mem.clear();
void *ptr = NULL;
sp<NativeHandle> native_handle;
- err = mOMX->allocateSecureBuffer(
- mNode, portIndex, bufSize, &info.mBufferID,
+ err = mOMXNode->allocateSecureBuffer(
+ portIndex, bufSize, &info.mBufferID,
&ptr, &native_handle);
// TRICKY: this representation is unorthodox, but ACodec requires
@@ -889,19 +897,17 @@
// because Widevine source only receives these base addresses.
const native_handle_t *native_handle_ptr =
native_handle == NULL ? NULL : native_handle->handle();
- info.mData = new ABuffer(
- ptr != NULL ? ptr : (void *)native_handle_ptr, bufSize);
+ info.mData = new MediaCodecBuffer(format,
+ new ABuffer(ptr != NULL ? ptr : (void *)native_handle_ptr, bufSize));
info.mNativeHandle = native_handle;
info.mCodecData = info.mData;
- } else if (mQuirks & requiresAllocateBufferBit) {
- err = mOMX->allocateBufferWithBackup(
- mNode, portIndex, mem, &info.mBufferID, allottedSize);
} else {
- err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID, allottedSize);
+ err = mOMXNode->useBuffer(
+ portIndex, mem, &info.mBufferID, allottedSize);
}
if (mem != NULL) {
- info.mCodecData = new ABuffer(mem->pointer(), bufSize);
+ info.mCodecData = new SharedMemoryBuffer(format, mem);
info.mCodecRef = mem;
if (type == kMetadataBufferTypeANWBuffer) {
@@ -916,7 +922,7 @@
if (mem == NULL|| mem->pointer() == NULL) {
return NO_MEMORY;
}
- info.mData = new ABuffer(mem->pointer(), conversionBufferSize);
+ info.mData = new SharedMemoryBuffer(format, mem);
info.mMemRef = mem;
} else {
info.mData = info.mCodecData;
@@ -958,15 +964,15 @@
InitOMXParams(&def);
def.nPortIndex = kPortIndexOutput;
- status_t err = mOMX->getParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ status_t err = mOMXNode->getParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err != OK) {
return err;
}
OMX_U32 usage = 0;
- err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
+ err = mOMXNode->getGraphicBufferUsage(kPortIndexOutput, &usage);
if (err != 0) {
ALOGW("querying usage flags from OMX IL component failed: %d", err);
// XXX: Currently this error is logged, but not fatal.
@@ -1003,8 +1009,8 @@
InitOMXParams(&def);
def.nPortIndex = kPortIndexOutput;
- status_t err = mOMX->getParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ status_t err = mOMXNode->getParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err == OK) {
err = setupNativeWindowSizeFormatAndUsage(
@@ -1021,8 +1027,8 @@
if (mTunneled) {
ALOGV("Tunneled Playback: skipping native window buffer allocation.");
def.nBufferCountActual = 0;
- err = mOMX->setParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ err = mOMXNode->setParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
*minUndequeuedBuffers = 0;
*bufferCount = 0;
@@ -1057,8 +1063,8 @@
OMX_U32 newBufferCount =
def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers;
def.nBufferCountActual = newBufferCount;
- err = mOMX->setParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ err = mOMXNode->setParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err == OK) {
*minUndequeuedBuffers += extraBuffers;
@@ -1120,14 +1126,12 @@
info.mFenceFd = fenceFd;
info.mIsReadFence = false;
info.mRenderInfo = NULL;
- info.mData = new ABuffer(NULL /* data */, bufferSize /* capacity */);
- info.mCodecData = info.mData;
info.mGraphicBuffer = graphicBuffer;
mBuffers[kPortIndexOutput].push(info);
IOMX::buffer_id bufferId;
- err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
- &bufferId);
+ err = mOMXNode->useGraphicBuffer(
+ kPortIndexOutput, graphicBuffer, &bufferId);
if (err != 0) {
ALOGE("registering GraphicBuffer %u with OMX IL component failed: "
"%d", i, err);
@@ -1206,14 +1210,14 @@
if (mOutputMetadataType == kMetadataBufferTypeANWBuffer) {
((VideoNativeMetadata *)mem->pointer())->nFenceFd = -1;
}
- info.mData = new ABuffer(mem->pointer(), mem->size());
+ info.mData = new SharedMemoryBuffer(mOutputFormat, mem);
info.mMemRef = mem;
info.mCodecData = info.mData;
info.mCodecRef = mem;
// we use useBuffer for metadata regardless of quirks
- err = mOMX->useBuffer(
- mNode, kPortIndexOutput, mem, &info.mBufferID, mem->size());
+ err = mOMXNode->useBuffer(
+ kPortIndexOutput, mem, &info.mBufferID, mem->size());
mBuffers[kPortIndexOutput].push(info);
ALOGV("[%s] allocated meta buffer with ID %u (pointer = %p)",
@@ -1242,8 +1246,8 @@
}
sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
- mOMX->updateGraphicBufferInMeta(
- mNode, kPortIndexOutput, graphicBuffer, info->mBufferID);
+ mOMXNode->updateGraphicBufferInMeta(
+ kPortIndexOutput, graphicBuffer, info->mBufferID);
info->mStatus = BufferInfo::OWNED_BY_US;
info->setWriteFence(fenceFd, "allocateOutputMetadataBuffers for legacy");
info->mGraphicBuffer = graphicBuffer;
@@ -1282,7 +1286,7 @@
--mMetadataBuffersToSubmit;
info->checkWriteFence("submitOutputMetadataBuffer");
- status_t err = mOMX->fillBuffer(mNode, info->mBufferID, info->mFenceFd);
+ status_t err = mOMXNode->fillBuffer(info->mBufferID, info->mFenceFd);
info->mFenceFd = -1;
if (err == OK) {
info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
@@ -1480,26 +1484,25 @@
mRenderTracker.untrackFrame(oldest->mRenderInfo);
oldest->mRenderInfo = NULL;
- mOMX->updateGraphicBufferInMeta(
- mNode, kPortIndexOutput, oldest->mGraphicBuffer,
- oldest->mBufferID);
+ mOMXNode->updateGraphicBufferInMeta(
+ kPortIndexOutput, oldest->mGraphicBuffer, oldest->mBufferID);
if (mOutputMetadataType == kMetadataBufferTypeGrallocSource) {
VideoGrallocMetadata *grallocMeta =
- reinterpret_cast<VideoGrallocMetadata *>(oldest->mData->base());
+ reinterpret_cast<VideoGrallocMetadata *>(oldest->mData->data());
ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
(unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
mDequeueCounter - oldest->mDequeuedAt,
(void *)(uintptr_t)grallocMeta->pHandle,
- oldest->mGraphicBuffer->handle, oldest->mData->base());
+ oldest->mGraphicBuffer->handle, oldest->mData->data());
} else if (mOutputMetadataType == kMetadataBufferTypeANWBuffer) {
VideoNativeMetadata *nativeMeta =
- reinterpret_cast<VideoNativeMetadata *>(oldest->mData->base());
+ reinterpret_cast<VideoNativeMetadata *>(oldest->mData->data());
ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
(unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
mDequeueCounter - oldest->mDequeuedAt,
(void *)(uintptr_t)nativeMeta->pBuffer,
- oldest->mGraphicBuffer->getNativeBuffer(), oldest->mData->base());
+ oldest->mGraphicBuffer->getNativeBuffer(), oldest->mData->data());
}
updateRenderInfoForDequeuedBuffer(buf, fenceFd, oldest);
@@ -1566,7 +1569,7 @@
// fall through
case BufferInfo::OWNED_BY_NATIVE_WINDOW:
- err = mOMX->freeBuffer(mNode, portIndex, info->mBufferID);
+ err = mOMXNode->freeBuffer(portIndex, info->mBufferID);
break;
default:
@@ -1584,7 +1587,7 @@
info->mRenderInfo = NULL;
}
- // remove buffer even if mOMX->freeBuffer fails
+ // remove buffer even if mOMXNode->freeBuffer fails
mBuffers[portIndex].removeAt(i);
return err;
}
@@ -1608,11 +1611,11 @@
status_t ACodec::setComponentRole(
bool isEncoder, const char *mime) {
- const char *role = getComponentRole(isEncoder, mime);
+ const char *role = GetComponentRole(isEncoder, mime);
if (role == NULL) {
return BAD_VALUE;
}
- status_t err = setComponentRole(mOMX, mNode, role);
+ status_t err = SetComponentRole(mOMXNode, role);
if (err != OK) {
ALOGW("[%s] Failed to set standard component role '%s'.",
mComponentName.c_str(), role);
@@ -1620,98 +1623,6 @@
return err;
}
-//static
-const char *ACodec::getComponentRole(
- bool isEncoder, const char *mime) {
- struct MimeToRole {
- const char *mime;
- const char *decoderRole;
- const char *encoderRole;
- };
-
- static const MimeToRole kMimeToRole[] = {
- { MEDIA_MIMETYPE_AUDIO_MPEG,
- "audio_decoder.mp3", "audio_encoder.mp3" },
- { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
- "audio_decoder.mp1", "audio_encoder.mp1" },
- { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
- "audio_decoder.mp2", "audio_encoder.mp2" },
- { MEDIA_MIMETYPE_AUDIO_AMR_NB,
- "audio_decoder.amrnb", "audio_encoder.amrnb" },
- { MEDIA_MIMETYPE_AUDIO_AMR_WB,
- "audio_decoder.amrwb", "audio_encoder.amrwb" },
- { MEDIA_MIMETYPE_AUDIO_AAC,
- "audio_decoder.aac", "audio_encoder.aac" },
- { MEDIA_MIMETYPE_AUDIO_VORBIS,
- "audio_decoder.vorbis", "audio_encoder.vorbis" },
- { MEDIA_MIMETYPE_AUDIO_OPUS,
- "audio_decoder.opus", "audio_encoder.opus" },
- { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
- "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
- { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
- "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
- { MEDIA_MIMETYPE_VIDEO_AVC,
- "video_decoder.avc", "video_encoder.avc" },
- { MEDIA_MIMETYPE_VIDEO_HEVC,
- "video_decoder.hevc", "video_encoder.hevc" },
- { MEDIA_MIMETYPE_VIDEO_MPEG4,
- "video_decoder.mpeg4", "video_encoder.mpeg4" },
- { MEDIA_MIMETYPE_VIDEO_H263,
- "video_decoder.h263", "video_encoder.h263" },
- { MEDIA_MIMETYPE_VIDEO_VP8,
- "video_decoder.vp8", "video_encoder.vp8" },
- { MEDIA_MIMETYPE_VIDEO_VP9,
- "video_decoder.vp9", "video_encoder.vp9" },
- { MEDIA_MIMETYPE_AUDIO_RAW,
- "audio_decoder.raw", "audio_encoder.raw" },
- { MEDIA_MIMETYPE_VIDEO_DOLBY_VISION,
- "video_decoder.dolby-vision", "video_encoder.dolby-vision" },
- { MEDIA_MIMETYPE_AUDIO_FLAC,
- "audio_decoder.flac", "audio_encoder.flac" },
- { MEDIA_MIMETYPE_AUDIO_MSGSM,
- "audio_decoder.gsm", "audio_encoder.gsm" },
- { MEDIA_MIMETYPE_VIDEO_MPEG2,
- "video_decoder.mpeg2", "video_encoder.mpeg2" },
- { MEDIA_MIMETYPE_AUDIO_AC3,
- "audio_decoder.ac3", "audio_encoder.ac3" },
- { MEDIA_MIMETYPE_AUDIO_EAC3,
- "audio_decoder.eac3", "audio_encoder.eac3" },
- };
-
- static const size_t kNumMimeToRole =
- sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
-
- size_t i;
- for (i = 0; i < kNumMimeToRole; ++i) {
- if (!strcasecmp(mime, kMimeToRole[i].mime)) {
- break;
- }
- }
-
- if (i == kNumMimeToRole) {
- return NULL;
- }
-
- return isEncoder ? kMimeToRole[i].encoderRole
- : kMimeToRole[i].decoderRole;
-}
-
-//static
-status_t ACodec::setComponentRole(
- const sp<IOMX> &omx, IOMX::node_id node, const char *role) {
- OMX_PARAM_COMPONENTROLETYPE roleParams;
- InitOMXParams(&roleParams);
-
- strncpy((char *)roleParams.cRole,
- role, OMX_MAX_STRINGNAME_SIZE - 1);
-
- roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
-
- return omx->setParameter(
- node, OMX_IndexParamStandardComponentRole,
- &roleParams, sizeof(roleParams));
-}
-
status_t ACodec::configureCodec(
const char *mime, const sp<AMessage> &msg) {
int32_t encoder;
@@ -1754,8 +1665,8 @@
&& msg->findInt32("android._input-metadata-buffer-type", &storeMeta)
&& storeMeta != kMetadataBufferTypeInvalid) {
mInputMetadataType = (MetadataBufferType)storeMeta;
- err = mOMX->storeMetaDataInBuffers(
- mNode, kPortIndexInput, OMX_TRUE, &mInputMetadataType);
+ err = mOMXNode->storeMetaDataInBuffers(
+ kPortIndexInput, OMX_TRUE, &mInputMetadataType);
if (err != OK) {
ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d",
mComponentName.c_str(), err);
@@ -1768,8 +1679,8 @@
}
uint32_t usageBits;
- if (mOMX->getParameter(
- mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
+ if (mOMXNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
&usageBits, sizeof(usageBits)) == OK) {
inputFormat->setInt32(
"using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
@@ -1781,18 +1692,15 @@
&& msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS)
&& prependSPSPPS != 0) {
OMX_INDEXTYPE index;
- err = mOMX->getExtensionIndex(
- mNode,
- "OMX.google.android.index.prependSPSPPSToIDRFrames",
- &index);
+ err = mOMXNode->getExtensionIndex(
+ "OMX.google.android.index.prependSPSPPSToIDRFrames", &index);
if (err == OK) {
PrependSPSPPSToIDRFramesParams params;
InitOMXParams(¶ms);
params.bEnable = OMX_TRUE;
- err = mOMX->setParameter(
- mNode, index, ¶ms, sizeof(params));
+ err = mOMXNode->setParameter(index, ¶ms, sizeof(params));
}
if (err != OK) {
@@ -1814,7 +1722,7 @@
&& storeMeta != 0);
mOutputMetadataType = kMetadataBufferTypeNativeHandleSource;
- err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, enable, &mOutputMetadataType);
+ err = mOMXNode->storeMetaDataInBuffers(kPortIndexOutput, enable, &mOutputMetadataType);
if (err != OK) {
ALOGE("[%s] storeMetaDataInBuffers (output) failed w/ err %d",
mComponentName.c_str(), err);
@@ -1866,8 +1774,8 @@
if (mFlags & kFlagIsSecure) {
// use native_handles for secure input buffers
- err = mOMX->enableNativeBuffers(
- mNode, kPortIndexInput, OMX_FALSE /* graphic */, OMX_TRUE);
+ err = mOMXNode->enableNativeBuffers(
+ kPortIndexInput, OMX_FALSE /* graphic */, OMX_TRUE);
ALOGI_IF(err != OK, "falling back to non-native_handles");
err = OK; // ignore error for now
}
@@ -1883,8 +1791,8 @@
OMX_CONFIG_BOOLEANTYPE config;
InitOMXParams(&config);
config.bEnabled = (OMX_BOOL)enabled;
- status_t temp = mOMX->setConfig(
- mNode, (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion,
+ status_t temp = mOMXNode->setConfig(
+ (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion,
&config, sizeof(config));
if (temp == OK) {
outputFormat->setInt32("auto-frc", enabled);
@@ -1915,8 +1823,8 @@
if (msg->findInt32("max-width", &maxWidth) &&
msg->findInt32("max-height", &maxHeight)) {
- err = mOMX->prepareForAdaptivePlayback(
- mNode, kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
+ err = mOMXNode->prepareForAdaptivePlayback(
+ kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
if (err != OK) {
ALOGW("[%s] prepareForAdaptivePlayback failed w/ err %d",
mComponentName.c_str(), err);
@@ -1943,8 +1851,8 @@
// Always try to enable dynamic output buffers on native surface
mOutputMetadataType = kMetadataBufferTypeANWBuffer;
- err = mOMX->storeMetaDataInBuffers(
- mNode, kPortIndexOutput, OMX_TRUE, &mOutputMetadataType);
+ err = mOMXNode->storeMetaDataInBuffers(
+ kPortIndexOutput, OMX_TRUE, &mOutputMetadataType);
if (err != OK) {
ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d",
mComponentName.c_str(), err);
@@ -1978,9 +1886,8 @@
ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)",
mComponentName.c_str(), maxWidth, maxHeight);
- err = mOMX->prepareForAdaptivePlayback(
- mNode, kPortIndexOutput, OMX_TRUE, maxWidth,
- maxHeight);
+ err = mOMXNode->prepareForAdaptivePlayback(
+ kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
ALOGW_IF(err != OK,
"[%s] prepareForAdaptivePlayback failed w/ err %d",
mComponentName.c_str(), err);
@@ -2068,8 +1975,8 @@
}
ALOGD("[%s] Requested output format %#x and got %#x.",
mComponentName.c_str(), requestedColorFormat, colorFormat);
- if (!isFlexibleColorFormat(
- mOMX, mNode, colorFormat, haveNativeWindow, &flexibleEquivalent)
+ if (!IsFlexibleColorFormat(
+ mOMXNode, colorFormat, haveNativeWindow, &flexibleEquivalent)
|| flexibleEquivalent != (OMX_U32)requestedColorFormat) {
// device did not handle flex-YUV request for native window, fall back
// to SW renderer
@@ -2079,16 +1986,16 @@
haveNativeWindow = false;
usingSwRenderer = true;
if (storingMetadataInDecodedBuffers()) {
- err = mOMX->storeMetaDataInBuffers(
- mNode, kPortIndexOutput, OMX_FALSE, &mOutputMetadataType);
+ err = mOMXNode->storeMetaDataInBuffers(
+ kPortIndexOutput, OMX_FALSE, &mOutputMetadataType);
mOutputMetadataType = kMetadataBufferTypeInvalid; // just in case
// TODO: implement adaptive-playback support for bytebuffer mode.
// This is done by SW codecs, but most HW codecs don't support it.
inputFormat->setInt32("adaptive-playback", false);
}
if (err == OK) {
- err = mOMX->enableNativeBuffers(
- mNode, kPortIndexOutput, OMX_TRUE /* graphic */, OMX_FALSE);
+ err = mOMXNode->enableNativeBuffers(
+ kPortIndexOutput, OMX_TRUE /* graphic */, OMX_FALSE);
}
if (mFlags & kFlagIsGrallocUsageProtected) {
// fallback is not supported for protected playback
@@ -2330,8 +2237,8 @@
OMX_PARAM_U32TYPE config;
InitOMXParams(&config);
config.nU32 = (OMX_U32)priority;
- status_t temp = mOMX->setConfig(
- mNode, (OMX_INDEXTYPE)OMX_IndexConfigPriority,
+ status_t temp = mOMXNode->setConfig(
+ (OMX_INDEXTYPE)OMX_IndexConfigPriority,
&config, sizeof(config));
if (temp != OK) {
ALOGI("codec does not support config priority (err %d)", temp);
@@ -2358,8 +2265,8 @@
OMX_PARAM_U32TYPE config;
InitOMXParams(&config);
config.nU32 = rate;
- status_t err = mOMX->setConfig(
- mNode, (OMX_INDEXTYPE)OMX_IndexConfigOperatingRate,
+ status_t err = mOMXNode->setConfig(
+ (OMX_INDEXTYPE)OMX_IndexConfigOperatingRate,
&config, sizeof(config));
if (err != OK) {
ALOGI("codec does not support config operating rate (err %d)", err);
@@ -2371,8 +2278,8 @@
OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
InitOMXParams(¶ms);
params.nPortIndex = kPortIndexOutput;
- status_t err = mOMX->getConfig(
- mNode, (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, ¶ms, sizeof(params));
+ status_t err = mOMXNode->getConfig(
+ (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, ¶ms, sizeof(params));
if (err == OK) {
*intraRefreshPeriod = params.nRefreshPeriod;
return OK;
@@ -2383,8 +2290,8 @@
InitOMXParams(&refreshParams);
refreshParams.nPortIndex = kPortIndexOutput;
refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
- err = mOMX->getParameter(
- mNode, OMX_IndexParamVideoIntraRefresh, &refreshParams, sizeof(refreshParams));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamVideoIntraRefresh, &refreshParams, sizeof(refreshParams));
if (err != OK || refreshParams.nCirMBs == 0) {
*intraRefreshPeriod = 0;
return OK;
@@ -2396,8 +2303,8 @@
InitOMXParams(&def);
OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
def.nPortIndex = kPortIndexOutput;
- err = mOMX->getParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err != OK) {
*intraRefreshPeriod = 0;
return err;
@@ -2415,8 +2322,8 @@
InitOMXParams(¶ms);
params.nPortIndex = kPortIndexOutput;
params.nRefreshPeriod = intraRefreshPeriod;
- status_t err = mOMX->setConfig(
- mNode, (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, ¶ms, sizeof(params));
+ status_t err = mOMXNode->setConfig(
+ (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, ¶ms, sizeof(params));
if (err == OK) {
return OK;
}
@@ -2443,8 +2350,8 @@
InitOMXParams(&def);
OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
def.nPortIndex = kPortIndexOutput;
- err = mOMX->getParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err != OK) {
return err;
}
@@ -2454,8 +2361,9 @@
refreshParams.nCirMBs = divUp((divUp(width, 16u) * divUp(height, 16u)), intraRefreshPeriod);
}
- err = mOMX->setParameter(mNode, OMX_IndexParamVideoIntraRefresh,
- &refreshParams, sizeof(refreshParams));
+ err = mOMXNode->setParameter(
+ OMX_IndexParamVideoIntraRefresh,
+ &refreshParams, sizeof(refreshParams));
if (err != OK) {
return err;
}
@@ -2498,9 +2406,9 @@
InitOMXParams(&layerParams);
layerParams.nPortIndex = kPortIndexOutput;
- status_t err = mOMX->getParameter(
- mNode, (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
- &layerParams, sizeof(layerParams));
+ status_t err = mOMXNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
+ &layerParams, sizeof(layerParams));
if (err != OK) {
return err;
@@ -2520,8 +2428,8 @@
layerConfig.nBLayerCountActual = numBLayers;
layerConfig.bBitrateRatiosSpecified = OMX_FALSE;
- err = mOMX->setConfig(
- mNode, (OMX_INDEXTYPE)OMX_IndexConfigAndroidVideoTemporalLayering,
+ err = mOMXNode->setConfig(
+ (OMX_INDEXTYPE)OMX_IndexConfigAndroidVideoTemporalLayering,
&layerConfig, sizeof(layerConfig));
} else {
layerParams.ePattern = pattern;
@@ -2529,8 +2437,8 @@
layerParams.nBLayerCountActual = numBLayers;
layerParams.bBitrateRatiosSpecified = OMX_FALSE;
- err = mOMX->setParameter(
- mNode, (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
+ err = mOMXNode->setParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
&layerParams, sizeof(layerParams));
}
@@ -2547,8 +2455,8 @@
return err;
}
- err = mOMX->getParameter(
- mNode, (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
+ err = mOMXNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
&layerParams, sizeof(layerParams));
if (err == OK) {
@@ -2571,8 +2479,8 @@
InitOMXParams(&def);
def.nPortIndex = portIndex;
- status_t err = mOMX->getParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ status_t err = mOMXNode->getParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err != OK) {
return err;
@@ -2584,15 +2492,15 @@
def.nBufferSize = size;
- err = mOMX->setParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ err = mOMXNode->setParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err != OK) {
return err;
}
- err = mOMX->getParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err != OK) {
return err;
@@ -2614,9 +2522,8 @@
format.nPortIndex = portIndex;
for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
format.nIndex = index;
- status_t err = mOMX->getParameter(
- mNode, OMX_IndexParamAudioPortFormat,
- &format, sizeof(format));
+ status_t err = mOMXNode->getParameter(
+ OMX_IndexParamAudioPortFormat, &format, sizeof(format));
if (err != OK) {
return err;
@@ -2634,8 +2541,8 @@
}
}
- return mOMX->setParameter(
- mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format));
+ return mOMXNode->setParameter(
+ OMX_IndexParamAudioPortFormat, &format, sizeof(format));
}
status_t ACodec::setupAACCodec(
@@ -2667,8 +2574,8 @@
InitOMXParams(&def);
def.nPortIndex = kPortIndexOutput;
- err = mOMX->getParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err != OK) {
return err;
@@ -2677,8 +2584,8 @@
def.format.audio.bFlagErrorConcealment = OMX_TRUE;
def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
- err = mOMX->setParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ err = mOMXNode->setParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err != OK) {
return err;
@@ -2688,8 +2595,8 @@
InitOMXParams(&profile);
profile.nPortIndex = kPortIndexOutput;
- err = mOMX->getParameter(
- mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamAudioAac, &profile, sizeof(profile));
if (err != OK) {
return err;
@@ -2736,8 +2643,8 @@
}
- err = mOMX->setParameter(
- mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
+ err = mOMXNode->setParameter(
+ OMX_IndexParamAudioAac, &profile, sizeof(profile));
if (err != OK) {
return err;
@@ -2750,8 +2657,8 @@
InitOMXParams(&profile);
profile.nPortIndex = kPortIndexInput;
- err = mOMX->getParameter(
- mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamAudioAac, &profile, sizeof(profile));
if (err != OK) {
return err;
@@ -2775,10 +2682,12 @@
presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
presentation.nPCMLimiterEnable = pcmLimiterEnable;
- status_t res = mOMX->setParameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
+ status_t res = mOMXNode->setParameter(
+ OMX_IndexParamAudioAac, &profile, sizeof(profile));
if (res == OK) {
// optional parameters, will not cause configuration failure
- mOMX->setParameter(mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation,
+ mOMXNode->setParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation,
&presentation, sizeof(presentation));
} else {
ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res);
@@ -2805,11 +2714,8 @@
InitOMXParams(&def);
def.nPortIndex = kPortIndexInput;
- err = mOMX->getParameter(
- mNode,
- (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
- &def,
- sizeof(def));
+ err = mOMXNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, &def, sizeof(def));
if (err != OK) {
return err;
@@ -2818,11 +2724,8 @@
def.nChannels = numChannels;
def.nSampleRate = sampleRate;
- return mOMX->setParameter(
- mNode,
- (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
- &def,
- sizeof(def));
+ return mOMXNode->setParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, &def, sizeof(def));
}
status_t ACodec::setupEAC3Codec(
@@ -2843,11 +2746,8 @@
InitOMXParams(&def);
def.nPortIndex = kPortIndexInput;
- err = mOMX->getParameter(
- mNode,
- (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
- &def,
- sizeof(def));
+ err = mOMXNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, &def, sizeof(def));
if (err != OK) {
return err;
@@ -2856,11 +2756,8 @@
def.nChannels = numChannels;
def.nSampleRate = sampleRate;
- return mOMX->setParameter(
- mNode,
- (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
- &def,
- sizeof(def));
+ return mOMXNode->setParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, &def, sizeof(def));
}
static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
@@ -2913,8 +2810,8 @@
InitOMXParams(&def);
def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
- status_t err =
- mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+ status_t err = mOMXNode->getParameter(
+ OMX_IndexParamAudioAmr, &def, sizeof(def));
if (err != OK) {
return err;
@@ -2923,8 +2820,8 @@
def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
- err = mOMX->setParameter(
- mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+ err = mOMXNode->setParameter(
+ OMX_IndexParamAudioAmr, &def, sizeof(def));
if (err != OK) {
return err;
@@ -2954,13 +2851,13 @@
def.nPortIndex = kPortIndexOutput;
// configure compression level
- status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
+ status_t err = mOMXNode->getParameter(OMX_IndexParamAudioFlac, &def, sizeof(def));
if (err != OK) {
ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err);
return err;
}
def.nCompressionLevel = compressionLevel;
- err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
+ err = mOMXNode->setParameter(OMX_IndexParamAudioFlac, &def, sizeof(def));
if (err != OK) {
ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err);
return err;
@@ -2979,8 +2876,8 @@
InitOMXParams(&def);
def.nPortIndex = portIndex;
- status_t err = mOMX->getParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ status_t err = mOMXNode->getParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err != OK) {
return err;
@@ -2988,8 +2885,8 @@
def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
- err = mOMX->setParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ err = mOMXNode->setParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err != OK) {
return err;
@@ -2999,8 +2896,8 @@
InitOMXParams(&pcmParams);
pcmParams.nPortIndex = portIndex;
- err = mOMX->getParameter(
- mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
if (err != OK) {
return err;
@@ -3031,15 +2928,15 @@
return OMX_ErrorNone;
}
- err = mOMX->setParameter(
- mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
+ err = mOMXNode->setParameter(
+ OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
// if we could not set up raw format to non-16-bit, try with 16-bit
// NOTE: we will also verify this via readback, in case codec ignores these fields
if (err != OK && encoding != kAudioEncodingPcm16bit) {
pcmParams.eNumData = OMX_NumericalDataSigned;
pcmParams.nBitPerSample = 16;
- err = mOMX->setParameter(
- mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
+ err = mOMXNode->setParameter(
+ OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
}
return err;
}
@@ -3048,8 +2945,8 @@
int32_t audioHwSync, const sp<ANativeWindow> &nativeWindow) {
native_handle_t* sidebandHandle;
- status_t err = mOMX->configureVideoTunnelMode(
- mNode, kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle);
+ status_t err = mOMXNode->configureVideoTunnelMode(
+ kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle);
if (err != OK) {
ALOGE("configureVideoTunnelMode failed! (err %d).", err);
return err;
@@ -3078,8 +2975,8 @@
for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
format.nIndex = index;
- status_t err = mOMX->getParameter(
- mNode, OMX_IndexParamVideoPortFormat,
+ status_t err = mOMXNode->getParameter(
+ OMX_IndexParamVideoPortFormat,
&format, sizeof(format));
if (err != OK) {
@@ -3089,8 +2986,8 @@
// substitute back flexible color format to codec supported format
OMX_U32 flexibleEquivalent;
if (compressionFormat == OMX_VIDEO_CodingUnused
- && isFlexibleColorFormat(
- mOMX, mNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent)
+ && IsFlexibleColorFormat(
+ mOMXNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent)
&& colorFormat == flexibleEquivalent) {
ALOGI("[%s] using color format %#x in place of %#x",
mComponentName.c_str(), format.eColorFormat, colorFormat);
@@ -3133,9 +3030,8 @@
return UNKNOWN_ERROR;
}
- status_t err = mOMX->setParameter(
- mNode, OMX_IndexParamVideoPortFormat,
- &format, sizeof(format));
+ status_t err = mOMXNode->setParameter(
+ OMX_IndexParamVideoPortFormat, &format, sizeof(format));
return err;
}
@@ -3165,9 +3061,8 @@
for (OMX_U32 index = 0; ; ++index) {
format.nIndex = index;
- status_t err = mOMX->getParameter(
- mNode, OMX_IndexParamVideoPortFormat,
- &format, sizeof(format));
+ status_t err = mOMXNode->getParameter(
+ OMX_IndexParamVideoPortFormat, &format, sizeof(format));
if (err != OK) {
// no more formats, pick legacy format if found
if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) {
@@ -3193,16 +3088,15 @@
// find best legacy non-standard format
OMX_U32 flexibleEquivalent;
if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused
- && isFlexibleColorFormat(
- mOMX, mNode, format.eColorFormat, false /* usingNativeBuffers */,
+ && IsFlexibleColorFormat(
+ mOMXNode, format.eColorFormat, false /* usingNativeBuffers */,
&flexibleEquivalent)
&& flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) {
memcpy(&legacyFormat, &format, sizeof(format));
}
}
- return mOMX->setParameter(
- mNode, OMX_IndexParamVideoPortFormat,
- &format, sizeof(format));
+ return mOMXNode->setParameter(
+ OMX_IndexParamVideoPortFormat, &format, sizeof(format));
}
static const struct VideoCodingMapEntry {
@@ -3258,14 +3152,14 @@
status_t err;
ALOGD("Setting [%s] %s port buffer number: %d", mComponentName.c_str(),
portIndex == kPortIndexInput ? "input" : "output", bufferNum);
- err = mOMX->getParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err != OK) {
return err;
}
def.nBufferCountActual = bufferNum;
- err = mOMX->setParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ err = mOMXNode->setParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err != OK) {
// Component could reject this request.
ALOGW("Fail to set [%s] %s port buffer number: %d", mComponentName.c_str(),
@@ -3296,11 +3190,9 @@
params.nPortIndex = kPortIndexInput;
// Check if VP9 decoder advertises supported profiles.
params.nProfileIndex = 0;
- status_t err = mOMX->getParameter(
- mNode,
+ status_t err = mOMXNode->getParameter(
OMX_IndexParamVideoProfileLevelQuerySupported,
- ¶ms,
- sizeof(params));
+ ¶ms, sizeof(params));
mIsLegacyVP9Decoder = err != OK;
}
@@ -3389,8 +3281,8 @@
}
status_t ACodec::initDescribeColorAspectsIndex() {
- status_t err = mOMX->getExtensionIndex(
- mNode, "OMX.google.android.index.describeColorAspects", &mDescribeColorAspectsIndex);
+ status_t err = mOMXNode->getExtensionIndex(
+ "OMX.google.android.index.describeColorAspects", &mDescribeColorAspectsIndex);
if (err != OK) {
mDescribeColorAspectsIndex = (OMX_INDEXTYPE)0;
}
@@ -3400,7 +3292,7 @@
status_t ACodec::setCodecColorAspects(DescribeColorAspectsParams ¶ms, bool verify) {
status_t err = ERROR_UNSUPPORTED;
if (mDescribeColorAspectsIndex) {
- err = mOMX->setConfig(mNode, mDescribeColorAspectsIndex, ¶ms, sizeof(params));
+ err = mOMXNode->setConfig(mDescribeColorAspectsIndex, ¶ms, sizeof(params));
}
ALOGV("[%s] setting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
mComponentName.c_str(),
@@ -3445,7 +3337,7 @@
status_t ACodec::getCodecColorAspects(DescribeColorAspectsParams ¶ms) {
status_t err = ERROR_UNSUPPORTED;
if (mDescribeColorAspectsIndex) {
- err = mOMX->getConfig(mNode, mDescribeColorAspectsIndex, ¶ms, sizeof(params));
+ err = mOMXNode->getConfig(mDescribeColorAspectsIndex, ¶ms, sizeof(params));
}
ALOGV("[%s] got color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
mComponentName.c_str(),
@@ -3667,8 +3559,8 @@
}
status_t ACodec::initDescribeHDRStaticInfoIndex() {
- status_t err = mOMX->getExtensionIndex(
- mNode, "OMX.google.android.index.describeHDRStaticInfo", &mDescribeHDRStaticInfoIndex);
+ status_t err = mOMXNode->getExtensionIndex(
+ "OMX.google.android.index.describeHDRStaticInfo", &mDescribeHDRStaticInfoIndex);
if (err != OK) {
mDescribeHDRStaticInfoIndex = (OMX_INDEXTYPE)0;
}
@@ -3678,7 +3570,7 @@
status_t ACodec::setHDRStaticInfo(const DescribeHDRStaticInfoParams ¶ms) {
status_t err = ERROR_UNSUPPORTED;
if (mDescribeHDRStaticInfoIndex) {
- err = mOMX->setConfig(mNode, mDescribeHDRStaticInfoIndex, ¶ms, sizeof(params));
+ err = mOMXNode->setConfig(mDescribeHDRStaticInfoIndex, ¶ms, sizeof(params));
}
const HDRStaticInfo *info = ¶ms.sInfo;
@@ -3699,7 +3591,7 @@
status_t ACodec::getHDRStaticInfo(DescribeHDRStaticInfoParams ¶ms) {
status_t err = ERROR_UNSUPPORTED;
if (mDescribeHDRStaticInfoIndex) {
- err = mOMX->getConfig(mNode, mDescribeHDRStaticInfoIndex, ¶ms, sizeof(params));
+ err = mOMXNode->getConfig(mDescribeHDRStaticInfoIndex, ¶ms, sizeof(params));
}
ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeHDRStaticInfoIndex,
@@ -3738,8 +3630,8 @@
def.nPortIndex = kPortIndexInput;
- err = mOMX->getParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err != OK) {
return err;
@@ -3789,8 +3681,8 @@
video_def->eColorFormat = colorFormat;
}
- err = mOMX->setParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ err = mOMXNode->setParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err != OK) {
ALOGE("[%s] failed to set input port definition parameters.",
@@ -3820,8 +3712,8 @@
def.nPortIndex = kPortIndexOutput;
- err = mOMX->getParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err != OK) {
return err;
@@ -3834,8 +3726,8 @@
video_def->eCompressionFormat = compressionFormat;
video_def->eColorFormat = OMX_COLOR_FormatUnused;
- err = mOMX->setParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ err = mOMXNode->setParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err != OK) {
ALOGE("[%s] failed to set output port definition parameters.",
@@ -3964,9 +3856,8 @@
params.nAirRef = ref;
}
- status_t err = mOMX->setParameter(
- mNode, OMX_IndexParamVideoIntraRefresh,
- ¶ms, sizeof(params));
+ status_t err = mOMXNode->setParameter(
+ OMX_IndexParamVideoIntraRefresh, ¶ms, sizeof(params));
return err;
}
@@ -4029,8 +3920,8 @@
InitOMXParams(&mpeg4type);
mpeg4type.nPortIndex = kPortIndexOutput;
- status_t err = mOMX->getParameter(
- mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
+ status_t err = mOMXNode->getParameter(
+ OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
if (err != OK) {
return err;
@@ -4072,8 +3963,8 @@
mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
}
- err = mOMX->setParameter(
- mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
+ err = mOMXNode->setParameter(
+ OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
if (err != OK) {
return err;
@@ -4111,8 +4002,8 @@
InitOMXParams(&h263type);
h263type.nPortIndex = kPortIndexOutput;
- status_t err = mOMX->getParameter(
- mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
+ status_t err = mOMXNode->getParameter(
+ OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
if (err != OK) {
return err;
@@ -4149,8 +4040,8 @@
h263type.nPictureHeaderRepetition = 0;
h263type.nGOBHeaderInterval = 0;
- err = mOMX->setParameter(
- mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
+ err = mOMXNode->setParameter(
+ OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
if (err != OK) {
return err;
@@ -4251,8 +4142,8 @@
InitOMXParams(&h264type);
h264type.nPortIndex = kPortIndexOutput;
- err = mOMX->getParameter(
- mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
if (err != OK) {
return err;
@@ -4341,8 +4232,8 @@
h264type.bMBAFF = OMX_FALSE;
h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
- err = mOMX->setParameter(
- mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
+ err = mOMXNode->setParameter(
+ OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
if (err != OK) {
return err;
@@ -4358,8 +4249,8 @@
OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE layering;
InitOMXParams(&layering);
layering.nPortIndex = kPortIndexOutput;
- if (mOMX->getParameter(
- mNode, (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
+ if (mOMXNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
&layering, sizeof(layering)) == OK
&& layering.eSupportedPatterns
&& layering.nBLayerCountMax == 0) {
@@ -4367,8 +4258,8 @@
h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames);
h264type.nAllowedPictureTypes &= ~OMX_VIDEO_PictureTypeB;
ALOGI("disabling B-frames");
- err = mOMX->setParameter(
- mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
+ err = mOMXNode->setParameter(
+ OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
if (err != OK) {
return err;
@@ -4403,8 +4294,8 @@
hevcType.nPortIndex = kPortIndexOutput;
status_t err = OK;
- err = mOMX->getParameter(
- mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
+ err = mOMXNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
if (err != OK) {
return err;
}
@@ -4427,8 +4318,8 @@
// TODO: finer control?
hevcType.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate) + 1;
- err = mOMX->setParameter(
- mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
+ err = mOMXNode->setParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
if (err != OK) {
return err;
}
@@ -4496,8 +4387,8 @@
OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
InitOMXParams(&vp8type);
vp8type.nPortIndex = kPortIndexOutput;
- status_t err = mOMX->getParameter(
- mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
+ status_t err = mOMXNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
&vp8type, sizeof(vp8type));
if (err == OK) {
@@ -4517,8 +4408,8 @@
vp8type.nMaxQuantizer = 63;
}
- err = mOMX->setParameter(
- mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
+ err = mOMXNode->setParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
&vp8type, sizeof(vp8type));
if (err != OK) {
ALOGW("Extended VP8 parameters set failed: %d", err);
@@ -4542,11 +4433,9 @@
for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
params.nProfileIndex = index;
- status_t err = mOMX->getParameter(
- mNode,
+ status_t err = mOMXNode->getParameter(
OMX_IndexParamVideoProfileLevelQuerySupported,
- ¶ms,
- sizeof(params));
+ ¶ms, sizeof(params));
if (err != OK) {
return err;
@@ -4574,9 +4463,8 @@
InitOMXParams(&bitrateType);
bitrateType.nPortIndex = kPortIndexOutput;
- status_t err = mOMX->getParameter(
- mNode, OMX_IndexParamVideoBitrate,
- &bitrateType, sizeof(bitrateType));
+ status_t err = mOMXNode->getParameter(
+ OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType));
if (err != OK) {
return err;
@@ -4585,9 +4473,8 @@
bitrateType.eControlRate = bitrateMode;
bitrateType.nTargetBitrate = bitrate;
- return mOMX->setParameter(
- mNode, OMX_IndexParamVideoBitrate,
- &bitrateType, sizeof(bitrateType));
+ return mOMXNode->setParameter(
+ OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType));
}
status_t ACodec::setupErrorCorrectionParameters() {
@@ -4595,8 +4482,8 @@
InitOMXParams(&errorCorrectionType);
errorCorrectionType.nPortIndex = kPortIndexOutput;
- status_t err = mOMX->getParameter(
- mNode, OMX_IndexParamVideoErrorCorrection,
+ status_t err = mOMXNode->getParameter(
+ OMX_IndexParamVideoErrorCorrection,
&errorCorrectionType, sizeof(errorCorrectionType));
if (err != OK) {
@@ -4609,8 +4496,8 @@
errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
errorCorrectionType.bEnableRVLC = OMX_FALSE;
- return mOMX->setParameter(
- mNode, OMX_IndexParamVideoErrorCorrection,
+ return mOMXNode->setParameter(
+ OMX_IndexParamVideoErrorCorrection,
&errorCorrectionType, sizeof(errorCorrectionType));
}
@@ -4624,8 +4511,8 @@
OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
- status_t err = mOMX->getParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ status_t err = mOMXNode->getParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err != OK) {
return err;
}
@@ -4654,18 +4541,18 @@
}
}
- err = mOMX->setParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ err = mOMXNode->setParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
return err;
}
status_t ACodec::initNativeWindow() {
if (mNativeWindow != NULL) {
- return mOMX->enableNativeBuffers(mNode, kPortIndexOutput, OMX_TRUE /* graphic */, OMX_TRUE);
+ return mOMXNode->enableNativeBuffers(kPortIndexOutput, OMX_TRUE /* graphic */, OMX_TRUE);
}
- mOMX->enableNativeBuffers(mNode, kPortIndexOutput, OMX_TRUE /* graphic */, OMX_FALSE);
+ mOMXNode->enableNativeBuffers(kPortIndexOutput, OMX_TRUE /* graphic */, OMX_FALSE);
return OK;
}
@@ -4747,195 +4634,13 @@
}
}
-// static
-bool ACodec::describeDefaultColorFormat(DescribeColorFormat2Params ¶ms) {
- MediaImage2 &image = params.sMediaImage;
- memset(&image, 0, sizeof(image));
-
- image.mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
- image.mNumPlanes = 0;
-
- const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat;
- image.mWidth = params.nFrameWidth;
- image.mHeight = params.nFrameHeight;
-
- // only supporting YUV420
- if (fmt != OMX_COLOR_FormatYUV420Planar &&
- fmt != OMX_COLOR_FormatYUV420PackedPlanar &&
- fmt != OMX_COLOR_FormatYUV420SemiPlanar &&
- fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar &&
- fmt != (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_YV12) {
- ALOGW("do not know color format 0x%x = %d", fmt, fmt);
- return false;
- }
-
- // TEMPORARY FIX for some vendors that advertise sliceHeight as 0
- if (params.nStride != 0 && params.nSliceHeight == 0) {
- ALOGW("using sliceHeight=%u instead of what codec advertised (=0)",
- params.nFrameHeight);
- params.nSliceHeight = params.nFrameHeight;
- }
-
- // we need stride and slice-height to be non-zero and sensible. These values were chosen to
- // prevent integer overflows further down the line, and do not indicate support for
- // 32kx32k video.
- if (params.nStride == 0 || params.nSliceHeight == 0
- || params.nStride > 32768 || params.nSliceHeight > 32768) {
- ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u",
- fmt, fmt, params.nStride, params.nSliceHeight);
- return false;
- }
-
- // set-up YUV format
- image.mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV;
- image.mNumPlanes = 3;
- image.mBitDepth = 8;
- image.mBitDepthAllocated = 8;
- image.mPlane[image.Y].mOffset = 0;
- image.mPlane[image.Y].mColInc = 1;
- image.mPlane[image.Y].mRowInc = params.nStride;
- image.mPlane[image.Y].mHorizSubsampling = 1;
- image.mPlane[image.Y].mVertSubsampling = 1;
-
- switch ((int)fmt) {
- case HAL_PIXEL_FORMAT_YV12:
- if (params.bUsingNativeBuffers) {
- size_t ystride = align(params.nStride, 16);
- size_t cstride = align(params.nStride / 2, 16);
- image.mPlane[image.Y].mRowInc = ystride;
-
- image.mPlane[image.V].mOffset = ystride * params.nSliceHeight;
- image.mPlane[image.V].mColInc = 1;
- image.mPlane[image.V].mRowInc = cstride;
- image.mPlane[image.V].mHorizSubsampling = 2;
- image.mPlane[image.V].mVertSubsampling = 2;
-
- image.mPlane[image.U].mOffset = image.mPlane[image.V].mOffset
- + (cstride * params.nSliceHeight / 2);
- image.mPlane[image.U].mColInc = 1;
- image.mPlane[image.U].mRowInc = cstride;
- image.mPlane[image.U].mHorizSubsampling = 2;
- image.mPlane[image.U].mVertSubsampling = 2;
- break;
- } else {
- // fall through as YV12 is used for YUV420Planar by some codecs
- }
-
- case OMX_COLOR_FormatYUV420Planar:
- case OMX_COLOR_FormatYUV420PackedPlanar:
- image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
- image.mPlane[image.U].mColInc = 1;
- image.mPlane[image.U].mRowInc = params.nStride / 2;
- image.mPlane[image.U].mHorizSubsampling = 2;
- image.mPlane[image.U].mVertSubsampling = 2;
-
- image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset
- + (params.nStride * params.nSliceHeight / 4);
- image.mPlane[image.V].mColInc = 1;
- image.mPlane[image.V].mRowInc = params.nStride / 2;
- image.mPlane[image.V].mHorizSubsampling = 2;
- image.mPlane[image.V].mVertSubsampling = 2;
- break;
-
- case OMX_COLOR_FormatYUV420SemiPlanar:
- // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder
- case OMX_COLOR_FormatYUV420PackedSemiPlanar:
- // NV12
- image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
- image.mPlane[image.U].mColInc = 2;
- image.mPlane[image.U].mRowInc = params.nStride;
- image.mPlane[image.U].mHorizSubsampling = 2;
- image.mPlane[image.U].mVertSubsampling = 2;
-
- image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1;
- image.mPlane[image.V].mColInc = 2;
- image.mPlane[image.V].mRowInc = params.nStride;
- image.mPlane[image.V].mHorizSubsampling = 2;
- image.mPlane[image.V].mVertSubsampling = 2;
- break;
-
- default:
- TRESPASS();
- }
- return true;
-}
-
-// static
-bool ACodec::describeColorFormat(
- const sp<IOMX> &omx, IOMX::node_id node,
- DescribeColorFormat2Params &describeParams)
-{
- OMX_INDEXTYPE describeColorFormatIndex;
- if (omx->getExtensionIndex(
- node, "OMX.google.android.index.describeColorFormat",
- &describeColorFormatIndex) == OK) {
- DescribeColorFormatParams describeParamsV1(describeParams);
- if (omx->getParameter(
- node, describeColorFormatIndex,
- &describeParamsV1, sizeof(describeParamsV1)) == OK) {
- describeParams.initFromV1(describeParamsV1);
- return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
- }
- } else if (omx->getExtensionIndex(
- node, "OMX.google.android.index.describeColorFormat2", &describeColorFormatIndex) == OK
- && omx->getParameter(
- node, describeColorFormatIndex, &describeParams, sizeof(describeParams)) == OK) {
- return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
- }
-
- return describeDefaultColorFormat(describeParams);
-}
-
-// static
-bool ACodec::isFlexibleColorFormat(
- const sp<IOMX> &omx, IOMX::node_id node,
- uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) {
- DescribeColorFormat2Params describeParams;
- InitOMXParams(&describeParams);
- describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
- // reasonable dummy values
- describeParams.nFrameWidth = 128;
- describeParams.nFrameHeight = 128;
- describeParams.nStride = 128;
- describeParams.nSliceHeight = 128;
- describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers;
-
- CHECK(flexibleEquivalent != NULL);
-
- if (!describeColorFormat(omx, node, describeParams)) {
- return false;
- }
-
- const MediaImage2 &img = describeParams.sMediaImage;
- if (img.mType == MediaImage2::MEDIA_IMAGE_TYPE_YUV) {
- if (img.mNumPlanes != 3
- || img.mPlane[img.Y].mHorizSubsampling != 1
- || img.mPlane[img.Y].mVertSubsampling != 1) {
- return false;
- }
-
- // YUV 420
- if (img.mPlane[img.U].mHorizSubsampling == 2
- && img.mPlane[img.U].mVertSubsampling == 2
- && img.mPlane[img.V].mHorizSubsampling == 2
- && img.mPlane[img.V].mVertSubsampling == 2) {
- // possible flexible YUV420 format
- if (img.mBitDepth <= 8) {
- *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible;
- return true;
- }
- }
- }
- return false;
-}
-
status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> ¬ify) {
const char *niceIndex = portIndex == kPortIndexInput ? "input" : "output";
OMX_PARAM_PORTDEFINITIONTYPE def;
InitOMXParams(&def);
def.nPortIndex = portIndex;
- status_t err = mOMX->getParameter(mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ status_t err = mOMXNode->getParameter(OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err != OK) {
return err;
}
@@ -4969,7 +4674,7 @@
describeParams.nSliceHeight = videoDef->nSliceHeight;
describeParams.bUsingNativeBuffers = OMX_FALSE;
- if (describeColorFormat(mOMX, mNode, describeParams)) {
+ if (DescribeColorFormat(mOMXNode, describeParams)) {
notify->setBuffer(
"image-data",
ABuffer::CreateAsCopy(
@@ -4994,8 +4699,7 @@
InitOMXParams(&rect);
rect.nPortIndex = portIndex;
- if (mOMX->getConfig(
- mNode,
+ if (mOMXNode->getConfig(
(portIndex == kPortIndexOutput ?
OMX_IndexConfigCommonOutputCrop :
OMX_IndexConfigCommonInputCrop),
@@ -5051,8 +4755,7 @@
OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
InitOMXParams(&vp8type);
vp8type.nPortIndex = kPortIndexOutput;
- status_t err = mOMX->getParameter(
- mNode,
+ status_t err = mOMXNode->getParameter(
(OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
&vp8type,
sizeof(vp8type));
@@ -5121,8 +4824,8 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- err = mOMX->getParameter(
- mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamAudioPcm, ¶ms, sizeof(params));
if (err != OK) {
return err;
}
@@ -5169,8 +4872,8 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- err = mOMX->getParameter(
- mNode, OMX_IndexParamAudioAac, ¶ms, sizeof(params));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamAudioAac, ¶ms, sizeof(params));
if (err != OK) {
return err;
}
@@ -5187,8 +4890,8 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- err = mOMX->getParameter(
- mNode, OMX_IndexParamAudioAmr, ¶ms, sizeof(params));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamAudioAmr, ¶ms, sizeof(params));
if (err != OK) {
return err;
}
@@ -5210,8 +4913,8 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- err = mOMX->getParameter(
- mNode, OMX_IndexParamAudioFlac, ¶ms, sizeof(params));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamAudioFlac, ¶ms, sizeof(params));
if (err != OK) {
return err;
}
@@ -5228,8 +4931,8 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- err = mOMX->getParameter(
- mNode, OMX_IndexParamAudioMp3, ¶ms, sizeof(params));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamAudioMp3, ¶ms, sizeof(params));
if (err != OK) {
return err;
}
@@ -5246,8 +4949,8 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- err = mOMX->getParameter(
- mNode, OMX_IndexParamAudioVorbis, ¶ms, sizeof(params));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamAudioVorbis, ¶ms, sizeof(params));
if (err != OK) {
return err;
}
@@ -5264,8 +4967,8 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- err = mOMX->getParameter(
- mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
+ err = mOMXNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
¶ms, sizeof(params));
if (err != OK) {
return err;
@@ -5283,8 +4986,8 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- err = mOMX->getParameter(
- mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
+ err = mOMXNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
¶ms, sizeof(params));
if (err != OK) {
return err;
@@ -5302,8 +5005,8 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- err = mOMX->getParameter(
- mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
+ err = mOMXNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
¶ms, sizeof(params));
if (err != OK) {
return err;
@@ -5321,8 +5024,8 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- err = mOMX->getParameter(
- mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, ¶ms, sizeof(params));
+ err = mOMXNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, ¶ms, sizeof(params));
if (err != OK) {
return err;
}
@@ -5348,8 +5051,8 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- err = mOMX->getParameter(
- mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params));
+ err = mOMXNode->getParameter(
+ OMX_IndexParamAudioPcm, ¶ms, sizeof(params));
if (err != OK) {
return err;
}
@@ -5522,11 +5225,6 @@
notify->post();
}
-////////////////////////////////////////////////////////////////////////////////
-
-ACodec::PortDescription::PortDescription() {
-}
-
status_t ACodec::requestIDRFrame() {
if (!mIsEncoder) {
return ERROR_UNSUPPORTED;
@@ -5538,15 +5236,19 @@
params.nPortIndex = kPortIndexOutput;
params.IntraRefreshVOP = OMX_TRUE;
- return mOMX->setConfig(
- mNode,
+ return mOMXNode->setConfig(
OMX_IndexConfigVideoIntraVOPRefresh,
¶ms,
sizeof(params));
}
+////////////////////////////////////////////////////////////////////////////////
+
+ACodec::PortDescription::PortDescription() {
+}
+
void ACodec::PortDescription::addBuffer(
- IOMX::buffer_id id, const sp<ABuffer> &buffer,
+ IOMX::buffer_id id, const sp<MediaCodecBuffer> &buffer,
const sp<NativeHandle> &handle, const sp<RefBase> &memRef) {
mBufferIDs.push_back(id);
mBuffers.push_back(buffer);
@@ -5562,7 +5264,7 @@
return mBufferIDs.itemAt(index);
}
-sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
+sp<MediaCodecBuffer> ACodec::PortDescription::bufferAt(size_t index) const {
return mBuffers.itemAt(index);
}
@@ -5646,6 +5348,7 @@
{
// This will result in kFlagSawMediaServerDie handling in MediaCodec.
ALOGE("OMX/mediaserver died, signalling error!");
+ mCodec->mGraphicBufferSource.clear();
mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
break;
}
@@ -5654,7 +5357,7 @@
{
ALOGI("[%s] forcing the release of codec",
mCodec->mComponentName.c_str());
- status_t err = mCodec->mOMX->freeNode(mCodec->mNode);
+ status_t err = mCodec->mOMXNode->freeNode();
ALOGE_IF("[%s] failed to release codec instance: err=%d",
mCodec->mComponentName.c_str(), err);
sp<AMessage> notify = mCodec->mNotify->dup();
@@ -5673,16 +5376,17 @@
bool ACodec::BaseState::checkOMXMessage(const sp<AMessage> &msg) {
// there is a possibility that this is an outstanding message for a
// codec that we have already destroyed
- if (mCodec->mNode == 0) {
+ if (mCodec->mOMXNode == NULL) {
ALOGI("ignoring message as already freed component: %s",
msg->debugString().c_str());
return false;
}
- IOMX::node_id nodeID;
- CHECK(msg->findInt32("node", (int32_t*)&nodeID));
- if (nodeID != mCodec->mNode) {
- ALOGE("Unexpected message for nodeID: %u, should have been %u", nodeID, mCodec->mNode);
+ int32_t generation;
+ CHECK(msg->findInt32("generation", (int32_t*)&generation));
+ if (generation != mCodec->mNodeGeneration) {
+ ALOGW("Unexpected message for component: %s, gen %u, cur %u",
+ msg->debugString().c_str(), generation, mCodec->mNodeGeneration);
return false;
}
return true;
@@ -5800,11 +5504,7 @@
bool ACodec::BaseState::onOMXEvent(
OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
if (event == OMX_EventDataSpaceChanged) {
- ColorAspects aspects;
- aspects.mRange = (ColorAspects::Range)((data2 >> 24) & 0xFF);
- aspects.mPrimaries = (ColorAspects::Primaries)((data2 >> 16) & 0xFF);
- aspects.mMatrixCoeffs = (ColorAspects::MatrixCoeffs)((data2 >> 8) & 0xFF);
- aspects.mTransfer = (ColorAspects::Transfer)(data2 & 0xFF);
+ ColorAspects aspects = ColorUtils::unpackToColorAspects(data2);
mCodec->onDataSpaceChanged((android_dataspace)data1, aspects);
return true;
@@ -5891,7 +5591,7 @@
notify->setInt32("buffer-id", info->mBufferID);
info->mData->meta()->clear();
- notify->setBuffer("buffer", info->mData);
+ notify->setObject("buffer", info->mData);
sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec);
reply->setInt32("buffer-id", info->mBufferID);
@@ -5906,12 +5606,13 @@
void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
IOMX::buffer_id bufferID;
CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
- sp<ABuffer> buffer;
+ sp<MediaCodecBuffer> buffer;
int32_t err = OK;
bool eos = false;
PortMode mode = getPortMode(kPortIndexInput);
- if (!msg->findBuffer("buffer", &buffer)) {
+ sp<RefBase> obj;
+ if (!msg->findObject("buffer", &obj)) {
/* these are unfilled buffers returned by client */
CHECK(msg->findInt32("err", &err));
@@ -5925,6 +5626,8 @@
}
buffer.clear();
+ } else {
+ buffer = static_cast<MediaCodecBuffer *>(obj.get());
}
int32_t tmp;
@@ -6050,8 +5753,8 @@
if (info->mCodecData->size() >= sizeof(VideoNativeHandleMetadata)) {
VideoNativeHandleMetadata *vnhmd =
(VideoNativeHandleMetadata*)info->mCodecData->base();
- err2 = mCodec->mOMX->updateNativeHandleInMeta(
- mCodec->mNode, kPortIndexInput,
+ err2 = mCodec->mOMXNode->updateNativeHandleInMeta(
+ mCodec->kPortIndexInput,
NativeHandle::create(vnhmd->pHandle, false /* ownsHandle */),
bufferID);
}
@@ -6059,8 +5762,8 @@
case kMetadataBufferTypeANWBuffer:
if (info->mCodecData->size() >= sizeof(VideoNativeMetadata)) {
VideoNativeMetadata *vnmd = (VideoNativeMetadata*)info->mCodecData->base();
- err2 = mCodec->mOMX->updateGraphicBufferInMeta(
- mCodec->mNode, kPortIndexInput,
+ err2 = mCodec->mOMXNode->updateGraphicBufferInMeta(
+ mCodec->kPortIndexInput,
new GraphicBuffer(vnmd->pBuffer, false /* keepOwnership */),
bufferID);
}
@@ -6075,8 +5778,7 @@
}
if (err2 == OK) {
- err2 = mCodec->mOMX->emptyBuffer(
- mCodec->mNode,
+ err2 = mCodec->mOMXNode->emptyBuffer(
bufferID,
0,
info->mCodecData->size(),
@@ -6113,8 +5815,7 @@
mCodec->mComponentName.c_str(), bufferID);
info->checkReadFence("onInputBufferFilled");
- status_t err2 = mCodec->mOMX->emptyBuffer(
- mCodec->mNode,
+ status_t err2 = mCodec->mOMXNode->emptyBuffer(
bufferID,
0,
0,
@@ -6244,7 +5945,7 @@
ALOGV("[%s] calling fillBuffer %u",
mCodec->mComponentName.c_str(), info->mBufferID);
- err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd);
+ err = mCodec->mOMXNode->fillBuffer(info->mBufferID, info->mFenceFd);
info->mFenceFd = -1;
if (err != OK) {
mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
@@ -6257,6 +5958,7 @@
sp<AMessage> reply =
new AMessage(kWhatOutputBufferDrained, mCodec);
+ sp<MediaCodecBuffer> buffer = info->mData;
if (mCodec->mOutputFormat != mCodec->mLastOutputFormat && rangeLength > 0) {
// pretend that output format has changed on the first frame (we used to do this)
@@ -6274,8 +5976,8 @@
if (mCodec->usingMetadataOnEncoderOutput()) {
native_handle_t *handle = NULL;
VideoNativeHandleMetadata &nativeMeta =
- *(VideoNativeHandleMetadata *)info->mData->data();
- if (info->mData->size() >= sizeof(nativeMeta)
+ *(VideoNativeHandleMetadata *)buffer->data();
+ if (buffer->size() >= sizeof(nativeMeta)
&& nativeMeta.eType == kMetadataBufferTypeNativeHandleSource) {
#ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
// handle is only valid on 32-bit/mediaserver process
@@ -6284,16 +5986,16 @@
handle = (native_handle_t *)nativeMeta.pHandle;
#endif
}
- info->mData->meta()->setPointer("handle", handle);
- info->mData->meta()->setInt32("rangeOffset", rangeOffset);
- info->mData->meta()->setInt32("rangeLength", rangeLength);
- } else if (info->mData == info->mCodecData) {
- info->mData->setRange(rangeOffset, rangeLength);
+ buffer->meta()->setPointer("handle", handle);
+ buffer->meta()->setInt32("rangeOffset", rangeOffset);
+ buffer->meta()->setInt32("rangeLength", rangeLength);
+ } else if (buffer == info->mCodecData) {
+ buffer->setRange(rangeOffset, rangeLength);
} else {
info->mCodecData->setRange(rangeOffset, rangeLength);
// in this case we know that mConverter is not null
status_t err = mCodec->mConverter[kPortIndexOutput]->convert(
- info->mCodecData, info->mData);
+ info->mCodecData, buffer);
if (err != OK) {
mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
return true;
@@ -6308,14 +6010,14 @@
#endif
if (mCodec->mSkipCutBuffer != NULL) {
- mCodec->mSkipCutBuffer->submit(info->mData);
+ mCodec->mSkipCutBuffer->submit(buffer);
}
- info->mData->meta()->setInt64("timeUs", timeUs);
+ buffer->meta()->setInt64("timeUs", timeUs);
sp<AMessage> notify = mCodec->mNotify->dup();
notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
notify->setInt32("buffer-id", info->mBufferID);
- notify->setBuffer("buffer", info->mData);
+ notify->setObject("buffer", buffer);
notify->setInt32("flags", flags);
reply->setInt32("buffer-id", info->mBufferID);
@@ -6358,6 +6060,11 @@
void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
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());
+ }
ssize_t index;
BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
BufferInfo::Status status = BufferInfo::getSafeStatus(info);
@@ -6388,13 +6095,13 @@
int32_t render;
if (mCodec->mNativeWindow != NULL
&& msg->findInt32("render", &render) && render != 0
- && info->mData != NULL && info->mData->size() != 0) {
+ && buffer != NULL && buffer->size() != 0) {
ATRACE_NAME("render");
// The client wants this buffer to be rendered.
// save buffers sent to the surface so we can get render time when they return
int64_t mediaTimeUs = -1;
- info->mData->meta()->findInt64("timeUs", &mediaTimeUs);
+ buffer->meta()->findInt64("timeUs", &mediaTimeUs);
if (mediaTimeUs >= 0) {
mCodec->mRenderTracker.onFrameQueued(
mediaTimeUs, info->mGraphicBuffer, new Fence(::dup(info->mFenceFd)));
@@ -6403,7 +6110,7 @@
int64_t timestampNs = 0;
if (!msg->findInt64("timestampNs", ×tampNs)) {
// use media timestamp if client did not request a specific render timestamp
- if (info->mData->meta()->findInt64("timeUs", ×tampNs)) {
+ if (buffer->meta()->findInt64("timeUs", ×tampNs)) {
ALOGV("using buffer PTS of %lld", (long long)timestampNs);
timestampNs *= 1000;
}
@@ -6428,7 +6135,7 @@
}
} else {
if (mCodec->mNativeWindow != NULL &&
- (info->mData == NULL || info->mData->size() != 0)) {
+ (buffer == NULL || buffer->size() != 0)) {
// move read fence into write fence to avoid clobbering
info->mIsReadFence = false;
ATRACE_NAME("frame-drop");
@@ -6466,8 +6173,8 @@
ALOGV("[%s] calling fillBuffer %u",
mCodec->mComponentName.c_str(), info->mBufferID);
info->checkWriteFence("onOutputBufferDrained::RESUBMIT_BUFFERS");
- status_t err = mCodec->mOMX->fillBuffer(
- mCodec->mNode, info->mBufferID, info->mFenceFd);
+ status_t err = mCodec->mOMXNode->fillBuffer(
+ info->mBufferID, info->mFenceFd);
info->mFenceFd = -1;
if (err == OK) {
info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
@@ -6504,16 +6211,18 @@
ALOGV("Now uninitialized");
if (mDeathNotifier != NULL) {
- mCodec->mNodeBinder->unlinkToDeath(mDeathNotifier);
+ if (mCodec->mOMXNode != NULL) {
+ sp<IBinder> binder = IInterface::asBinder(mCodec->mOMXNode);
+ binder->unlinkToDeath(mDeathNotifier);
+ }
mDeathNotifier.clear();
}
mCodec->mUsingNativeWindow = false;
mCodec->mNativeWindow.clear();
mCodec->mNativeWindowUsageBits = 0;
- mCodec->mNode = 0;
mCodec->mOMX.clear();
- mCodec->mQuirks = 0;
+ mCodec->mOMXNode.clear();
mCodec->mFlags = 0;
mCodec->mInputMetadataType = kMetadataBufferTypeInvalid;
mCodec->mOutputMetadataType = kMetadataBufferTypeInvalid;
@@ -6592,7 +6301,7 @@
bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
ALOGV("onAllocateComponent");
- CHECK(mCodec->mNode == 0);
+ CHECK(mCodec->mOMXNode == NULL);
OMXClient client;
if (client.connect() != OK) {
@@ -6631,7 +6340,7 @@
}
sp<CodecObserver> observer = new CodecObserver;
- IOMX::node_id node = 0;
+ sp<IOMXNode> omxNode;
status_t err = NAME_NOT_FOUND;
for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
@@ -6642,7 +6351,7 @@
pid_t tid = gettid();
int prevPriority = androidGetThreadPriority(tid);
androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
- err = omx->allocateNode(componentName.c_str(), observer, &mCodec->mNodeBinder, &node);
+ err = omx->allocateNode(componentName.c_str(), observer, &omxNode);
androidSetThreadPriority(tid, prevPriority);
if (err == OK) {
@@ -6651,10 +6360,10 @@
ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
}
- node = 0;
+ omxNode = NULL;
}
- if (node == 0) {
+ if (omxNode == NULL) {
if (!mime.empty()) {
ALOGE("Unable to instantiate a %scoder for type '%s' with err %#x.",
encoder ? "en" : "de", mime.c_str(), err);
@@ -6667,14 +6376,14 @@
}
mDeathNotifier = new DeathNotifier(notify);
- if (mCodec->mNodeBinder == NULL ||
- mCodec->mNodeBinder->linkToDeath(mDeathNotifier) != OK) {
+ if (IInterface::asBinder(omxNode)->linkToDeath(mDeathNotifier) != OK) {
// This was a local binder, if it dies so do we, we won't care
// about any notifications in the afterlife.
mDeathNotifier.clear();
}
notify = new AMessage(kWhatOMXMessageList, mCodec);
+ notify->setInt32("generation", ++mCodec->mNodeGeneration);
observer->setNotificationMessage(notify);
mCodec->mComponentName = componentName;
@@ -6687,9 +6396,9 @@
mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
}
- mCodec->mQuirks = quirks;
+ omxNode->setQuirks(quirks);
mCodec->mOMX = omx;
- mCodec->mNode = node;
+ mCodec->mOMXNode = omxNode;
{
sp<AMessage> notify = mCodec->mNotify->dup();
@@ -6723,6 +6432,7 @@
mCodec->mInputFormat.clear();
mCodec->mOutputFormat.clear();
mCodec->mBaseOutputFormat.clear();
+ mCodec->mGraphicBufferSource.clear();
if (mCodec->mShutdownInProgress) {
bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
@@ -6739,7 +6449,7 @@
void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
if (!keepComponentAllocated) {
- (void)mCodec->mOMX->freeNode(mCodec->mNode);
+ (void)mCodec->mOMXNode->freeNode();
mCodec->changeState(mCodec->mUninitializedState);
}
@@ -6818,7 +6528,7 @@
const sp<AMessage> &msg) {
ALOGV("onConfigureComponent");
- CHECK(mCodec->mNode != 0);
+ CHECK(mCodec->mOMXNode != NULL);
status_t err = OK;
AString mime;
@@ -6847,97 +6557,89 @@
}
status_t ACodec::LoadedState::setupInputSurface() {
- status_t err = OK;
+ if (mCodec->mGraphicBufferSource == NULL) {
+ return BAD_VALUE;
+ }
+
+ android_dataspace dataSpace;
+ status_t err =
+ mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace);
+ if (err != OK) {
+ ALOGE("Failed to get default data space");
+ return err;
+ }
+
+ err = statusFromBinderStatus(
+ mCodec->mGraphicBufferSource->configure(mCodec->mOMXNode, dataSpace));
+ if (err != OK) {
+ ALOGE("[%s] Unable to configure for node (err %d)",
+ mCodec->mComponentName.c_str(), err);
+ return err;
+ }
if (mCodec->mRepeatFrameDelayUs > 0ll) {
- err = mCodec->mOMX->setInternalOption(
- mCodec->mNode,
- kPortIndexInput,
- IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY,
- &mCodec->mRepeatFrameDelayUs,
- sizeof(mCodec->mRepeatFrameDelayUs));
+ err = statusFromBinderStatus(
+ mCodec->mGraphicBufferSource->setRepeatPreviousFrameDelayUs(
+ mCodec->mRepeatFrameDelayUs));
if (err != OK) {
ALOGE("[%s] Unable to configure option to repeat previous "
"frames (err %d)",
- mCodec->mComponentName.c_str(),
- err);
+ mCodec->mComponentName.c_str(), err);
return err;
}
}
if (mCodec->mMaxPtsGapUs > 0ll) {
- err = mCodec->mOMX->setInternalOption(
- mCodec->mNode,
- kPortIndexInput,
- IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP,
- &mCodec->mMaxPtsGapUs,
- sizeof(mCodec->mMaxPtsGapUs));
+ err = statusFromBinderStatus(
+ mCodec->mGraphicBufferSource->setMaxTimestampGapUs(
+ mCodec->mMaxPtsGapUs));
if (err != OK) {
ALOGE("[%s] Unable to configure max timestamp gap (err %d)",
- mCodec->mComponentName.c_str(),
- err);
+ mCodec->mComponentName.c_str(), err);
return err;
}
}
if (mCodec->mMaxFps > 0) {
- err = mCodec->mOMX->setInternalOption(
- mCodec->mNode,
- kPortIndexInput,
- IOMX::INTERNAL_OPTION_MAX_FPS,
- &mCodec->mMaxFps,
- sizeof(mCodec->mMaxFps));
+ err = statusFromBinderStatus(
+ mCodec->mGraphicBufferSource->setMaxFps(mCodec->mMaxFps));
if (err != OK) {
ALOGE("[%s] Unable to configure max fps (err %d)",
- mCodec->mComponentName.c_str(),
- err);
+ mCodec->mComponentName.c_str(), err);
return err;
}
}
if (mCodec->mTimePerCaptureUs > 0ll
&& mCodec->mTimePerFrameUs > 0ll) {
- int64_t timeLapse[2];
- timeLapse[0] = mCodec->mTimePerFrameUs;
- timeLapse[1] = mCodec->mTimePerCaptureUs;
- err = mCodec->mOMX->setInternalOption(
- mCodec->mNode,
- kPortIndexInput,
- IOMX::INTERNAL_OPTION_TIME_LAPSE,
- &timeLapse[0],
- sizeof(timeLapse));
+ err = statusFromBinderStatus(
+ mCodec->mGraphicBufferSource->setTimeLapseConfig(
+ mCodec->mTimePerFrameUs, mCodec->mTimePerCaptureUs));
if (err != OK) {
ALOGE("[%s] Unable to configure time lapse (err %d)",
- mCodec->mComponentName.c_str(),
- err);
+ mCodec->mComponentName.c_str(), err);
return err;
}
}
if (mCodec->mCreateInputBuffersSuspended) {
- bool suspend = true;
- err = mCodec->mOMX->setInternalOption(
- mCodec->mNode,
- kPortIndexInput,
- IOMX::INTERNAL_OPTION_SUSPEND,
- &suspend,
- sizeof(suspend));
+ err = statusFromBinderStatus(
+ mCodec->mGraphicBufferSource->setSuspend(true));
if (err != OK) {
ALOGE("[%s] Unable to configure option to suspend (err %d)",
- mCodec->mComponentName.c_str(),
- err);
+ mCodec->mComponentName.c_str(), err);
return err;
}
}
uint32_t usageBits;
- if (mCodec->mOMX->getParameter(
- mCodec->mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
+ if (mCodec->mOMXNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
&usageBits, sizeof(usageBits)) == OK) {
mCodec->mInputFormat->setInt32(
"using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
@@ -6945,9 +6647,14 @@
sp<ABuffer> colorAspectsBuffer;
if (mCodec->mInputFormat->findBuffer("android._color-aspects", &colorAspectsBuffer)) {
- err = mCodec->mOMX->setInternalOption(
- mCodec->mNode, kPortIndexInput, IOMX::INTERNAL_OPTION_COLOR_ASPECTS,
- colorAspectsBuffer->base(), colorAspectsBuffer->capacity());
+ if (colorAspectsBuffer->size() != sizeof(ColorAspects)) {
+ return INVALID_OPERATION;
+ }
+
+ err = statusFromBinderStatus(
+ mCodec->mGraphicBufferSource->setColorAspects(ColorUtils::packToU32(
+ *(ColorAspects *)colorAspectsBuffer->base())));
+
if (err != OK) {
ALOGE("[%s] Unable to configure color aspects (err %d)",
mCodec->mComponentName.c_str(), err);
@@ -6964,29 +6671,20 @@
sp<AMessage> notify = mCodec->mNotify->dup();
notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated);
- android_dataspace dataSpace;
- status_t err =
- mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace);
- notify->setMessage("input-format", mCodec->mInputFormat);
- notify->setMessage("output-format", mCodec->mOutputFormat);
-
sp<IGraphicBufferProducer> bufferProducer;
- if (err == OK) {
- mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
- err = mCodec->mOMX->createInputSurface(
- mCodec->mNode, kPortIndexInput, dataSpace, &bufferProducer,
- &mCodec->mInputMetadataType);
- // framework uses ANW buffers internally instead of gralloc handles
- if (mCodec->mInputMetadataType == kMetadataBufferTypeGrallocSource) {
- mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
- }
- }
+ status_t err = mCodec->mOMX->createInputSurface(
+ &bufferProducer, &mCodec->mGraphicBufferSource);
if (err == OK) {
err = setupInputSurface();
}
if (err == OK) {
+ mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
+
+ notify->setMessage("input-format", mCodec->mInputFormat);
+ notify->setMessage("output-format", mCodec->mOutputFormat);
+
notify->setObject("input-surface",
new BufferProducerWrapper(bufferProducer));
} else {
@@ -7010,30 +6708,16 @@
sp<RefBase> obj;
CHECK(msg->findObject("input-surface", &obj));
sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get());
+ mCodec->mGraphicBufferSource = surface->getBufferSource();
- android_dataspace dataSpace;
- status_t err =
- mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace);
- notify->setMessage("input-format", mCodec->mInputFormat);
- notify->setMessage("output-format", mCodec->mOutputFormat);
+ status_t err = setupInputSurface();
if (err == OK) {
mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
- err = mCodec->mOMX->setInputSurface(
- mCodec->mNode, kPortIndexInput, surface->getBufferConsumer(),
- &mCodec->mInputMetadataType);
- // framework uses ANW buffers internally instead of gralloc handles
- if (mCodec->mInputMetadataType == kMetadataBufferTypeGrallocSource) {
- mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
- }
- }
- if (err == OK) {
- surface->getBufferConsumer()->setDefaultBufferDataSpace(dataSpace);
- err = setupInputSurface();
- }
-
- if (err != OK) {
+ notify->setMessage("input-format", mCodec->mInputFormat);
+ notify->setMessage("output-format", mCodec->mOutputFormat);
+ } else {
// Can't use mCodec->signalError() here -- MediaCodec won't forward
// the error through because it's in the "configured" state. We
// send a kWhatInputSurfaceAccepted with an error value instead.
@@ -7047,7 +6731,7 @@
void ACodec::LoadedState::onStart() {
ALOGV("onStart");
- status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle);
+ status_t err = mCodec->mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle);
if (err != OK) {
mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
} else {
@@ -7072,8 +6756,8 @@
mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
- mCodec->mOMX->sendCommand(
- mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded);
+ mCodec->mOMXNode->sendCommand(
+ OMX_CommandStateSet, OMX_StateLoaded);
if (mCodec->allYourBuffersAreBelongToUs(kPortIndexInput)) {
mCodec->freeBuffersOnPort(kPortIndexInput);
}
@@ -7145,8 +6829,8 @@
}
if (err == OK) {
- err = mCodec->mOMX->sendCommand(
- mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting);
+ err = mCodec->mOMXNode->sendCommand(
+ OMX_CommandStateSet, OMX_StateExecuting);
}
if (err != OK) {
@@ -7289,7 +6973,7 @@
ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID);
info->checkWriteFence("submitRegularOutputBuffers");
- status_t err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd);
+ status_t err = mCodec->mOMXNode->fillBuffer(info->mBufferID, info->mFenceFd);
info->mFenceFd = -1;
if (err != OK) {
failed = true;
@@ -7357,8 +7041,8 @@
mActive = false;
- status_t err = mCodec->mOMX->sendCommand(
- mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle);
+ status_t err = mCodec->mOMXNode->sendCommand(
+ OMX_CommandStateSet, OMX_StateIdle);
if (err != OK) {
if (keepComponentAllocated) {
mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
@@ -7384,7 +7068,7 @@
mActive = false;
- status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandFlush, OMX_ALL);
+ status_t err = mCodec->mOMXNode->sendCommand(OMX_CommandFlush, OMX_ALL);
if (err != OK) {
mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
} else {
@@ -7467,8 +7151,7 @@
configParams.nPortIndex = kPortIndexOutput;
configParams.nEncodeBitrate = videoBitrate;
- status_t err = mOMX->setConfig(
- mNode,
+ status_t err = mOMXNode->setConfig(
OMX_IndexConfigVideoBitrate,
&configParams,
sizeof(configParams));
@@ -7483,12 +7166,14 @@
int64_t timeOffsetUs;
if (params->findInt64("time-offset-us", &timeOffsetUs)) {
- status_t err = mOMX->setInternalOption(
- mNode,
- kPortIndexInput,
- IOMX::INTERNAL_OPTION_TIME_OFFSET,
- &timeOffsetUs,
- sizeof(timeOffsetUs));
+ if (mGraphicBufferSource == NULL) {
+ ALOGE("[%s] Invalid to set input buffer time offset without surface",
+ mComponentName.c_str());
+ return INVALID_OPERATION;
+ }
+
+ status_t err = statusFromBinderStatus(
+ mGraphicBufferSource->setTimeOffsetUs(timeOffsetUs));
if (err != OK) {
ALOGE("[%s] Unable to set input buffer time offset (err %d)",
@@ -7500,13 +7185,14 @@
int64_t skipFramesBeforeUs;
if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
- status_t err =
- mOMX->setInternalOption(
- mNode,
- kPortIndexInput,
- IOMX::INTERNAL_OPTION_START_TIME,
- &skipFramesBeforeUs,
- sizeof(skipFramesBeforeUs));
+ if (mGraphicBufferSource == NULL) {
+ ALOGE("[%s] Invalid to set start time without surface",
+ mComponentName.c_str());
+ return INVALID_OPERATION;
+ }
+
+ status_t err = statusFromBinderStatus(
+ mGraphicBufferSource->setStartTimeUs(skipFramesBeforeUs));
if (err != OK) {
ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err);
@@ -7516,15 +7202,14 @@
int32_t dropInputFrames;
if (params->findInt32("drop-input-frames", &dropInputFrames)) {
- bool suspend = dropInputFrames != 0;
+ if (mGraphicBufferSource == NULL) {
+ ALOGE("[%s] Invalid to set suspend without surface",
+ mComponentName.c_str());
+ return INVALID_OPERATION;
+ }
- status_t err =
- mOMX->setInternalOption(
- mNode,
- kPortIndexInput,
- IOMX::INTERNAL_OPTION_SUSPEND,
- &suspend,
- sizeof(suspend));
+ status_t err = statusFromBinderStatus(
+ mGraphicBufferSource->setSuspend(dropInputFrames != 0));
if (err != OK) {
ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
@@ -7574,7 +7259,10 @@
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", CodecBase::kWhatSignaledInputEOS);
- status_t err = mOMX->signalEndOfInputStream(mNode);
+ status_t err = INVALID_OPERATION;
+ if (mGraphicBufferSource != NULL) {
+ err = statusFromBinderStatus(mGraphicBufferSource->signalEndOfInputStream());
+ }
if (err != OK) {
notify->setInt32("err", err);
}
@@ -7597,8 +7285,7 @@
if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
mCodec->mMetadataBuffersToSubmit = 0;
- CHECK_EQ(mCodec->mOMX->sendCommand(
- mCodec->mNode,
+ CHECK_EQ(mCodec->mOMXNode->sendCommand(
OMX_CommandPortDisable, kPortIndexOutput),
(status_t)OK);
@@ -7703,8 +7390,8 @@
}
if (err == OK) {
- err = mCodec->mOMX->sendCommand(
- mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput);
+ err = mCodec->mOMXNode->sendCommand(
+ OMX_CommandPortEnable, kPortIndexOutput);
}
if (err == OK) {
@@ -7829,8 +7516,8 @@
void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
- status_t err = mCodec->mOMX->sendCommand(
- mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded);
+ status_t err = mCodec->mOMXNode->sendCommand(
+ OMX_CommandStateSet, OMX_StateLoaded);
if (err == OK) {
err = mCodec->freeBuffersOnPort(kPortIndexInput);
status_t err2 = mCodec->freeBuffersOnPort(kPortIndexOutput);
@@ -8016,7 +7703,7 @@
{
sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec);
msg->setInt32("type", omx_message::EVENT);
- msg->setInt32("node", mCodec->mNode);
+ msg->setInt32("generation", mCodec->mNodeGeneration);
msg->setInt32("event", event);
msg->setInt32("data1", data1);
msg->setInt32("data2", data2);
@@ -8079,7 +7766,7 @@
const AString &name, const AString &mime, bool isEncoder,
sp<MediaCodecInfo::Capabilities> *caps) {
(*caps).clear();
- const char *role = getComponentRole(isEncoder, mime.c_str());
+ const char *role = GetComponentRole(isEncoder, mime.c_str());
if (role == NULL) {
return BAD_VALUE;
}
@@ -8092,17 +7779,17 @@
sp<IOMX> omx = client.interface();
sp<CodecObserver> observer = new CodecObserver;
- IOMX::node_id node = 0;
+ sp<IOMXNode> omxNode;
- err = omx->allocateNode(name.c_str(), observer, NULL, &node);
+ err = omx->allocateNode(name.c_str(), observer, &omxNode);
if (err != OK) {
client.disconnect();
return err;
}
- err = setComponentRole(omx, node, role);
+ err = SetComponentRole(omxNode, role);
if (err != OK) {
- omx->freeNode(node);
+ omxNode->freeNode();
client.disconnect();
return err;
}
@@ -8117,8 +7804,8 @@
for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
param.nProfileIndex = index;
- status_t err = omx->getParameter(
- node, OMX_IndexParamVideoProfileLevelQuerySupported,
+ status_t err = omxNode->getParameter(
+ OMX_IndexParamVideoProfileLevelQuerySupported,
¶m, sizeof(param));
if (err != OK) {
break;
@@ -8141,16 +7828,16 @@
Vector<uint32_t> supportedColors; // shadow copy to check for duplicates
for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
portFormat.nIndex = index;
- status_t err = omx->getParameter(
- node, OMX_IndexParamVideoPortFormat,
+ status_t err = omxNode->getParameter(
+ OMX_IndexParamVideoPortFormat,
&portFormat, sizeof(portFormat));
if (err != OK) {
break;
}
OMX_U32 flexibleEquivalent;
- if (isFlexibleColorFormat(
- omx, node, portFormat.eColorFormat, false /* usingNativeWindow */,
+ if (IsFlexibleColorFormat(
+ omxNode, portFormat.eColorFormat, false /* usingNativeWindow */,
&flexibleEquivalent)) {
bool marked = false;
for (size_t i = 0; i < supportedColors.size(); ++i) {
@@ -8180,8 +7867,8 @@
param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput;
for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
param.nProfileIndex = index;
- status_t err = omx->getParameter(
- node, (OMX_INDEXTYPE)OMX_IndexParamAudioProfileQuerySupported,
+ status_t err = omxNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamAudioProfileQuerySupported,
¶m, sizeof(param));
if (err != OK) {
break;
@@ -8205,15 +7892,15 @@
if (isVideo && !isEncoder) {
native_handle_t *sidebandHandle = NULL;
- if (omx->configureVideoTunnelMode(
- node, kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) {
+ if (omxNode->configureVideoTunnelMode(
+ kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) {
// tunneled playback includes adaptive playback
builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback
| MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback);
- } else if (omx->storeMetaDataInBuffers(
- node, kPortIndexOutput, OMX_TRUE) == OK ||
- omx->prepareForAdaptivePlayback(
- node, kPortIndexOutput, OMX_TRUE,
+ } else if (omxNode->storeMetaDataInBuffers(
+ kPortIndexOutput, OMX_TRUE) == OK ||
+ omxNode->prepareForAdaptivePlayback(
+ kPortIndexOutput, OMX_TRUE,
1280 /* width */, 720 /* height */) == OK) {
builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback);
}
@@ -8224,15 +7911,15 @@
InitOMXParams(¶ms);
params.nPortIndex = kPortIndexOutput;
// TODO: should we verify if fallback is supported?
- if (omx->getConfig(
- node, (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh,
+ if (omxNode->getConfig(
+ (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh,
¶ms, sizeof(params)) == OK) {
builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh);
}
}
*caps = builder;
- omx->freeNode(node);
+ omxNode->freeNode();
client.disconnect();
return OK;
}
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 98bcc56..2c741db 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -10,6 +10,7 @@
AMRWriter.cpp \
AudioPlayer.cpp \
AudioSource.cpp \
+ BufferImpl.cpp \
CallbackDataSource.cpp \
CameraSource.cpp \
CameraSourceTimeLapse.cpp \
@@ -35,7 +36,6 @@
MediaCodecList.cpp \
MediaCodecListOverrides.cpp \
MediaCodecSource.cpp \
- MediaDefs.cpp \
MediaExtractor.cpp \
MediaSync.cpp \
MidiExtractor.cpp \
@@ -133,7 +133,6 @@
LOCAL_CFLAGS += -DENABLE_STAGEFRIGHT_EXPERIMENTS
endif
-LOCAL_CLANG := true
LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow
LOCAL_MODULE:= libstagefright
diff --git a/media/libstagefright/BufferImpl.cpp b/media/libstagefright/BufferImpl.cpp
new file mode 100644
index 0000000..7d195d3
--- /dev/null
+++ b/media/libstagefright/BufferImpl.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "BufferImpl"
+#include <utils/Log.h>
+
+#include <binder/IMemory.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#include "include/SharedMemoryBuffer.h"
+
+namespace android {
+
+SharedMemoryBuffer::SharedMemoryBuffer(const sp<AMessage> &format, const sp<IMemory> &mem)
+ : MediaCodecBuffer(format, new ABuffer(mem->pointer(), mem->size())),
+ mMemory(mem) {
+}
+
+} // namespace android
diff --git a/media/libstagefright/DataConverter.cpp b/media/libstagefright/DataConverter.cpp
index aea47f3..52be054 100644
--- a/media/libstagefright/DataConverter.cpp
+++ b/media/libstagefright/DataConverter.cpp
@@ -21,13 +21,13 @@
#include <audio_utils/primitives.h>
-#include <media/stagefright/foundation/ABuffer.h>
+#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AUtils.h>
namespace android {
-status_t DataConverter::convert(const sp<ABuffer> &source, sp<ABuffer> &target) {
+status_t DataConverter::convert(const sp<MediaCodecBuffer> &source, sp<MediaCodecBuffer> &target) {
CHECK(source->base() != target->base());
size_t size = targetSize(source->size());
status_t err = OK;
@@ -43,7 +43,8 @@
return err;
}
-status_t DataConverter::safeConvert(const sp<ABuffer> &source, sp<ABuffer> &target) {
+status_t DataConverter::safeConvert(
+ const sp<MediaCodecBuffer> &source, sp<MediaCodecBuffer> &target) {
memcpy(target->base(), source->data(), source->size());
return OK;
}
@@ -101,7 +102,7 @@
return NULL;
}
-status_t AudioConverter::safeConvert(const sp<ABuffer> &src, sp<ABuffer> &tgt) {
+status_t AudioConverter::safeConvert(const sp<MediaCodecBuffer> &src, sp<MediaCodecBuffer> &tgt) {
if (mTo == kAudioEncodingPcm8bit && mFrom == kAudioEncodingPcm16bit) {
memcpy_to_u8_from_i16((uint8_t*)tgt->base(), (const int16_t*)src->data(), src->size() / 2);
} else if (mTo == kAudioEncodingPcm8bit && mFrom == kAudioEncodingPcmFloat) {
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
index 931b280..b83b0a0 100644
--- a/media/libstagefright/MPEG2TSWriter.cpp
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -37,7 +37,7 @@
struct MPEG2TSWriter::SourceInfo : public AHandler {
explicit SourceInfo(const sp<IMediaSource> &source);
- void start(const sp<AMessage> ¬ify);
+ void start(const sp<AMessage> ¬ify, const sp<MetaData> ¶ms);
void stop();
unsigned streamType() const;
@@ -75,7 +75,7 @@
sp<ABuffer> mAACCodecSpecificData;
- sp<ABuffer> mAACBuffer;
+ sp<ABuffer> mBuffer;
sp<ABuffer> mLastAccessUnit;
bool mEOSReceived;
@@ -85,10 +85,8 @@
void extractCodecSpecificData();
- bool appendAACFrames(MediaBuffer *buffer);
- bool flushAACFrames();
-
- void postAVCFrame(MediaBuffer *buffer);
+ void appendAACFrames(MediaBuffer *buffer);
+ void appendAVCFrame(MediaBuffer *buffer);
DISALLOW_EVIL_CONSTRUCTORS(SourceInfo);
};
@@ -129,13 +127,14 @@
return mContinuityCounter;
}
-void MPEG2TSWriter::SourceInfo::start(const sp<AMessage> ¬ify) {
+void MPEG2TSWriter::SourceInfo::start(const sp<AMessage> ¬ify, const sp<MetaData> ¶ms) {
mLooper->registerHandler(this);
mLooper->start();
-
mNotify = notify;
- (new AMessage(kWhatStart, this))->post();
+ sp<AMessage> msg = new AMessage(kWhatStart, this);
+ msg->setObject("meta", params);
+ msg->post();
}
void MPEG2TSWriter::SourceInfo::stop() {
@@ -250,56 +249,51 @@
notify->post();
}
-void MPEG2TSWriter::SourceInfo::postAVCFrame(MediaBuffer *buffer) {
+void MPEG2TSWriter::SourceInfo::appendAVCFrame(MediaBuffer *buffer) {
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", kNotifyBuffer);
- sp<ABuffer> copy =
- new ABuffer(buffer->range_length());
- memcpy(copy->data(),
+ if (mBuffer == NULL || buffer->range_length() > mBuffer->capacity()) {
+ mBuffer = new ABuffer(buffer->range_length());
+ }
+ mBuffer->setRange(0, 0);
+
+ memcpy(mBuffer->data(),
(const uint8_t *)buffer->data()
+ buffer->range_offset(),
buffer->range_length());
int64_t timeUs;
CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
- copy->meta()->setInt64("timeUs", timeUs);
+ mBuffer->meta()->setInt64("timeUs", timeUs);
int32_t isSync;
if (buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)
&& isSync != 0) {
- copy->meta()->setInt32("isSync", true);
+ mBuffer->meta()->setInt32("isSync", true);
}
- notify->setBuffer("buffer", copy);
+ mBuffer->setRange(0, buffer->range_length());
+
+ notify->setBuffer("buffer", mBuffer);
notify->post();
}
-bool MPEG2TSWriter::SourceInfo::appendAACFrames(MediaBuffer *buffer) {
- bool accessUnitPosted = false;
+void MPEG2TSWriter::SourceInfo::appendAACFrames(MediaBuffer *buffer) {
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kNotifyBuffer);
- if (mAACBuffer != NULL
- && mAACBuffer->size() + 7 + buffer->range_length()
- > mAACBuffer->capacity()) {
- accessUnitPosted = flushAACFrames();
+ if (mBuffer == NULL || 7 + buffer->range_length() > mBuffer->capacity()) {
+ mBuffer = new ABuffer(7 + buffer->range_length());
}
- if (mAACBuffer == NULL) {
- size_t alloc = 4096;
- if (buffer->range_length() + 7 > alloc) {
- alloc = 7 + buffer->range_length();
- }
+ int64_t timeUs;
+ CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
- mAACBuffer = new ABuffer(alloc);
+ mBuffer->meta()->setInt64("timeUs", timeUs);
+ mBuffer->meta()->setInt32("isSync", true);
- int64_t timeUs;
- CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
-
- mAACBuffer->meta()->setInt64("timeUs", timeUs);
- mAACBuffer->meta()->setInt32("isSync", true);
-
- mAACBuffer->setRange(0, 0);
- }
+ mBuffer->setRange(0, 0);
const uint8_t *codec_specific_data = mAACCodecSpecificData->data();
@@ -312,7 +306,7 @@
unsigned channel_configuration =
(codec_specific_data[1] >> 3) & 0x0f;
- uint8_t *ptr = mAACBuffer->data() + mAACBuffer->size();
+ uint8_t *ptr = mBuffer->data() + mBuffer->size();
const uint32_t aac_frame_length = buffer->range_length() + 7;
@@ -340,24 +334,10 @@
ptr += buffer->range_length();
- mAACBuffer->setRange(0, ptr - mAACBuffer->data());
+ mBuffer->setRange(0, ptr - mBuffer->data());
- return accessUnitPosted;
-}
-
-bool MPEG2TSWriter::SourceInfo::flushAACFrames() {
- if (mAACBuffer == NULL) {
- return false;
- }
-
- sp<AMessage> notify = mNotify->dup();
- notify->setInt32("what", kNotifyBuffer);
- notify->setBuffer("buffer", mAACBuffer);
+ notify->setBuffer("buffer", mBuffer);
notify->post();
-
- mAACBuffer.clear();
-
- return true;
}
void MPEG2TSWriter::SourceInfo::readMore() {
@@ -368,7 +348,10 @@
switch (msg->what()) {
case kWhatStart:
{
- status_t err = mSource->start();
+ sp<RefBase> obj;
+ CHECK(msg->findObject("meta", &obj));
+ MetaData *params = static_cast<MetaData *>(obj.get());
+ status_t err = mSource->start(params);
if (err != OK) {
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", kNotifyStartFailed);
@@ -376,6 +359,7 @@
break;
}
+ // Extract CSD from config format.
extractCodecSpecificData();
readMore();
@@ -388,10 +372,6 @@
status_t err = mSource->read(&buffer);
if (err != OK && err != INFO_FORMAT_CHANGED) {
- if (mStreamType == 0x0f) {
- flushAACFrames();
- }
-
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", kNotifyReachedEOS);
notify->setInt32("status", err);
@@ -401,23 +381,20 @@
if (err == OK) {
if (mStreamType == 0x0f && mAACCodecSpecificData == NULL) {
- // The first buffer contains codec specific data.
-
+ // The first audio buffer must contain CSD if not received yet.
CHECK_GE(buffer->range_length(), 2u);
-
mAACCodecSpecificData = new ABuffer(buffer->range_length());
memcpy(mAACCodecSpecificData->data(),
(const uint8_t *)buffer->data()
+ buffer->range_offset(),
buffer->range_length());
+ readMore();
} else if (buffer->range_length() > 0) {
if (mStreamType == 0x0f) {
- if (!appendAACFrames(buffer)) {
- msg->post();
- }
+ appendAACFrames(buffer);
} else {
- postAVCFrame(buffer);
+ appendAVCFrame(buffer);
}
} else {
readMore();
@@ -452,7 +429,6 @@
int64_t timeUs;
CHECK(mLastAccessUnit->meta()->findInt64("timeUs", &timeUs));
-
return timeUs;
}
@@ -542,7 +518,7 @@
return OK;
}
-status_t MPEG2TSWriter::start(MetaData * /* param */) {
+status_t MPEG2TSWriter::start(MetaData *param ) {
CHECK(!mStarted);
mStarted = true;
@@ -556,7 +532,7 @@
notify->setInt32("source-index", i);
- mSources.editItemAt(i)->start(notify);
+ mSources.editItemAt(i)->start(notify, param);
}
return OK;
@@ -594,13 +570,13 @@
{
int32_t sourceIndex;
CHECK(msg->findInt32("source-index", &sourceIndex));
+ sp<SourceInfo> source = mSources.editItemAt(sourceIndex);
int32_t what;
CHECK(msg->findInt32("what", &what));
if (what == SourceInfo::kNotifyReachedEOS
|| what == SourceInfo::kNotifyStartFailed) {
- sp<SourceInfo> source = mSources.editItemAt(sourceIndex);
source->setEOSReceived();
sp<ABuffer> buffer = source->lastAccessUnit();
@@ -615,6 +591,7 @@
} else if (what == SourceInfo::kNotifyBuffer) {
sp<ABuffer> buffer;
CHECK(msg->findBuffer("buffer", &buffer));
+ CHECK(source->lastAccessUnit() == NULL);
int32_t oob;
if (msg->findInt32("oob", &oob) && oob) {
@@ -635,15 +612,10 @@
// Rinse, repeat.
// If we don't have data on any track we don't write
// anything just yet.
-
- sp<SourceInfo> source = mSources.editItemAt(sourceIndex);
-
- CHECK(source->lastAccessUnit() == NULL);
source->setLastAccessUnit(buffer);
ALOGV("lastAccessUnitTimeUs[%d] = %.2f secs",
- sourceIndex, source->lastAccessUnitTimeUs() / 1E6);
-
+ sourceIndex, source->lastAccessUnitTimeUs() / 1E6);
int64_t minTimeUs = -1;
size_t minIndex = 0;
@@ -665,15 +637,14 @@
}
if (minTimeUs < 0) {
- ALOGV("not a all tracks have valid data.");
+ ALOGV("not all tracks have valid data.");
break;
}
ALOGV("writing access unit at time %.2f secs (index %zu)",
- minTimeUs / 1E6, minIndex);
+ minTimeUs / 1E6, minIndex);
source = mSources.editItemAt(minIndex);
-
buffer = source->lastAccessUnit();
source->setLastAccessUnit(NULL);
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index c8ca36c..d37e973 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -814,6 +814,10 @@
ALOGE("b/23540914");
return ERROR_MALFORMED;
}
+ if (depth > 100) {
+ ALOGE("b/27456299");
+ return ERROR_MALFORMED;
+ }
uint32_t hdr[2];
if (mDataSource->readAt(*offset, hdr, 8) < 8) {
return ERROR_IO;
@@ -2298,6 +2302,12 @@
return UNKNOWN_ERROR; // stop parsing after sidx
}
+ case FOURCC('a', 'c', '-', '3'):
+ {
+ *offset += chunk_size;
+ return parseAC3SampleEntry(data_offset);
+ }
+
case FOURCC('f', 't', 'y', 'p'):
{
if (chunk_data_size < 8 || depth != 0) {
@@ -2346,6 +2356,99 @@
return OK;
}
+status_t MPEG4Extractor::parseAC3SampleEntry(off64_t offset) {
+ // skip 16 bytes:
+ // + 6-byte reserved,
+ // + 2-byte data reference index,
+ // + 8-byte reserved
+ offset += 16;
+ uint16_t channelCount;
+ if (!mDataSource->getUInt16(offset, &channelCount)) {
+ return ERROR_MALFORMED;
+ }
+ // skip 8 bytes:
+ // + 2-byte channelCount,
+ // + 2-byte sample size,
+ // + 4-byte reserved
+ offset += 8;
+ uint16_t sampleRate;
+ if (!mDataSource->getUInt16(offset, &sampleRate)) {
+ ALOGE("MPEG4Extractor: error while reading ac-3 block: cannot read sample rate");
+ return ERROR_MALFORMED;
+ }
+
+ // skip 4 bytes:
+ // + 2-byte sampleRate,
+ // + 2-byte reserved
+ offset += 4;
+ return parseAC3SpecificBox(offset, sampleRate);
+}
+
+status_t MPEG4Extractor::parseAC3SpecificBox(
+ off64_t offset, uint16_t sampleRate) {
+ uint32_t size;
+ // + 4-byte size
+ // + 4-byte type
+ // + 3-byte payload
+ const uint32_t kAC3SpecificBoxSize = 11;
+ if (!mDataSource->getUInt32(offset, &size) || size < kAC3SpecificBoxSize) {
+ ALOGE("MPEG4Extractor: error while reading ac-3 block: cannot read specific box size");
+ return ERROR_MALFORMED;
+ }
+
+ offset += 4;
+ uint32_t type;
+ if (!mDataSource->getUInt32(offset, &type) || type != FOURCC('d', 'a', 'c', '3')) {
+ ALOGE("MPEG4Extractor: error while reading ac-3 specific block: header not dac3");
+ return ERROR_MALFORMED;
+ }
+
+ offset += 4;
+ const uint32_t kAC3SpecificBoxPayloadSize = 3;
+ uint8_t chunk[kAC3SpecificBoxPayloadSize];
+ if (mDataSource->readAt(offset, chunk, sizeof(chunk)) != sizeof(chunk)) {
+ ALOGE("MPEG4Extractor: error while reading ac-3 specific block: bitstream fields");
+ return ERROR_MALFORMED;
+ }
+
+ ABitReader br(chunk, sizeof(chunk));
+ static const unsigned channelCountTable[] = {2, 1, 2, 3, 3, 4, 4, 5};
+ static const unsigned sampleRateTable[] = {48000, 44100, 32000};
+
+ unsigned fscod = br.getBits(2);
+ if (fscod == 3) {
+ ALOGE("Incorrect fscod (3) in AC3 header");
+ return ERROR_MALFORMED;
+ }
+ unsigned boxSampleRate = sampleRateTable[fscod];
+ if (boxSampleRate != sampleRate) {
+ ALOGE("sample rate mismatch: boxSampleRate = %d, sampleRate = %d",
+ boxSampleRate, sampleRate);
+ return ERROR_MALFORMED;
+ }
+
+ unsigned bsid = br.getBits(5);
+ if (bsid > 8) {
+ ALOGW("Incorrect bsid in AC3 header. Possibly E-AC-3?");
+ return ERROR_MALFORMED;
+ }
+
+ // skip
+ unsigned bsmod __unused = br.getBits(3);
+
+ unsigned acmod = br.getBits(3);
+ unsigned lfeon = br.getBits(1);
+ unsigned channelCount = channelCountTable[acmod] + lfeon;
+
+ if (mLastTrack == NULL) {
+ return ERROR_MALFORMED;
+ }
+ mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AC3);
+ mLastTrack->meta->setInt32(kKeyChannelCount, channelCount);
+ mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
+ return OK;
+}
+
status_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) {
ALOGV("MPEG4Extractor::parseSegmentIndex");
@@ -2890,7 +2993,7 @@
int32_t type = U32_AT(&buffer[0]);
if ((type == FOURCC('n', 'c', 'l', 'x') && size >= 11)
- || (type == FOURCC('n', 'c', 'l', 'c' && size >= 10))) {
+ || (type == FOURCC('n', 'c', 'l', 'c') && size >= 10)) {
int32_t primaries = U16_AT(&buffer[4]);
int32_t transfer = U16_AT(&buffer[6]);
int32_t coeffs = U16_AT(&buffer[8]);
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index c9bcfc3..74eb590 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -3300,7 +3300,12 @@
// Each character is packed as the difference between its ASCII value and 0x60.
// For "English", these are 00101, 01110, 00111.
// XXX: Where is the padding bit located: 0x15C7?
- mOwner->writeInt16(0); // language code
+ const char *lang = NULL;
+ int16_t langCode = 0;
+ if (mMeta->findCString(kKeyMediaLanguage, &lang) && lang && strnlen(lang, 3) > 2) {
+ langCode = ((lang[0] & 0x1f) << 10) | ((lang[1] & 0x1f) << 5) | (lang[2] & 0x1f);
+ }
+ mOwner->writeInt16(langCode); // language code
mOwner->writeInt16(0); // predefined
mOwner->endBox();
}
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index b088775..465ebc8 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -19,6 +19,7 @@
#include <inttypes.h>
#include "include/avc_utils.h"
+#include "include/SharedMemoryBuffer.h"
#include "include/SoftwareRenderer.h"
#include <binder/IMemory.h>
@@ -30,6 +31,7 @@
#include <media/ICrypto.h>
#include <media/IOMX.h>
#include <media/IResourceManagerService.h>
+#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -211,50 +213,24 @@
// static
sp<PersistentSurface> MediaCodec::CreatePersistentInputSurface() {
OMXClient client;
- CHECK_EQ(client.connect(), (status_t)OK);
+ if (client.connect() != OK) {
+ ALOGE("Failed to connect to OMX to create persistent input surface.");
+ return NULL;
+ }
+
sp<IOMX> omx = client.interface();
- const sp<IMediaCodecList> mediaCodecList = MediaCodecList::getInstance();
- if (mediaCodecList == NULL) {
- ALOGE("Failed to obtain MediaCodecList!");
- return NULL; // if called from Java should raise IOException
- }
-
- AString tmp;
- sp<AMessage> globalSettings = mediaCodecList->getGlobalSettings();
- if (globalSettings == NULL || !globalSettings->findString(
- kMaxEncoderInputBuffers, &tmp)) {
- ALOGE("Failed to get encoder input buffer count!");
- return NULL;
- }
-
- int32_t bufferCount = strtol(tmp.c_str(), NULL, 10);
- if (bufferCount <= 0
- || bufferCount > BufferQueue::MAX_MAX_ACQUIRED_BUFFERS) {
- ALOGE("Encoder input buffer count is invalid!");
- return NULL;
- }
-
sp<IGraphicBufferProducer> bufferProducer;
- sp<IGraphicBufferConsumer> bufferConsumer;
+ sp<IGraphicBufferSource> bufferSource;
- status_t err = omx->createPersistentInputSurface(
- &bufferProducer, &bufferConsumer);
+ status_t err = omx->createInputSurface(&bufferProducer, &bufferSource);
if (err != OK) {
ALOGE("Failed to create persistent input surface.");
return NULL;
}
- err = bufferConsumer->setMaxAcquiredBufferCount(bufferCount);
-
- if (err != NO_ERROR) {
- ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
- bufferCount, err);
- return NULL;
- }
-
- return new PersistentSurface(bufferProducer, bufferConsumer);
+ return new PersistentSurface(bufferProducer, bufferSource);
}
MediaCodec::MediaCodec(const sp<ALooper> &looper, pid_t pid)
@@ -860,7 +836,7 @@
return OK;
}
-status_t MediaCodec::getWidevineLegacyBuffers(Vector<sp<ABuffer> > *buffers) const {
+status_t MediaCodec::getWidevineLegacyBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
msg->setInt32("portIndex", kPortIndexInput);
msg->setPointer("buffers", buffers);
@@ -870,7 +846,7 @@
return PostAndAwaitResponse(msg, &response);
}
-status_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
+status_t MediaCodec::getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
msg->setInt32("portIndex", kPortIndexInput);
msg->setPointer("buffers", buffers);
@@ -879,7 +855,7 @@
return PostAndAwaitResponse(msg, &response);
}
-status_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const {
+status_t MediaCodec::getOutputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
msg->setInt32("portIndex", kPortIndexOutput);
msg->setPointer("buffers", buffers);
@@ -888,17 +864,17 @@
return PostAndAwaitResponse(msg, &response);
}
-status_t MediaCodec::getOutputBuffer(size_t index, sp<ABuffer> *buffer) {
+status_t MediaCodec::getOutputBuffer(size_t index, sp<MediaCodecBuffer> *buffer) {
sp<AMessage> format;
return getBufferAndFormat(kPortIndexOutput, index, buffer, &format);
}
status_t MediaCodec::getOutputFormat(size_t index, sp<AMessage> *format) {
- sp<ABuffer> buffer;
+ sp<MediaCodecBuffer> buffer;
return getBufferAndFormat(kPortIndexOutput, index, &buffer, format);
}
-status_t MediaCodec::getInputBuffer(size_t index, sp<ABuffer> *buffer) {
+status_t MediaCodec::getInputBuffer(size_t index, sp<MediaCodecBuffer> *buffer) {
sp<AMessage> format;
return getBufferAndFormat(kPortIndexInput, index, buffer, &format);
}
@@ -909,7 +885,7 @@
status_t MediaCodec::getBufferAndFormat(
size_t portIndex, size_t index,
- sp<ABuffer> *buffer, sp<AMessage> *format) {
+ sp<MediaCodecBuffer> *buffer, sp<AMessage> *format) {
// use mutex instead of a context switch
if (mReleasedByResourceManager) {
ALOGE("getBufferAndFormat - resource already released");
@@ -917,7 +893,7 @@
}
if (buffer == NULL) {
- ALOGE("getBufferAndFormat - null ABuffer");
+ ALOGE("getBufferAndFormat - null MediaCodecBuffer");
return INVALID_OPERATION;
}
@@ -956,7 +932,6 @@
*buffer = (portIndex == kPortIndexInput && mCrypto != NULL) ?
info.mEncryptedData :
info.mData;
-
*format = info.mFormat;
return OK;
@@ -1046,7 +1021,7 @@
return false;
}
- const sp<ABuffer> &buffer =
+ const sp<MediaCodecBuffer> &buffer =
mPortBuffers[kPortIndexOutput].itemAt(index).mData;
response->setSize("index", index);
@@ -1310,6 +1285,8 @@
status_t err = NO_ERROR;
sp<AMessage> response = new AMessage();
if (!msg->findInt32("err", &err)) {
+ CHECK(msg->findMessage("input-format", &mInputFormat));
+ CHECK(msg->findMessage("output-format", &mOutputFormat));
mHaveInputSurface = true;
} else {
response->setInt32("err", err);
@@ -1377,7 +1354,7 @@
if (portIndex == kPortIndexInput && mCrypto != NULL) {
sp<IMemory> mem = mDealer->allocate(info.mData->capacity());
info.mEncryptedData =
- new ABuffer(mem->pointer(), info.mData->capacity());
+ new SharedMemoryBuffer(mInputFormat, mem);
info.mSharedEncryptedBuffer = mem;
}
@@ -1484,6 +1461,9 @@
break;
}
+ // TODO: hold reference of buffer from downstream when
+ // mPortBuffers is removed.
+
if (!mCSD.empty()) {
ssize_t index = dequeuePortBuffer(kPortIndexInput);
CHECK_GE(index, 0);
@@ -1539,8 +1519,10 @@
break;
}
- sp<ABuffer> buffer;
- CHECK(msg->findBuffer("buffer", &buffer));
+ sp<RefBase> obj;
+ CHECK(msg->findObject("buffer", &obj));
+ sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
+ // TODO: hold buffer's reference when we remove mPortBuffers
int32_t omxFlags;
CHECK(msg->findInt32("flags", &omxFlags));
@@ -2123,7 +2105,7 @@
sp<AReplyToken> replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
- if (!isExecuting()) {
+ if (!isExecuting() || !mHaveInputSurface) {
PostReplyWithError(replyID, INVALID_OPERATION);
break;
} else if (mFlags & kFlagStickyError) {
@@ -2156,7 +2138,7 @@
int32_t portIndex;
CHECK(msg->findInt32("portIndex", &portIndex));
- Vector<sp<ABuffer> > *dstBuffers;
+ Vector<sp<MediaCodecBuffer> > *dstBuffers;
CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
dstBuffers->clear();
@@ -2306,7 +2288,7 @@
sp<ABuffer> csd = *mCSD.begin();
mCSD.erase(mCSD.begin());
- const sp<ABuffer> &codecInputData =
+ const sp<MediaCodecBuffer> &codecInputData =
(mCrypto != NULL) ? info->mEncryptedData : info->mData;
if (csd->size() > codecInputData->capacity()) {
@@ -2553,13 +2535,14 @@
info->mData->setRange(0, result);
}
+ // TODO: release buffer reference.
// synchronization boundary for getBufferAndFormat
{
Mutex::Autolock al(mBufferLock);
info->mOwnedByClient = false;
}
- reply->setBuffer("buffer", info->mData);
+ reply->setObject("buffer", info->mData);
reply->post();
info->mNotify = NULL;
@@ -2644,8 +2627,10 @@
}
}
+ info->mNotify->setObject("buffer", info->mData);
+ // TODO: release buffer reference.
info->mNotify->post();
- info->mNotify = NULL;
+ info->mNotify.clear();
return OK;
}
@@ -2765,7 +2750,7 @@
void MediaCodec::onOutputBufferAvailable() {
int32_t index;
while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
- const sp<ABuffer> &buffer =
+ const sp<MediaCodecBuffer> &buffer =
mPortBuffers[kPortIndexOutput].itemAt(index).mData;
sp<AMessage> msg = mCallback->dup();
msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);
@@ -2866,7 +2851,7 @@
}
status_t MediaCodec::amendOutputFormatWithCodecSpecificData(
- const sp<ABuffer> &buffer) {
+ const sp<MediaCodecBuffer> &buffer) {
AString mime;
CHECK(mOutputFormat->findString("mime", &mime));
@@ -2900,7 +2885,10 @@
} else {
// For everything else we just stash the codec specific data into
// the output format as a single piece of csd under "csd-0".
- mOutputFormat->setBuffer("csd-0", buffer);
+ sp<ABuffer> csd = new ABuffer(buffer->size());
+ memcpy(csd->data(), buffer->data(), buffer->size());
+ csd->setRange(0, buffer->size());
+ mOutputFormat->setBuffer("csd-0", csd);
}
return OK;
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 8afb7e9..93643c2 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -44,8 +44,6 @@
namespace android {
-const char *kMaxEncoderInputBuffers = "max-video-encoder-input-buffers";
-
static Mutex sInitMutex;
static bool parseBoolean(const char *s) {
@@ -196,9 +194,7 @@
if (mInitCheck != OK) {
return; // this may fail if IMediaPlayerService is not available.
}
- mOMX = client.interface();
parseXMLFile(codecs_xml);
- mOMX.clear();
if (mInitCheck != OK) {
if (ignore_errors) {
diff --git a/media/libstagefright/MediaCodecListOverrides.cpp b/media/libstagefright/MediaCodecListOverrides.cpp
index 33795f3..095fc6a 100644
--- a/media/libstagefright/MediaCodecListOverrides.cpp
+++ b/media/libstagefright/MediaCodecListOverrides.cpp
@@ -127,61 +127,6 @@
return format;
}
-static size_t doProfileEncoderInputBuffers(
- const AString &name, const AString &mime, const sp<MediaCodecInfo::Capabilities> &caps) {
- ALOGV("doProfileEncoderInputBuffers: name %s, mime %s", name.c_str(), mime.c_str());
-
- sp<AMessage> format = getMeasureFormat(true /* isEncoder */, mime, caps);
- if (format == NULL) {
- return 0;
- }
-
- format->setInt32("color-format", OMX_COLOR_FormatAndroidOpaque);
- ALOGV("doProfileEncoderInputBuffers: format %s", format->debugString().c_str());
-
- status_t err = OK;
- sp<ALooper> looper = new ALooper;
- looper->setName("MediaCodec_looper");
- looper->start(
- false /* runOnCallingThread */, false /* canCallJava */, ANDROID_PRIORITY_AUDIO);
-
- sp<MediaCodec> codec = MediaCodec::CreateByComponentName(looper, name.c_str(), &err);
- if (err != OK) {
- ALOGE("Failed to create codec: %s", name.c_str());
- return 0;
- }
-
- err = codec->configure(format, NULL, NULL, MediaCodec::CONFIGURE_FLAG_ENCODE);
- if (err != OK) {
- ALOGE("Failed to configure codec: %s with mime: %s", name.c_str(), mime.c_str());
- codec->release();
- return 0;
- }
-
- sp<IGraphicBufferProducer> bufferProducer;
- err = codec->createInputSurface(&bufferProducer);
- if (err != OK) {
- ALOGE("Failed to create surface: %s with mime: %s", name.c_str(), mime.c_str());
- codec->release();
- return 0;
- }
-
- int minUndequeued = 0;
- err = bufferProducer->query(
- NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeued);
- if (err != OK) {
- ALOGE("Failed to query NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS");
- minUndequeued = 0;
- }
-
- err = codec->release();
- if (err != OK) {
- ALOGW("Failed to release codec: %s with mime: %s", name.c_str(), mime.c_str());
- }
-
- return minUndequeued;
-}
-
static size_t doProfileCodecs(
bool isEncoder, const AString &name, const AString &mime, const sp<MediaCodecInfo::Capabilities> &caps) {
sp<AMessage> format = getMeasureFormat(isEncoder, mime, caps);
@@ -276,7 +221,6 @@
bool forceToMeasure) {
KeyedVector<AString, sp<MediaCodecInfo::Capabilities>> codecsNeedMeasure;
AString supportMultipleSecureCodecs = "true";
- size_t maxEncoderInputBuffers = 0;
for (size_t i = 0; i < infos.size(); ++i) {
const sp<MediaCodecInfo> info = infos[i];
AString name = info->getCodecName();
@@ -319,21 +263,9 @@
supportMultipleSecureCodecs = "false";
}
}
- if (info->isEncoder() && mimes[i].startsWith("video/")) {
- size_t encoderInputBuffers =
- doProfileEncoderInputBuffers(name, mimes[i], caps);
- if (encoderInputBuffers > maxEncoderInputBuffers) {
- maxEncoderInputBuffers = encoderInputBuffers;
- }
- }
}
}
}
- if (maxEncoderInputBuffers > 0) {
- char tmp[32];
- sprintf(tmp, "%zu", maxEncoderInputBuffers);
- global_results->add(kMaxEncoderInputBuffers, tmp);
- }
global_results->add(kPolicySupportsMultipleSecureCodecs, supportMultipleSecureCodecs);
}
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 35c07ca..de4d06f 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -20,10 +20,10 @@
#include <inttypes.h>
-#include <gui/IGraphicBufferConsumer.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/Surface.h>
#include <media/ICrypto.h>
+#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>
@@ -35,7 +35,6 @@
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
-#include <media/stagefright/PersistentSurface.h>
#include <media/stagefright/Utils.h>
namespace android {
@@ -325,10 +324,10 @@
const sp<ALooper> &looper,
const sp<AMessage> &format,
const sp<MediaSource> &source,
- const sp<IGraphicBufferConsumer> &consumer,
+ const sp<PersistentSurface> &persistentSurface,
uint32_t flags) {
- sp<MediaCodecSource> mediaSource =
- new MediaCodecSource(looper, format, source, consumer, flags);
+ sp<MediaCodecSource> mediaSource = new MediaCodecSource(
+ looper, format, source, persistentSurface, flags);
if (mediaSource->init() == OK) {
return mediaSource;
@@ -404,7 +403,7 @@
const sp<ALooper> &looper,
const sp<AMessage> &outputFormat,
const sp<MediaSource> &source,
- const sp<IGraphicBufferConsumer> &consumer,
+ const sp<PersistentSurface> &persistentSurface,
uint32_t flags)
: mLooper(looper),
mOutputFormat(outputFormat),
@@ -417,7 +416,7 @@
mSetEncoderFormat(false),
mEncoderFormat(0),
mEncoderDataSpace(0),
- mGraphicBufferConsumer(consumer),
+ mPersistentSurface(persistentSurface),
mInputBufferTimeOffsetUs(0),
mFirstSampleSystemTimeUs(-1ll),
mPausePending(false),
@@ -514,12 +513,11 @@
if (mFlags & FLAG_USE_SURFACE_INPUT) {
CHECK(mIsVideo);
- if (mGraphicBufferConsumer != NULL) {
+ if (mPersistentSurface != NULL) {
// When using persistent surface, we are only interested in the
// consumer, but have to use PersistentSurface as a wrapper to
// pass consumer over messages (similar to BufferProducerWrapper)
- err = mEncoder->setInputSurface(
- new PersistentSurface(NULL, mGraphicBufferConsumer));
+ err = mEncoder->setInputSurface(mPersistentSurface);
} else {
err = mEncoder->createInputSurface(&mGraphicBufferProducer);
}
@@ -689,7 +687,7 @@
#endif // DEBUG_DRIFT_TIME
}
- sp<ABuffer> inbuf;
+ sp<MediaCodecBuffer> inbuf;
status_t err = mEncoder->getInputBuffer(bufferIndex, &inbuf);
if (err != OK || inbuf == NULL) {
mbuf->release();
@@ -851,7 +849,7 @@
break;
}
- sp<ABuffer> outbuf;
+ sp<MediaCodecBuffer> outbuf;
status_t err = mEncoder->getOutputBuffer(index, &outbuf);
if (err != OK || outbuf == NULL) {
signalEOS();
@@ -906,6 +904,7 @@
}
mbuf->meta_data()->setInt64(kKeyTime, timeUs);
} else {
+ mbuf->meta_data()->setInt64(kKeyTime, 0ll);
mbuf->meta_data()->setInt32(kKeyIsCodecConfig, true);
}
if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) {
@@ -1017,7 +1016,7 @@
CHECK(msg->findInt64("time-offset-us", &mInputBufferTimeOffsetUs));
// Propagate the timestamp offset to GraphicBufferSource.
- if (mIsVideo) {
+ if (mFlags & FLAG_USE_SURFACE_INPUT) {
sp<AMessage> params = new AMessage;
params->setInt64("time-offset-us", mInputBufferTimeOffsetUs);
err = mEncoder->setParameters(params);
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 92ce88c..f2fdbc9 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -94,7 +94,7 @@
sp<IMemory> mMemory;
sp<DataSource> mSource;
String8 mName;
- RemoteDataSource(const sp<DataSource> &source);
+ explicit RemoteDataSource(const sp<DataSource> &source);
DISALLOW_EVIL_CONSTRUCTORS(RemoteDataSource);
};
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 276d731..ad27856 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -66,7 +66,7 @@
const KeyedVector<String8, String8> *headers) {
Mutex::Autolock autoLock(mLock);
- if (mImpl != NULL) {
+ if (mImpl != NULL || path == NULL) {
return -EINVAL;
}
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index e40dbcf..a29aff0 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -24,506 +24,18 @@
#include <utils/Log.h>
#include <binder/IServiceManager.h>
-#include <media/IMediaPlayerService.h>
#include <media/IMediaCodecService.h>
-#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/OMXClient.h>
-#include <cutils/properties.h>
-#include <utils/KeyedVector.h>
#include "include/OMX.h"
namespace android {
-static bool sCodecProcessEnabled = true;
-
-struct MuxOMX : public IOMX {
- MuxOMX(const sp<IOMX> &mediaServerOMX, const sp<IOMX> &mediaCodecOMX);
- virtual ~MuxOMX();
-
- // Nobody should be calling this. In case someone does anyway, just
- // return the media server IOMX.
- // TODO: return NULL
- virtual IBinder *onAsBinder() {
- ALOGE("MuxOMX::onAsBinder should not be called");
- return IInterface::asBinder(mMediaServerOMX).get();
- }
-
- virtual bool livesLocally(node_id node, pid_t pid);
-
- virtual status_t listNodes(List<ComponentInfo> *list);
-
- virtual status_t allocateNode(
- const char *name, const sp<IOMXObserver> &observer,
- sp<IBinder> *nodeBinder,
- node_id *node);
-
- virtual status_t freeNode(node_id node);
-
- virtual status_t sendCommand(
- node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param);
-
- virtual status_t getParameter(
- node_id node, OMX_INDEXTYPE index,
- void *params, size_t size);
-
- virtual status_t setParameter(
- node_id node, OMX_INDEXTYPE index,
- const void *params, size_t size);
-
- virtual status_t getConfig(
- node_id node, OMX_INDEXTYPE index,
- void *params, size_t size);
-
- virtual status_t setConfig(
- node_id node, OMX_INDEXTYPE index,
- const void *params, size_t size);
-
- virtual status_t getState(
- node_id node, OMX_STATETYPE* state);
-
- virtual status_t storeMetaDataInBuffers(
- node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type);
-
- virtual status_t prepareForAdaptivePlayback(
- node_id node, OMX_U32 port_index, OMX_BOOL enable,
- OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight);
-
- virtual status_t configureVideoTunnelMode(
- node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
- OMX_U32 audioHwSync, native_handle_t **sidebandHandle);
-
- virtual status_t enableNativeBuffers(
- node_id node, OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable);
-
- virtual status_t getGraphicBufferUsage(
- node_id node, OMX_U32 port_index, OMX_U32* usage);
-
- virtual status_t useBuffer(
- node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
- buffer_id *buffer, OMX_U32 allottedSize);
-
- virtual status_t useGraphicBuffer(
- node_id node, OMX_U32 port_index,
- const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer);
-
- virtual status_t updateGraphicBufferInMeta(
- node_id node, OMX_U32 port_index,
- const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer);
-
- virtual status_t updateNativeHandleInMeta(
- node_id node, OMX_U32 port_index,
- const sp<NativeHandle> &nativeHandle, buffer_id buffer);
-
- virtual status_t createInputSurface(
- node_id node, OMX_U32 port_index, android_dataspace dataSpace,
- sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type);
-
- virtual status_t createPersistentInputSurface(
- sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferConsumer> *bufferConsumer);
-
- virtual status_t setInputSurface(
- node_id node, OMX_U32 port_index,
- const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type);
-
- virtual status_t signalEndOfInputStream(node_id node);
-
- virtual status_t allocateSecureBuffer(
- node_id node, OMX_U32 port_index, size_t size,
- buffer_id *buffer, void **buffer_data, sp<NativeHandle> *native_handle);
-
- virtual status_t allocateBufferWithBackup(
- node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
- buffer_id *buffer, OMX_U32 allottedSize);
-
- virtual status_t freeBuffer(
- node_id node, OMX_U32 port_index, buffer_id buffer);
-
- virtual status_t fillBuffer(node_id node, buffer_id buffer, int fenceFd);
-
- virtual status_t emptyBuffer(
- node_id node,
- buffer_id buffer,
- OMX_U32 range_offset, OMX_U32 range_length,
- OMX_U32 flags, OMX_TICKS timestamp, int fenceFd);
-
- virtual status_t getExtensionIndex(
- node_id node,
- const char *parameter_name,
- OMX_INDEXTYPE *index);
-
- virtual status_t setInternalOption(
- node_id node,
- OMX_U32 port_index,
- InternalOptionType type,
- const void *data,
- size_t size);
-
-private:
- mutable Mutex mLock;
-
- sp<IOMX> mMediaServerOMX;
- sp<IOMX> mMediaCodecOMX;
- sp<IOMX> mLocalOMX;
-
- typedef enum {
- LOCAL,
- MEDIAPROCESS,
- CODECPROCESS
- } node_location;
-
- KeyedVector<node_id, node_location> mNodeLocation;
-
- bool isLocalNode(node_id node) const;
- bool isLocalNode_l(node_id node) const;
- const sp<IOMX> &getOMX(node_id node) const;
- const sp<IOMX> &getOMX_l(node_id node) const;
-
- static node_location getPreferredCodecLocation(const char *name);
-
- DISALLOW_EVIL_CONSTRUCTORS(MuxOMX);
-};
-
-MuxOMX::MuxOMX(const sp<IOMX> &mediaServerOMX, const sp<IOMX> &mediaCodecOMX)
- : mMediaServerOMX(mediaServerOMX),
- mMediaCodecOMX(mediaCodecOMX) {
- ALOGI("MuxOMX ctor");
-}
-
-MuxOMX::~MuxOMX() {
-}
-
-bool MuxOMX::isLocalNode(node_id node) const {
- Mutex::Autolock autoLock(mLock);
-
- return isLocalNode_l(node);
-}
-
-bool MuxOMX::isLocalNode_l(node_id node) const {
- return mNodeLocation.valueFor(node) == LOCAL;
-}
-
-// static
-MuxOMX::node_location MuxOMX::getPreferredCodecLocation(const char *name) {
- if (sCodecProcessEnabled) {
- // all codecs go to codec process unless excluded using system property, in which case
- // all non-secure decoders, OMX.google.* codecs and encoders can go in the codec process
- // (non-OMX.google.* encoders can be excluded using system property.)
- if ((strcasestr(name, "decoder")
- && strcasestr(name, ".secure") != name + strlen(name) - 7)
- || (strcasestr(name, "encoder")
- && !property_get_bool("media.stagefright.legacyencoder", false))
- || !property_get_bool("media.stagefright.less-secure", false)
- || !strncasecmp(name, "OMX.google.", 11)) {
- return CODECPROCESS;
- }
- // everything else runs in the media server
- return MEDIAPROCESS;
- } else {
-#ifdef __LP64__
- // 64 bit processes always run OMX remote on MediaServer
- return MEDIAPROCESS;
-#else
- // 32 bit processes run only OMX.google.* components locally
- if (!strncasecmp(name, "OMX.google.", 11)) {
- return LOCAL;
- }
- return MEDIAPROCESS;
-#endif
- }
-}
-
-const sp<IOMX> &MuxOMX::getOMX(node_id node) const {
- Mutex::Autolock autoLock(mLock);
- return getOMX_l(node);
-}
-
-const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const {
- node_location loc = mNodeLocation.valueFor(node);
- if (loc == LOCAL) {
- return mLocalOMX;
- } else if (loc == MEDIAPROCESS) {
- return mMediaServerOMX;
- } else if (loc == CODECPROCESS) {
- return mMediaCodecOMX;
- }
- ALOGE("Couldn't determine node location for node %d: %d, using local", node, loc);
- return mLocalOMX;
-}
-
-bool MuxOMX::livesLocally(node_id node, pid_t pid) {
- return getOMX(node)->livesLocally(node, pid);
-}
-
-status_t MuxOMX::listNodes(List<ComponentInfo> *list) {
- Mutex::Autolock autoLock(mLock);
-
- if (mLocalOMX == NULL) {
- mLocalOMX = new OMX;
- }
-
- return mLocalOMX->listNodes(list);
-}
-
-status_t MuxOMX::allocateNode(
- const char *name, const sp<IOMXObserver> &observer,
- sp<IBinder> *nodeBinder,
- node_id *node) {
- Mutex::Autolock autoLock(mLock);
-
- sp<IOMX> omx;
-
- node_location loc = getPreferredCodecLocation(name);
- if (loc == CODECPROCESS) {
- omx = mMediaCodecOMX;
- } else if (loc == MEDIAPROCESS) {
- omx = mMediaServerOMX;
- } else {
- if (mLocalOMX == NULL) {
- mLocalOMX = new OMX;
- }
- omx = mLocalOMX;
- }
-
- status_t err = omx->allocateNode(name, observer, nodeBinder, node);
- ALOGV("allocated node_id %x on %s OMX", *node, omx == mMediaCodecOMX ? "codecprocess" :
- omx == mMediaServerOMX ? "mediaserver" : "local");
-
-
- if (err != OK) {
- return err;
- }
-
- mNodeLocation.add(*node, loc);
-
- return OK;
-}
-
-status_t MuxOMX::freeNode(node_id node) {
- Mutex::Autolock autoLock(mLock);
-
- // exit if we have already freed the node
- if (mNodeLocation.indexOfKey(node) < 0) {
- ALOGD("MuxOMX::freeNode: node %d seems to be released already --- ignoring.", node);
- return OK;
- }
-
- status_t err = getOMX_l(node)->freeNode(node);
-
- if (err != OK) {
- return err;
- }
-
- mNodeLocation.removeItem(node);
-
- return OK;
-}
-
-status_t MuxOMX::sendCommand(
- node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
- return getOMX(node)->sendCommand(node, cmd, param);
-}
-
-status_t MuxOMX::getParameter(
- node_id node, OMX_INDEXTYPE index,
- void *params, size_t size) {
- return getOMX(node)->getParameter(node, index, params, size);
-}
-
-status_t MuxOMX::setParameter(
- node_id node, OMX_INDEXTYPE index,
- const void *params, size_t size) {
- return getOMX(node)->setParameter(node, index, params, size);
-}
-
-status_t MuxOMX::getConfig(
- node_id node, OMX_INDEXTYPE index,
- void *params, size_t size) {
- return getOMX(node)->getConfig(node, index, params, size);
-}
-
-status_t MuxOMX::setConfig(
- node_id node, OMX_INDEXTYPE index,
- const void *params, size_t size) {
- return getOMX(node)->setConfig(node, index, params, size);
-}
-
-status_t MuxOMX::getState(
- node_id node, OMX_STATETYPE* state) {
- return getOMX(node)->getState(node, state);
-}
-
-status_t MuxOMX::storeMetaDataInBuffers(
- node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
- return getOMX(node)->storeMetaDataInBuffers(node, port_index, enable, type);
-}
-
-status_t MuxOMX::prepareForAdaptivePlayback(
- node_id node, OMX_U32 port_index, OMX_BOOL enable,
- OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) {
- return getOMX(node)->prepareForAdaptivePlayback(
- node, port_index, enable, maxFrameWidth, maxFrameHeight);
-}
-
-status_t MuxOMX::configureVideoTunnelMode(
- node_id node, OMX_U32 portIndex, OMX_BOOL enable,
- OMX_U32 audioHwSync, native_handle_t **sidebandHandle) {
- return getOMX(node)->configureVideoTunnelMode(
- node, portIndex, enable, audioHwSync, sidebandHandle);
-}
-
-status_t MuxOMX::enableNativeBuffers(
- node_id node, OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable) {
- return getOMX(node)->enableNativeBuffers(node, port_index, graphic, enable);
-}
-
-status_t MuxOMX::getGraphicBufferUsage(
- node_id node, OMX_U32 port_index, OMX_U32* usage) {
- return getOMX(node)->getGraphicBufferUsage(node, port_index, usage);
-}
-
-status_t MuxOMX::useBuffer(
- node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
- buffer_id *buffer, OMX_U32 allottedSize) {
- return getOMX(node)->useBuffer(node, port_index, params, buffer, allottedSize);
-}
-
-status_t MuxOMX::useGraphicBuffer(
- node_id node, OMX_U32 port_index,
- const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
- return getOMX(node)->useGraphicBuffer(
- node, port_index, graphicBuffer, buffer);
-}
-
-status_t MuxOMX::updateGraphicBufferInMeta(
- node_id node, OMX_U32 port_index,
- const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) {
- return getOMX(node)->updateGraphicBufferInMeta(
- node, port_index, graphicBuffer, buffer);
-}
-
-status_t MuxOMX::updateNativeHandleInMeta(
- node_id node, OMX_U32 port_index,
- const sp<NativeHandle> &nativeHandle, buffer_id buffer) {
- return getOMX(node)->updateNativeHandleInMeta(
- node, port_index, nativeHandle, buffer);
-}
-
-status_t MuxOMX::createInputSurface(
- node_id node, OMX_U32 port_index, android_dataspace dataSpace,
- sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
- status_t err = getOMX(node)->createInputSurface(
- node, port_index, dataSpace, bufferProducer, type);
- return err;
-}
-
-status_t MuxOMX::createPersistentInputSurface(
- sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferConsumer> *bufferConsumer) {
- sp<IOMX> omx;
- {
- Mutex::Autolock autoLock(mLock);
- if (property_get_bool("media.stagefright.legacyencoder", false)) {
- omx = mMediaServerOMX;
- } else {
- omx = mMediaCodecOMX;
- }
- }
- return omx->createPersistentInputSurface(
- bufferProducer, bufferConsumer);
-}
-
-status_t MuxOMX::setInputSurface(
- node_id node, OMX_U32 port_index,
- const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type) {
- return getOMX(node)->setInputSurface(node, port_index, bufferConsumer, type);
-}
-
-status_t MuxOMX::signalEndOfInputStream(node_id node) {
- return getOMX(node)->signalEndOfInputStream(node);
-}
-
-status_t MuxOMX::allocateSecureBuffer(
- node_id node, OMX_U32 port_index, size_t size,
- buffer_id *buffer, void **buffer_data, sp<NativeHandle> *native_handle) {
- return getOMX(node)->allocateSecureBuffer(
- node, port_index, size, buffer, buffer_data, native_handle);
-}
-
-status_t MuxOMX::allocateBufferWithBackup(
- node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
- buffer_id *buffer, OMX_U32 allottedSize) {
- return getOMX(node)->allocateBufferWithBackup(
- node, port_index, params, buffer, allottedSize);
-}
-
-status_t MuxOMX::freeBuffer(
- node_id node, OMX_U32 port_index, buffer_id buffer) {
- return getOMX(node)->freeBuffer(node, port_index, buffer);
-}
-
-status_t MuxOMX::fillBuffer(node_id node, buffer_id buffer, int fenceFd) {
- return getOMX(node)->fillBuffer(node, buffer, fenceFd);
-}
-
-status_t MuxOMX::emptyBuffer(
- node_id node,
- buffer_id buffer,
- OMX_U32 range_offset, OMX_U32 range_length,
- OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
- return getOMX(node)->emptyBuffer(
- node, buffer, range_offset, range_length, flags, timestamp, fenceFd);
-}
-
-status_t MuxOMX::getExtensionIndex(
- node_id node,
- const char *parameter_name,
- OMX_INDEXTYPE *index) {
- return getOMX(node)->getExtensionIndex(node, parameter_name, index);
-}
-
-status_t MuxOMX::setInternalOption(
- node_id node,
- OMX_U32 port_index,
- InternalOptionType type,
- const void *data,
- size_t size) {
- return getOMX(node)->setInternalOption(node, port_index, type, data, size);
-}
-
OMXClient::OMXClient() {
- char value[PROPERTY_VALUE_MAX];
- if (property_get("media.stagefright.codecremote", value, NULL)
- && (!strcmp("0", value) || !strcasecmp("false", value))) {
- sCodecProcessEnabled = false;
- }
}
status_t OMXClient::connect() {
sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> playerbinder = sm->getService(String16("media.player"));
- sp<IMediaPlayerService> mediaservice = interface_cast<IMediaPlayerService>(playerbinder);
-
- if (mediaservice.get() == NULL) {
- ALOGE("Cannot obtain IMediaPlayerService");
- return NO_INIT;
- }
-
- sp<IOMX> mediaServerOMX = mediaservice->getOMX();
- if (mediaServerOMX.get() == NULL) {
- ALOGE("Cannot obtain mediaserver IOMX");
- return NO_INIT;
- }
-
- // If we don't want to use the codec process, and the media server OMX
- // is local, use it directly instead of going through MuxOMX
- if (!sCodecProcessEnabled &&
- mediaServerOMX->livesLocally(0 /* node */, getpid())) {
- mOMX = mediaServerOMX;
- return OK;
- }
-
sp<IBinder> codecbinder = sm->getService(String16("media.codec"));
sp<IMediaCodecService> codecservice = interface_cast<IMediaCodecService>(codecbinder);
@@ -532,22 +44,17 @@
return NO_INIT;
}
- sp<IOMX> mediaCodecOMX = codecservice->getOMX();
- if (mediaCodecOMX.get() == NULL) {
+ mOMX = codecservice->getOMX();
+ if (mOMX.get() == NULL) {
ALOGE("Cannot obtain mediacodec IOMX");
return NO_INIT;
}
- mOMX = new MuxOMX(mediaServerOMX, mediaCodecOMX);
-
return OK;
}
void OMXClient::disconnect() {
- if (mOMX.get() != NULL) {
- mOMX.clear();
- mOMX = NULL;
- }
+ mOMX.clear();
}
} // namespace android
diff --git a/media/libstagefright/SimpleDecodingSource.cpp b/media/libstagefright/SimpleDecodingSource.cpp
index de21c5e..4c4d93e 100644
--- a/media/libstagefright/SimpleDecodingSource.cpp
+++ b/media/libstagefright/SimpleDecodingSource.cpp
@@ -17,7 +17,7 @@
#include <gui/Surface.h>
#include <media/ICrypto.h>
-#include <media/stagefright/foundation/ABuffer.h>
+#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>
@@ -225,7 +225,7 @@
break;
}
- sp<ABuffer> in_buffer;
+ sp<MediaCodecBuffer> in_buffer;
if (res == OK) {
res = mCodec->getInputBuffer(in_ix, &in_buffer);
}
@@ -330,7 +330,7 @@
return res;
}
- sp<ABuffer> out_buffer;
+ sp<MediaCodecBuffer> out_buffer;
res = mCodec->getOutputBuffer(out_ix, &out_buffer);
if (res != OK) {
ALOGW("[%s] could not get output buffer #%zu",
diff --git a/media/libstagefright/SkipCutBuffer.cpp b/media/libstagefright/SkipCutBuffer.cpp
index d30be88..ee9016d 100644
--- a/media/libstagefright/SkipCutBuffer.cpp
+++ b/media/libstagefright/SkipCutBuffer.cpp
@@ -88,7 +88,8 @@
buffer->set_range(0, copied);
}
-void SkipCutBuffer::submit(const sp<ABuffer>& buffer) {
+template <typename T>
+void SkipCutBuffer::submitInternal(const sp<T>& buffer) {
if (mCutBuffer == NULL) {
// passthrough mode
return;
@@ -120,6 +121,14 @@
buffer->setRange(0, copied);
}
+void SkipCutBuffer::submit(const sp<ABuffer>& buffer) {
+ submitInternal(buffer);
+}
+
+void SkipCutBuffer::submit(const sp<MediaCodecBuffer>& buffer) {
+ submitInternal(buffer);
+}
+
void SkipCutBuffer::clear() {
mWriteHead = mReadHead = 0;
mFrontPadding = mSkip;
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index be5067d..65bb428 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -27,8 +27,8 @@
#include <media/ICrypto.h>
#include <media/IMediaHTTPService.h>
+#include <media/MediaCodecBuffer.h>
-#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/ColorConverter.h>
@@ -223,7 +223,7 @@
return NULL;
}
- Vector<sp<ABuffer> > inputBuffers;
+ Vector<sp<MediaCodecBuffer> > inputBuffers;
err = decoder->getInputBuffers(&inputBuffers);
if (err != OK) {
ALOGW("failed to get input buffers: %d (%s)", err, asString(err));
@@ -232,7 +232,7 @@
return NULL;
}
- Vector<sp<ABuffer> > outputBuffers;
+ Vector<sp<MediaCodecBuffer> > outputBuffers;
err = decoder->getOutputBuffers(&outputBuffers);
if (err != OK) {
ALOGW("failed to get output buffers: %d (%s)", err, asString(err));
@@ -264,7 +264,7 @@
size_t inputIndex = -1;
int64_t ptsUs = 0ll;
uint32_t flags = 0;
- sp<ABuffer> codecBuffer = NULL;
+ sp<MediaCodecBuffer> codecBuffer = NULL;
while (haveMoreInputs) {
err = decoder->dequeueInputBuffer(&inputIndex, kBufferTimeOutUs);
@@ -376,7 +376,7 @@
}
ALOGV("successfully decoded video frame.");
- sp<ABuffer> videoFrameBuffer = outputBuffers.itemAt(index);
+ sp<MediaCodecBuffer> videoFrameBuffer = outputBuffers.itemAt(index);
if (thumbNailTime >= 0) {
if (timeUs != thumbNailTime) {
@@ -754,9 +754,9 @@
if (numTracks == 1) {
const char *fileMIME;
- CHECK(meta->findCString(kKeyMIMEType, &fileMIME));
- if (!strcasecmp(fileMIME, "video/x-matroska")) {
+ if (meta->findCString(kKeyMIMEType, &fileMIME) &&
+ !strcasecmp(fileMIME, "video/x-matroska")) {
sp<MetaData> trackMeta = mExtractor->getTrackMetaData(0);
const char *trackMIME;
CHECK(trackMeta->findCString(kKeyMIMEType, &trackMIME));
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 36be7a0..34d7546 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -637,6 +637,11 @@
msg->setInt32("track-id", trackID);
}
+ const char *lang;
+ if (meta->findCString(kKeyMediaLanguage, &lang)) {
+ msg->setString("language", lang);
+ }
+
if (!strncasecmp("video/", mime, 6)) {
int32_t width, height;
if (!meta->findInt32(kKeyWidth, &width)
@@ -1273,6 +1278,11 @@
meta->setInt32(kKeyMaxBitRate, maxBitrate);
}
+ AString lang;
+ if (msg->findString("language", &lang)) {
+ meta->setCString(kKeyMediaLanguage, lang.c_str());
+ }
+
if (mime.startsWith("video/")) {
int32_t width;
int32_t height;
@@ -1505,6 +1515,7 @@
{ MEDIA_MIMETYPE_AUDIO_AAC, AUDIO_FORMAT_AAC },
{ MEDIA_MIMETYPE_AUDIO_VORBIS, AUDIO_FORMAT_VORBIS },
{ MEDIA_MIMETYPE_AUDIO_OPUS, AUDIO_FORMAT_OPUS},
+ { MEDIA_MIMETYPE_AUDIO_AC3, AUDIO_FORMAT_AC3},
{ 0, AUDIO_FORMAT_INVALID }
};
diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp
index 0396dc6..9f15cf7 100644
--- a/media/libstagefright/avc_utils.cpp
+++ b/media/libstagefright/avc_utils.cpp
@@ -447,7 +447,8 @@
return meta;
}
-bool IsIDR(const sp<ABuffer> &buffer) {
+template <typename T>
+bool IsIDRInternal(const sp<T> &buffer) {
const uint8_t *data = buffer->data();
size_t size = buffer->size();
@@ -469,6 +470,14 @@
return foundIDR;
}
+bool IsIDR(const sp<ABuffer> &buffer) {
+ return IsIDRInternal(buffer);
+}
+
+bool IsIDR(const sp<MediaCodecBuffer> &buffer) {
+ return IsIDRInternal(buffer);
+}
+
bool IsAVCReferenceFrame(const sp<ABuffer> &accessUnit) {
const uint8_t *data = accessUnit->data();
size_t size = accessUnit->size();
diff --git a/media/libstagefright/codecs/aacdec/Android.mk b/media/libstagefright/codecs/aacdec/Android.mk
index 84ea708..6490f8f 100644
--- a/media/libstagefright/codecs/aacdec/Android.mk
+++ b/media/libstagefright/codecs/aacdec/Android.mk
@@ -19,7 +19,6 @@
LOCAL_CFLAGS :=
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow unsigned-integer-overflow
LOCAL_STATIC_LIBRARIES := libFraunhoferAAC
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 1c5e3c6..9fbdb72 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -62,6 +62,7 @@
OMX_AUDIO_AACObjectHE_PS,
OMX_AUDIO_AACObjectLD,
OMX_AUDIO_AACObjectELD,
+ OMX_AUDIO_AACObjectER_Scalable,
};
SoftAAC2::SoftAAC2(
diff --git a/media/libstagefright/codecs/aacenc/Android.mk b/media/libstagefright/codecs/aacenc/Android.mk
index 71c374b..2f34e83 100644
--- a/media/libstagefright/codecs/aacenc/Android.mk
+++ b/media/libstagefright/codecs/aacenc/Android.mk
@@ -78,7 +78,6 @@
$(LOCAL_PATH)/basic_op
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow unsigned-integer-overflow
include $(BUILD_STATIC_LIBRARY)
@@ -106,7 +105,6 @@
LOCAL_CFLAGS :=
LOCAL_CFLAGS += -Werror
- LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow unsigned-integer-overflow
LOCAL_STATIC_LIBRARIES := libFraunhoferAAC
@@ -132,7 +130,6 @@
LOCAL_CFLAGS := -DOSCL_IMPORT_REF=
LOCAL_CFLAGS += -Werror
- LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow unsigned-integer-overflow
LOCAL_STATIC_LIBRARIES := \
diff --git a/media/libstagefright/codecs/amrnb/common/Android.mk b/media/libstagefright/codecs/amrnb/common/Android.mk
index 15220a4..0bb5724 100644
--- a/media/libstagefright/codecs/amrnb/common/Android.mk
+++ b/media/libstagefright/codecs/amrnb/common/Android.mk
@@ -68,7 +68,6 @@
-D"OSCL_UNUSED_ARG(x)=(void)(x)" -DOSCL_IMPORT_REF= -DOSCL_EXPORT_REF=
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
#addressing b/25409744
#LOCAL_SANITIZE := signed-integer-overflow unsigned-integer-overflow
diff --git a/media/libstagefright/codecs/amrnb/dec/Android.mk b/media/libstagefright/codecs/amrnb/dec/Android.mk
index 7967ec3..3959b80 100644
--- a/media/libstagefright/codecs/amrnb/dec/Android.mk
+++ b/media/libstagefright/codecs/amrnb/dec/Android.mk
@@ -48,7 +48,6 @@
-D"OSCL_UNUSED_ARG(x)=(void)(x)" -DOSCL_IMPORT_REF=
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
#LOCAL_SANITIZE := signed-integer-overflow
LOCAL_MODULE := libstagefright_amrnbdec
@@ -73,7 +72,6 @@
LOCAL_CFLAGS := -DOSCL_IMPORT_REF=
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
#LOCAL_SANITIZE := signed-integer-overflow
LOCAL_STATIC_LIBRARIES := \
@@ -104,7 +102,6 @@
LOCAL_SHARED_LIBRARIES := \
libstagefright_amrnb_common libaudioutils liblog
-LOCAL_CLANG := true
#LOCAL_SANITIZE := signed-integer-overflow
LOCAL_MODULE := libstagefright_amrnbdec_test
diff --git a/media/libstagefright/codecs/amrnb/enc/Android.mk b/media/libstagefright/codecs/amrnb/enc/Android.mk
index f8a41af..af1efb9 100644
--- a/media/libstagefright/codecs/amrnb/enc/Android.mk
+++ b/media/libstagefright/codecs/amrnb/enc/Android.mk
@@ -70,7 +70,6 @@
-D"OSCL_UNUSED_ARG(x)=(void)(x)"
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
#addressing b/25409744
#LOCAL_SANITIZE := signed-integer-overflow
@@ -94,7 +93,6 @@
$(LOCAL_PATH)/../common
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
#addressing b/25409744
#LOCAL_SANITIZE := signed-integer-overflow
@@ -127,7 +125,6 @@
LOCAL_SHARED_LIBRARIES := \
libstagefright_amrnb_common
-LOCAL_CLANG := true
#addressing b/25409744
#LOCAL_SANITIZE := signed-integer-overflow
diff --git a/media/libstagefright/codecs/amrwb/Android.mk b/media/libstagefright/codecs/amrwb/Android.mk
index 1649c4a..73a1751 100644
--- a/media/libstagefright/codecs/amrwb/Android.mk
+++ b/media/libstagefright/codecs/amrwb/Android.mk
@@ -51,7 +51,6 @@
-D"OSCL_UNUSED_ARG(x)=(void)(x)" -DOSCL_IMPORT_REF=
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
LOCAL_MODULE := libstagefright_amrwbdec
@@ -74,7 +73,6 @@
LOCAL_SHARED_LIBRARIES := \
libaudioutils
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
LOCAL_MODULE := libstagefright_amrwbdec_test
diff --git a/media/libstagefright/codecs/amrwbenc/Android.mk b/media/libstagefright/codecs/amrwbenc/Android.mk
index 026006e..3395fc1 100644
--- a/media/libstagefright/codecs/amrwbenc/Android.mk
+++ b/media/libstagefright/codecs/amrwbenc/Android.mk
@@ -102,7 +102,6 @@
$(LOCAL_PATH)/inc
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
#LOCAL_SANITIZE := signed-integer-overflow
include $(BUILD_STATIC_LIBRARY)
@@ -120,7 +119,6 @@
frameworks/native/include/media/openmax
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
LOCAL_STATIC_LIBRARIES := \
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c b/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c
index 0cb0097..7c094f3 100644
--- a/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c
+++ b/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c
@@ -90,7 +90,7 @@
VO_AUDIO_CODECAPI AudioAPI;
VO_MEM_OPERATOR moper;
VO_CODEC_INIT_USERDATA useData;
- VO_HANDLE hCodec;
+ VO_HANDLE hCodec = NULL;
VO_CODECBUFFER inData;
VO_CODECBUFFER outData;
VO_AUDIO_OUTPUTINFO outFormat;
@@ -211,7 +211,7 @@
if(returnCode == 0)
{
framenum++;
- printf(" Frames processed: %hd\r", framenum);
+ printf(" Frames processed: %d\r", framenum);
if(framenum == 1)
{
fwrite(OutputBuf, 1, outData.Length + size1, fdst);
diff --git a/media/libstagefright/codecs/avc/common/Android.mk b/media/libstagefright/codecs/avc/common/Android.mk
index ed0f8ca..ecf0884 100644
--- a/media/libstagefright/codecs/avc/common/Android.mk
+++ b/media/libstagefright/codecs/avc/common/Android.mk
@@ -17,7 +17,6 @@
$(LOCAL_PATH)/include
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/avc/enc/Android.mk b/media/libstagefright/codecs/avc/enc/Android.mk
index 8ff2f35..8249d66 100644
--- a/media/libstagefright/codecs/avc/enc/Android.mk
+++ b/media/libstagefright/codecs/avc/enc/Android.mk
@@ -31,7 +31,6 @@
-DOSCL_IMPORT_REF= -D"OSCL_UNUSED_ARG(x)=(void)(x)" -DOSCL_EXPORT_REF=
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
include $(BUILD_STATIC_LIBRARY)
@@ -60,7 +59,7 @@
libstagefright_avcenc
LOCAL_SHARED_LIBRARIES := \
- libstagefright \
+ libmedia \
libstagefright_avc_common \
libstagefright_enc_common \
libstagefright_foundation \
@@ -74,7 +73,6 @@
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
include $(BUILD_SHARED_LIBRARY)
@@ -94,7 +92,6 @@
LOCAL_CFLAGS := \
-DOSCL_IMPORT_REF= -DOSCL_UNUSED_ARG= -DOSCL_EXPORT_REF=
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
LOCAL_STATIC_LIBRARIES := \
diff --git a/media/libstagefright/codecs/avcdec/Android.mk b/media/libstagefright/codecs/avcdec/Android.mk
index ef0dbfd..9da8a6f 100644
--- a/media/libstagefright/codecs/avcdec/Android.mk
+++ b/media/libstagefright/codecs/avcdec/Android.mk
@@ -14,13 +14,12 @@
LOCAL_C_INCLUDES += $(TOP)/frameworks/av/media/libstagefright/include
LOCAL_C_INCLUDES += $(TOP)/frameworks/native/include/media/openmax
-LOCAL_SHARED_LIBRARIES := libstagefright
+LOCAL_SHARED_LIBRARIES := libmedia
LOCAL_SHARED_LIBRARIES += libstagefright_omx
LOCAL_SHARED_LIBRARIES += libstagefright_foundation
LOCAL_SHARED_LIBRARIES += libutils
LOCAL_SHARED_LIBRARIES += liblog
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
LOCAL_LDFLAGS := -Wl,-Bsymbolic
diff --git a/media/libstagefright/codecs/avcenc/Android.mk b/media/libstagefright/codecs/avcenc/Android.mk
index 70e531b..2d24584 100644
--- a/media/libstagefright/codecs/avcenc/Android.mk
+++ b/media/libstagefright/codecs/avcenc/Android.mk
@@ -12,18 +12,15 @@
LOCAL_C_INCLUDES := $(TOP)/external/libavc/encoder
LOCAL_C_INCLUDES += $(TOP)/external/libavc/common
LOCAL_C_INCLUDES += $(TOP)/frameworks/av/media/libstagefright/include
-LOCAL_C_INCLUDES += $(TOP)/frameworks/native/include/media/openmax
-LOCAL_C_INCLUDES += $(TOP)/frameworks/av/media/libstagefright/include
LOCAL_C_INCLUDES += $(TOP)/frameworks/native/include/media/hardware
LOCAL_C_INCLUDES += $(TOP)/frameworks/native/include/media/openmax
-LOCAL_SHARED_LIBRARIES := libstagefright
+LOCAL_SHARED_LIBRARIES := libmedia
LOCAL_SHARED_LIBRARIES += libstagefright_omx
LOCAL_SHARED_LIBRARIES += libstagefright_foundation
LOCAL_SHARED_LIBRARIES += libutils
LOCAL_SHARED_LIBRARIES += liblog
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
LOCAL_LDFLAGS := -Wl,-Bsymbolic
diff --git a/media/libstagefright/codecs/flac/enc/Android.mk b/media/libstagefright/codecs/flac/enc/Android.mk
index 7e6e015..a3c37fb 100644
--- a/media/libstagefright/codecs/flac/enc/Android.mk
+++ b/media/libstagefright/codecs/flac/enc/Android.mk
@@ -10,11 +10,10 @@
external/flac/include
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow unsigned-integer-overflow
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils liblog
+ libmedia libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_STATIC_LIBRARIES := \
libFLAC \
diff --git a/media/libstagefright/codecs/g711/dec/Android.mk b/media/libstagefright/codecs/g711/dec/Android.mk
index b36c99d..b002208 100644
--- a/media/libstagefright/codecs/g711/dec/Android.mk
+++ b/media/libstagefright/codecs/g711/dec/Android.mk
@@ -9,13 +9,12 @@
frameworks/native/include/media/openmax
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils liblog
+ libmedia libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_MODULE := libstagefright_soft_g711dec
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow unsigned-integer-overflow
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/gsm/dec/Android.mk b/media/libstagefright/codecs/gsm/dec/Android.mk
index fe8c830..5d6c289 100644
--- a/media/libstagefright/codecs/gsm/dec/Android.mk
+++ b/media/libstagefright/codecs/gsm/dec/Android.mk
@@ -10,11 +10,10 @@
external/libgsm/inc
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow unsigned-integer-overflow
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils liblog
+ libmedia libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_STATIC_LIBRARIES := \
libgsm
diff --git a/media/libstagefright/codecs/hevcdec/Android.mk b/media/libstagefright/codecs/hevcdec/Android.mk
index 78c4637..83e377c 100644
--- a/media/libstagefright/codecs/hevcdec/Android.mk
+++ b/media/libstagefright/codecs/hevcdec/Android.mk
@@ -13,10 +13,9 @@
LOCAL_C_INCLUDES += $(TOP)/external/libhevc/common
LOCAL_C_INCLUDES += $(TOP)/frameworks/av/media/libstagefright/include
LOCAL_C_INCLUDES += $(TOP)/frameworks/native/include/media/openmax
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
-LOCAL_SHARED_LIBRARIES := libstagefright
+LOCAL_SHARED_LIBRARIES := libmedia
LOCAL_SHARED_LIBRARIES += libstagefright_omx
LOCAL_SHARED_LIBRARIES += libstagefright_foundation
LOCAL_SHARED_LIBRARIES += libutils
diff --git a/media/libstagefright/codecs/m4v_h263/dec/Android.mk b/media/libstagefright/codecs/m4v_h263/dec/Android.mk
index eb39b44..e83d24d 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/Android.mk
+++ b/media/libstagefright/codecs/m4v_h263/dec/Android.mk
@@ -47,7 +47,6 @@
LOCAL_CFLAGS := -DOSCL_EXPORT_REF= -DOSCL_IMPORT_REF=
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
include $(BUILD_STATIC_LIBRARY)
@@ -71,13 +70,12 @@
libstagefright_m4vh263dec
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils liblog
+ libmedia libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_MODULE := libstagefright_soft_mpeg4dec
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/m4v_h263/enc/Android.mk b/media/libstagefright/codecs/m4v_h263/enc/Android.mk
index ab079e8..1ff8b47 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/Android.mk
+++ b/media/libstagefright/codecs/m4v_h263/enc/Android.mk
@@ -34,7 +34,6 @@
$(TOP)/frameworks/native/include/media/openmax
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
include $(BUILD_STATIC_LIBRARY)
@@ -64,7 +63,7 @@
libstagefright_m4vh263enc
LOCAL_SHARED_LIBRARIES := \
- libstagefright \
+ libmedia \
libstagefright_enc_common \
libstagefright_foundation \
libstagefright_omx \
@@ -77,7 +76,6 @@
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
include $(BUILD_SHARED_LIBRARY)
@@ -93,7 +91,6 @@
$(LOCAL_PATH)/include
LOCAL_CFLAGS := -DOSCL_EXPORT_REF= -DOSCL_IMPORT_REF= -DBX_RC
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
LOCAL_STATIC_LIBRARIES := \
diff --git a/media/libstagefright/codecs/mp3dec/Android.mk b/media/libstagefright/codecs/mp3dec/Android.mk
index 11581c1..62dce35 100644
--- a/media/libstagefright/codecs/mp3dec/Android.mk
+++ b/media/libstagefright/codecs/mp3dec/Android.mk
@@ -54,7 +54,6 @@
-D"OSCL_UNUSED_ARG(x)=(void)(x)"
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
LOCAL_MODULE := libstagefright_mp3dec
@@ -77,11 +76,10 @@
$(LOCAL_PATH)/include
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils liblog
+ libmedia libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_STATIC_LIBRARIES := \
libstagefright_mp3dec
@@ -103,7 +101,6 @@
$(LOCAL_PATH)/test/include \
$(call include-path-for, audio-utils)
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
LOCAL_STATIC_LIBRARIES := \
libstagefright_mp3dec libsndfile
diff --git a/media/libstagefright/codecs/mpeg2dec/Android.mk b/media/libstagefright/codecs/mpeg2dec/Android.mk
index f1c1719..65a081e 100644
--- a/media/libstagefright/codecs/mpeg2dec/Android.mk
+++ b/media/libstagefright/codecs/mpeg2dec/Android.mk
@@ -14,14 +14,13 @@
LOCAL_C_INCLUDES += $(TOP)/frameworks/av/media/libstagefright/include
LOCAL_C_INCLUDES += $(TOP)/frameworks/native/include/media/openmax
-LOCAL_SHARED_LIBRARIES := libstagefright
+LOCAL_SHARED_LIBRARIES := libmedia
LOCAL_SHARED_LIBRARIES += libstagefright_omx
LOCAL_SHARED_LIBRARIES += libstagefright_foundation
LOCAL_SHARED_LIBRARIES += libutils
LOCAL_SHARED_LIBRARIES += liblog
LOCAL_LDFLAGS := -Wl,-Bsymbolic
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/on2/dec/Android.mk b/media/libstagefright/codecs/on2/dec/Android.mk
index 76f7600..de1e937 100644
--- a/media/libstagefright/codecs/on2/dec/Android.mk
+++ b/media/libstagefright/codecs/on2/dec/Android.mk
@@ -15,13 +15,12 @@
libvpx
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils liblog
+ libmedia libstagefright_omx libstagefright_foundation libutils liblog
LOCAL_MODULE := libstagefright_soft_vpxdec
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow unsigned-integer-overflow
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/on2/enc/Android.mk b/media/libstagefright/codecs/on2/enc/Android.mk
index 1de318a..f8019d0 100644
--- a/media/libstagefright/codecs/on2/enc/Android.mk
+++ b/media/libstagefright/codecs/on2/enc/Android.mk
@@ -2,7 +2,9 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
- SoftVPXEncoder.cpp
+ SoftVPXEncoder.cpp \
+ SoftVP8Encoder.cpp \
+ SoftVP9Encoder.cpp
LOCAL_C_INCLUDES := \
$(TOP)/external/libvpx/libvpx \
@@ -11,14 +13,13 @@
frameworks/av/media/libstagefright/include \
frameworks/native/include/media/openmax \
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow unsigned-integer-overflow
LOCAL_STATIC_LIBRARIES := \
libvpx
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils liblog \
+ libmedia libstagefright_omx libstagefright_foundation libutils liblog \
libhardware \
LOCAL_MODULE := libstagefright_soft_vpxenc
diff --git a/media/libstagefright/codecs/on2/enc/SoftVP8Encoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVP8Encoder.cpp
new file mode 100644
index 0000000..04737a9
--- /dev/null
+++ b/media/libstagefright/codecs/on2/enc/SoftVP8Encoder.cpp
@@ -0,0 +1,162 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "SoftVP8Encoder"
+#include "SoftVP8Encoder.h"
+
+#include <utils/Log.h>
+#include <utils/misc.h>
+
+#include <media/hardware/HardwareAPI.h>
+#include <media/hardware/MetadataBufferType.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaDefs.h>
+
+#ifndef INT32_MAX
+#define INT32_MAX 2147483647
+#endif
+
+namespace android {
+
+static const CodecProfileLevel kVp8ProfileLevels[] = {
+ { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version0 },
+ { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version1 },
+ { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version2 },
+ { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version3 },
+};
+
+SoftVP8Encoder::SoftVP8Encoder(const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component)
+ : SoftVPXEncoder(
+ name, callbacks, appData, component, "video_encoder.vp8",
+ OMX_VIDEO_CodingVP8, MEDIA_MIMETYPE_VIDEO_VP8, 2,
+ kVp8ProfileLevels, NELEM(kVp8ProfileLevels)),
+ mDCTPartitions(0),
+ mLevel(OMX_VIDEO_VP8Level_Version0) {
+}
+
+void SoftVP8Encoder::setCodecSpecificInterface() {
+ mCodecInterface = vpx_codec_vp8_cx();
+}
+
+void SoftVP8Encoder::setCodecSpecificConfiguration() {
+ switch (mLevel) {
+ case OMX_VIDEO_VP8Level_Version0:
+ mCodecConfiguration->g_profile = 0;
+ break;
+
+ case OMX_VIDEO_VP8Level_Version1:
+ mCodecConfiguration->g_profile = 1;
+ break;
+
+ case OMX_VIDEO_VP8Level_Version2:
+ mCodecConfiguration->g_profile = 2;
+ break;
+
+ case OMX_VIDEO_VP8Level_Version3:
+ mCodecConfiguration->g_profile = 3;
+ break;
+
+ default:
+ mCodecConfiguration->g_profile = 0;
+ }
+}
+
+vpx_codec_err_t SoftVP8Encoder::setCodecSpecificControls() {
+ vpx_codec_err_t codec_return = vpx_codec_control(mCodecContext,
+ VP8E_SET_TOKEN_PARTITIONS,
+ mDCTPartitions);
+ if (codec_return != VPX_CODEC_OK) {
+ ALOGE("Error setting dct partitions for vpx encoder.");
+ }
+ return codec_return;
+}
+
+OMX_ERRORTYPE SoftVP8Encoder::internalGetParameter(OMX_INDEXTYPE index,
+ OMX_PTR param) {
+ // can include extension index OMX_INDEXEXTTYPE
+ const int32_t indexFull = index;
+
+ switch (indexFull) {
+ case OMX_IndexParamVideoVp8:
+ return internalGetVp8Params(
+ (OMX_VIDEO_PARAM_VP8TYPE *)param);
+
+ default:
+ return SoftVPXEncoder::internalGetParameter(index, param);
+ }
+}
+
+OMX_ERRORTYPE SoftVP8Encoder::internalSetParameter(OMX_INDEXTYPE index,
+ const OMX_PTR param) {
+ // can include extension index OMX_INDEXEXTTYPE
+ const int32_t indexFull = index;
+
+ switch (indexFull) {
+ case OMX_IndexParamVideoVp8:
+ return internalSetVp8Params(
+ (const OMX_VIDEO_PARAM_VP8TYPE *)param);
+
+ default:
+ return SoftVPXEncoder::internalSetParameter(index, param);
+ }
+}
+
+OMX_ERRORTYPE SoftVP8Encoder::internalGetVp8Params(
+ OMX_VIDEO_PARAM_VP8TYPE* vp8Params) {
+ if (vp8Params->nPortIndex != kOutputPortIndex) {
+ return OMX_ErrorUnsupportedIndex;
+ }
+
+ vp8Params->eProfile = OMX_VIDEO_VP8ProfileMain;
+ vp8Params->eLevel = mLevel;
+ vp8Params->bErrorResilientMode = mErrorResilience;
+ vp8Params->nDCTPartitions = mDCTPartitions;
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftVP8Encoder::internalSetVp8Params(
+ const OMX_VIDEO_PARAM_VP8TYPE* vp8Params) {
+ if (vp8Params->nPortIndex != kOutputPortIndex) {
+ return OMX_ErrorUnsupportedIndex;
+ }
+
+ if (vp8Params->eProfile != OMX_VIDEO_VP8ProfileMain) {
+ return OMX_ErrorBadParameter;
+ }
+
+ if (vp8Params->eLevel == OMX_VIDEO_VP8Level_Version0 ||
+ vp8Params->eLevel == OMX_VIDEO_VP8Level_Version1 ||
+ vp8Params->eLevel == OMX_VIDEO_VP8Level_Version2 ||
+ vp8Params->eLevel == OMX_VIDEO_VP8Level_Version3) {
+ mLevel = vp8Params->eLevel;
+ } else {
+ return OMX_ErrorBadParameter;
+ }
+
+ mErrorResilience = vp8Params->bErrorResilientMode;
+ if (vp8Params->nDCTPartitions <= kMaxDCTPartitions) {
+ mDCTPartitions = vp8Params->nDCTPartitions;
+ } else {
+ return OMX_ErrorBadParameter;
+ }
+ return OMX_ErrorNone;
+}
+
+} // namespace android
diff --git a/media/libstagefright/codecs/on2/enc/SoftVP8Encoder.h b/media/libstagefright/codecs/on2/enc/SoftVP8Encoder.h
new file mode 100644
index 0000000..b4904bf
--- /dev/null
+++ b/media/libstagefright/codecs/on2/enc/SoftVP8Encoder.h
@@ -0,0 +1,95 @@
+/*
+ * 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 SOFT_VP8_ENCODER_H_
+
+#define SOFT_VP8_ENCODER_H_
+
+#include "SoftVPXEncoder.h"
+
+#include <OMX_VideoExt.h>
+#include <OMX_IndexExt.h>
+
+#include <hardware/gralloc.h>
+
+#include "vpx/vpx_encoder.h"
+#include "vpx/vpx_codec.h"
+#include "vpx/vp8cx.h"
+
+namespace android {
+
+// Exposes a vp8 encoder as an OMX Component
+//
+// In addition to the base class settings, Only following encoder settings are
+// available:
+// - token partitioning
+struct SoftVP8Encoder : public SoftVPXEncoder {
+ SoftVP8Encoder(const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+protected:
+ // Returns current values for requested OMX
+ // parameters
+ virtual OMX_ERRORTYPE internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR param);
+
+ // Validates, extracts and stores relevant OMX
+ // parameters
+ virtual OMX_ERRORTYPE internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR param);
+
+ // Populates |mCodecInterface| with codec specific settings.
+ virtual void setCodecSpecificInterface();
+
+ // Sets codec specific configuration.
+ virtual void setCodecSpecificConfiguration();
+
+ // Initializes codec specific encoder settings.
+ virtual vpx_codec_err_t setCodecSpecificControls();
+
+ // Gets vp8 specific parameters.
+ OMX_ERRORTYPE internalGetVp8Params(
+ OMX_VIDEO_PARAM_VP8TYPE* vp8Params);
+
+ // Handles vp8 specific parameters.
+ OMX_ERRORTYPE internalSetVp8Params(
+ const OMX_VIDEO_PARAM_VP8TYPE* vp8Params);
+
+private:
+ // Max value supported for DCT partitions
+ static const uint32_t kMaxDCTPartitions = 3;
+
+ // vp8 specific configuration parameter
+ // that enables token partitioning of
+ // the stream into substreams
+ int32_t mDCTPartitions;
+
+ // Encoder profile corresponding to OMX level parameter
+ //
+ // The inconsistency in the naming is caused by
+ // OMX spec referring vpx profiles (g_profile)
+ // as "levels" whereas using the name "profile" for
+ // something else.
+ OMX_VIDEO_VP8LEVELTYPE mLevel;
+
+ DISALLOW_EVIL_CONSTRUCTORS(SoftVP8Encoder);
+};
+
+} // namespace android
+
+#endif // SOFT_VP8_ENCODER_H_
diff --git a/media/libstagefright/codecs/on2/enc/SoftVP9Encoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVP9Encoder.cpp
new file mode 100644
index 0000000..4c7290d
--- /dev/null
+++ b/media/libstagefright/codecs/on2/enc/SoftVP9Encoder.cpp
@@ -0,0 +1,162 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "SoftVP9Encoder"
+#include "SoftVP9Encoder.h"
+
+#include <utils/Log.h>
+#include <utils/misc.h>
+
+#include <media/hardware/HardwareAPI.h>
+#include <media/hardware/MetadataBufferType.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaDefs.h>
+
+namespace android {
+
+static const CodecProfileLevel kVp9ProfileLevels[] = {
+ { OMX_VIDEO_VP9Profile0, OMX_VIDEO_VP9Level41 },
+};
+
+SoftVP9Encoder::SoftVP9Encoder(
+ const char *name, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData,
+ OMX_COMPONENTTYPE **component)
+ : SoftVPXEncoder(
+ name, callbacks, appData, component, "video_encoder.vp9",
+ OMX_VIDEO_CodingVP9, MEDIA_MIMETYPE_VIDEO_VP9, 4,
+ kVp9ProfileLevels, NELEM(kVp9ProfileLevels)),
+ mLevel(OMX_VIDEO_VP9Level1),
+ mTileColumns(0),
+ mFrameParallelDecoding(OMX_FALSE) {
+}
+
+void SoftVP9Encoder::setCodecSpecificInterface() {
+ mCodecInterface = vpx_codec_vp9_cx();
+}
+
+void SoftVP9Encoder::setCodecSpecificConfiguration() {
+ mCodecConfiguration->g_profile = 0;
+}
+
+vpx_codec_err_t SoftVP9Encoder::setCodecSpecificControls() {
+ vpx_codec_err_t codecReturn = vpx_codec_control(
+ mCodecContext, VP9E_SET_TILE_COLUMNS, mTileColumns);
+ if (codecReturn != VPX_CODEC_OK) {
+ ALOGE("Error setting VP9E_SET_TILE_COLUMNS to %d. vpx_codec_control() "
+ "returned %d", mTileColumns, codecReturn);
+ return codecReturn;
+ }
+ codecReturn = vpx_codec_control(
+ mCodecContext, VP9E_SET_FRAME_PARALLEL_DECODING,
+ mFrameParallelDecoding);
+ if (codecReturn != VPX_CODEC_OK) {
+ ALOGE("Error setting VP9E_SET_FRAME_PARALLEL_DECODING to %d."
+ "vpx_codec_control() returned %d", mFrameParallelDecoding,
+ codecReturn);
+ return codecReturn;
+ }
+ // For VP9, we always set CPU_USED to 8 (because the realtime default is 0
+ // which is too slow).
+ codecReturn = vpx_codec_control(mCodecContext, VP8E_SET_CPUUSED, 8);
+ if (codecReturn != VPX_CODEC_OK) {
+ ALOGE("Error setting VP8E_SET_CPUUSED to 8. vpx_codec_control() "
+ "returned %d", codecReturn);
+ return codecReturn;
+ }
+ return codecReturn;
+}
+
+OMX_ERRORTYPE SoftVP9Encoder::internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR param) {
+ // can include extension index OMX_INDEXEXTTYPE
+ const int32_t indexFull = index;
+
+ switch (indexFull) {
+ case OMX_IndexParamVideoVp9:
+ return internalGetVp9Params(
+ (OMX_VIDEO_PARAM_VP9TYPE *)param);
+
+ default:
+ return SoftVPXEncoder::internalGetParameter(index, param);
+ }
+}
+
+OMX_ERRORTYPE SoftVP9Encoder::internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR param) {
+ // can include extension index OMX_INDEXEXTTYPE
+ const int32_t indexFull = index;
+
+ switch (indexFull) {
+ case OMX_IndexParamVideoVp9:
+ return internalSetVp9Params(
+ (const OMX_VIDEO_PARAM_VP9TYPE *)param);
+
+ default:
+ return SoftVPXEncoder::internalSetParameter(index, param);
+ }
+}
+
+OMX_ERRORTYPE SoftVP9Encoder::internalGetVp9Params(
+ OMX_VIDEO_PARAM_VP9TYPE *vp9Params) {
+ if (vp9Params->nPortIndex != kOutputPortIndex) {
+ return OMX_ErrorUnsupportedIndex;
+ }
+
+ vp9Params->eProfile = OMX_VIDEO_VP9Profile0;
+ vp9Params->eLevel = mLevel;
+ vp9Params->bErrorResilientMode = mErrorResilience;
+ vp9Params->nTileColumns = mTileColumns;
+ vp9Params->bEnableFrameParallelDecoding = mFrameParallelDecoding;
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftVP9Encoder::internalSetVp9Params(
+ const OMX_VIDEO_PARAM_VP9TYPE *vp9Params) {
+ if (vp9Params->nPortIndex != kOutputPortIndex) {
+ return OMX_ErrorUnsupportedIndex;
+ }
+
+ if (vp9Params->eProfile != OMX_VIDEO_VP9Profile0) {
+ return OMX_ErrorBadParameter;
+ }
+
+ if (vp9Params->eLevel == OMX_VIDEO_VP9Level1 ||
+ vp9Params->eLevel == OMX_VIDEO_VP9Level11 ||
+ vp9Params->eLevel == OMX_VIDEO_VP9Level2 ||
+ vp9Params->eLevel == OMX_VIDEO_VP9Level21 ||
+ vp9Params->eLevel == OMX_VIDEO_VP9Level3 ||
+ vp9Params->eLevel == OMX_VIDEO_VP9Level31 ||
+ vp9Params->eLevel == OMX_VIDEO_VP9Level4 ||
+ vp9Params->eLevel == OMX_VIDEO_VP9Level41 ||
+ vp9Params->eLevel == OMX_VIDEO_VP9Level5 ||
+ vp9Params->eLevel == OMX_VIDEO_VP9Level51 ||
+ vp9Params->eLevel == OMX_VIDEO_VP9Level52 ||
+ vp9Params->eLevel == OMX_VIDEO_VP9Level6 ||
+ vp9Params->eLevel == OMX_VIDEO_VP9Level61 ||
+ vp9Params->eLevel == OMX_VIDEO_VP9Level62) {
+ mLevel = vp9Params->eLevel;
+ } else {
+ return OMX_ErrorBadParameter;
+ }
+
+ mErrorResilience = vp9Params->bErrorResilientMode;
+ mTileColumns = vp9Params->nTileColumns;
+ mFrameParallelDecoding = vp9Params->bEnableFrameParallelDecoding;
+ return OMX_ErrorNone;
+}
+
+} // namespace android
diff --git a/media/libstagefright/codecs/on2/enc/SoftVP9Encoder.h b/media/libstagefright/codecs/on2/enc/SoftVP9Encoder.h
new file mode 100644
index 0000000..85df69a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/enc/SoftVP9Encoder.h
@@ -0,0 +1,93 @@
+/*
+ * 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 SOFT_VP9_ENCODER_H_
+
+#define SOFT_VP9_ENCODER_H_
+
+#include "SoftVPXEncoder.h"
+
+#include <OMX_VideoExt.h>
+#include <OMX_IndexExt.h>
+
+#include <hardware/gralloc.h>
+
+#include "vpx/vpx_encoder.h"
+#include "vpx/vpx_codec.h"
+#include "vpx/vp8cx.h"
+
+namespace android {
+
+// Exposes a VP9 encoder as an OMX Component
+//
+// In addition to the base class settings, Only following encoder settings are
+// available:
+// - tile rows
+// - tile columns
+// - frame parallel mode
+struct SoftVP9Encoder : public SoftVPXEncoder {
+ SoftVP9Encoder(const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+protected:
+ // Returns current values for requested OMX
+ // parameters
+ virtual OMX_ERRORTYPE internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR param);
+
+ // Validates, extracts and stores relevant OMX
+ // parameters
+ virtual OMX_ERRORTYPE internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR param);
+
+ // Populates |mCodecInterface| with codec specific settings.
+ virtual void setCodecSpecificInterface();
+
+ // Sets codec specific configuration.
+ virtual void setCodecSpecificConfiguration();
+
+ // Initializes codec specific encoder settings.
+ virtual vpx_codec_err_t setCodecSpecificControls();
+
+ // Gets vp9 specific parameters.
+ OMX_ERRORTYPE internalGetVp9Params(
+ OMX_VIDEO_PARAM_VP9TYPE* vp9Params);
+
+ // Handles vp9 specific parameters.
+ OMX_ERRORTYPE internalSetVp9Params(
+ const OMX_VIDEO_PARAM_VP9TYPE* vp9Params);
+
+private:
+ // Encoder profile corresponding to OMX level parameter
+ //
+ // The inconsistency in the naming is caused by
+ // OMX spec referring vpx profiles (g_profile)
+ // as "levels" whereas using the name "profile" for
+ // something else.
+ OMX_VIDEO_VP9LEVELTYPE mLevel;
+
+ int32_t mTileColumns;
+
+ OMX_BOOL mFrameParallelDecoding;
+
+ DISALLOW_EVIL_CONSTRUCTORS(SoftVP9Encoder);
+};
+
+} // namespace android
+
+#endif // SOFT_VP9_ENCODER_H_
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
index 5edfbb5..5609032 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
@@ -18,6 +18,9 @@
#define LOG_TAG "SoftVPXEncoder"
#include "SoftVPXEncoder.h"
+#include "SoftVP8Encoder.h"
+#include "SoftVP9Encoder.h"
+
#include <utils/Log.h>
#include <utils/misc.h>
@@ -42,7 +45,6 @@
params->nVersion.s.nStep = 0;
}
-
static int GetCPUCoreCount() {
int cpuCoreCount = 1;
#if defined(_SC_NPROCESSORS_ONLN)
@@ -55,30 +57,26 @@
return cpuCoreCount;
}
-static const CodecProfileLevel kProfileLevels[] = {
- { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version0 },
- { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version1 },
- { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version2 },
- { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version3 },
-};
-
SoftVPXEncoder::SoftVPXEncoder(const char *name,
const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData,
- OMX_COMPONENTTYPE **component)
+ OMX_COMPONENTTYPE **component,
+ const char* role,
+ OMX_VIDEO_CODINGTYPE codingType,
+ const char* mimeType,
+ int32_t minCompressionRatio,
+ const CodecProfileLevel *profileLevels,
+ size_t numProfileLevels)
: SoftVideoEncoderOMXComponent(
- name, "video_encoder.vp8", OMX_VIDEO_CodingVP8,
- kProfileLevels, NELEM(kProfileLevels),
+ name, role, codingType, profileLevels, numProfileLevels,
176 /* width */, 144 /* height */,
callbacks, appData, component),
mCodecContext(NULL),
mCodecConfiguration(NULL),
mCodecInterface(NULL),
mBitrateUpdated(false),
- mBitrateControlMode(VPX_VBR), // variable bitrate
- mDCTPartitions(0),
+ mBitrateControlMode(VPX_VBR),
mErrorResilience(OMX_FALSE),
- mLevel(OMX_VIDEO_VP8Level_Version0),
mKeyFrameInterval(0),
mMinQuantizer(0),
mMaxQuantizer(0),
@@ -96,10 +94,9 @@
initPorts(
kNumBuffers, kNumBuffers, kMinOutputBufferSize,
- MEDIA_MIMETYPE_VIDEO_VP8, 2 /* minCompressionRatio */);
+ mimeType, minCompressionRatio);
}
-
SoftVPXEncoder::~SoftVPXEncoder() {
releaseEncoder();
}
@@ -108,18 +105,18 @@
vpx_codec_err_t codec_return;
status_t result = UNKNOWN_ERROR;
- mCodecInterface = vpx_codec_vp8_cx();
+ setCodecSpecificInterface();
if (mCodecInterface == NULL) {
goto CLEAN_UP;
}
- ALOGD("VP8: initEncoder. BRMode: %u. TSLayers: %zu. KF: %u. QP: %u - %u",
+ ALOGD("VPx: initEncoder. BRMode: %u. TSLayers: %zu. KF: %u. QP: %u - %u",
(uint32_t)mBitrateControlMode, mTemporalLayers, mKeyFrameInterval,
mMinQuantizer, mMaxQuantizer);
mCodecConfiguration = new vpx_codec_enc_cfg_t;
codec_return = vpx_codec_enc_config_default(mCodecInterface,
mCodecConfiguration,
- 0); // Codec specific flags
+ 0);
if (codec_return != VPX_CODEC_OK) {
ALOGE("Error populating default configuration for vpx encoder.");
@@ -131,27 +128,6 @@
mCodecConfiguration->g_threads = GetCPUCoreCount();
mCodecConfiguration->g_error_resilient = mErrorResilience;
- switch (mLevel) {
- case OMX_VIDEO_VP8Level_Version0:
- mCodecConfiguration->g_profile = 0;
- break;
-
- case OMX_VIDEO_VP8Level_Version1:
- mCodecConfiguration->g_profile = 1;
- break;
-
- case OMX_VIDEO_VP8Level_Version2:
- mCodecConfiguration->g_profile = 2;
- break;
-
- case OMX_VIDEO_VP8Level_Version3:
- mCodecConfiguration->g_profile = 3;
- break;
-
- default:
- mCodecConfiguration->g_profile = 0;
- }
-
// OMX timebase unit is microsecond
// g_timebase is in seconds (i.e. 1/1000000 seconds)
mCodecConfiguration->g_timebase.num = 1;
@@ -253,7 +229,6 @@
goto CLEAN_UP;
}
}
-
// Set bitrate values for each layer
for (size_t i = 0; i < mCodecConfiguration->ts_number_layers; i++) {
mCodecConfiguration->ts_target_bitrate[i] =
@@ -271,7 +246,7 @@
if (mMaxQuantizer > 0) {
mCodecConfiguration->rc_max_quantizer = mMaxQuantizer;
}
-
+ setCodecSpecificConfiguration();
mCodecContext = new vpx_codec_ctx_t;
codec_return = vpx_codec_enc_init(mCodecContext,
mCodecInterface,
@@ -283,14 +258,6 @@
goto CLEAN_UP;
}
- codec_return = vpx_codec_control(mCodecContext,
- VP8E_SET_TOKEN_PARTITIONS,
- mDCTPartitions);
- if (codec_return != VPX_CODEC_OK) {
- ALOGE("Error setting dct partitions for vpx encoder.");
- goto CLEAN_UP;
- }
-
// Extra CBR settings
if (mBitrateControlMode == VPX_CBR) {
codec_return = vpx_codec_control(mCodecContext,
@@ -318,6 +285,13 @@
}
}
+ codec_return = setCodecSpecificControls();
+
+ if (codec_return != VPX_CODEC_OK) {
+ // The codec specific method would have logged the error.
+ goto CLEAN_UP;
+ }
+
if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) {
free(mConversionBuffer);
mConversionBuffer = NULL;
@@ -338,7 +312,6 @@
return result;
}
-
status_t SoftVPXEncoder::releaseEncoder() {
if (mCodecContext != NULL) {
vpx_codec_destroy(mCodecContext);
@@ -362,7 +335,6 @@
return OK;
}
-
OMX_ERRORTYPE SoftVPXEncoder::internalGetParameter(OMX_INDEXTYPE index,
OMX_PTR param) {
// can include extension index OMX_INDEXEXTTYPE
@@ -393,54 +365,15 @@
return OMX_ErrorNone;
}
- // VP8 specific parameters that use extension headers
- case OMX_IndexParamVideoVp8: {
- OMX_VIDEO_PARAM_VP8TYPE *vp8Params =
- (OMX_VIDEO_PARAM_VP8TYPE *)param;
-
- if (!isValidOMXParam(vp8Params)) {
- return OMX_ErrorBadParameter;
- }
-
- if (vp8Params->nPortIndex != kOutputPortIndex) {
- return OMX_ErrorUnsupportedIndex;
- }
-
- vp8Params->eProfile = OMX_VIDEO_VP8ProfileMain;
- vp8Params->eLevel = mLevel;
- vp8Params->nDCTPartitions = mDCTPartitions;
- vp8Params->bErrorResilientMode = mErrorResilience;
- return OMX_ErrorNone;
- }
-
- case OMX_IndexParamVideoAndroidVp8Encoder: {
- OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vp8AndroidParams =
- (OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)param;
-
- if (!isValidOMXParam(vp8AndroidParams)) {
- return OMX_ErrorBadParameter;
- }
-
- if (vp8AndroidParams->nPortIndex != kOutputPortIndex) {
- return OMX_ErrorUnsupportedIndex;
- }
-
- vp8AndroidParams->nKeyFrameInterval = mKeyFrameInterval;
- vp8AndroidParams->eTemporalPattern = mTemporalPatternType;
- vp8AndroidParams->nTemporalLayerCount = mTemporalLayers;
- vp8AndroidParams->nMinQuantizer = mMinQuantizer;
- vp8AndroidParams->nMaxQuantizer = mMaxQuantizer;
- memcpy(vp8AndroidParams->nTemporalLayerBitrateRatio,
- mTemporalLayerBitrateRatio, sizeof(mTemporalLayerBitrateRatio));
- return OMX_ErrorNone;
- }
+ case OMX_IndexParamVideoAndroidVp8Encoder:
+ return internalGetAndroidVpxParams(
+ (OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)param);
default:
return SoftVideoEncoderOMXComponent::internalGetParameter(index, param);
}
}
-
OMX_ERRORTYPE SoftVPXEncoder::internalSetParameter(OMX_INDEXTYPE index,
const OMX_PTR param) {
// can include extension index OMX_INDEXEXTTYPE
@@ -458,27 +391,9 @@
return internalSetBitrateParams(bitRate);
}
- case OMX_IndexParamVideoVp8: {
- const OMX_VIDEO_PARAM_VP8TYPE *vp8Params =
- (const OMX_VIDEO_PARAM_VP8TYPE*) param;
-
- if (!isValidOMXParam(vp8Params)) {
- return OMX_ErrorBadParameter;
- }
-
- return internalSetVp8Params(vp8Params);
- }
-
- case OMX_IndexParamVideoAndroidVp8Encoder: {
- const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vp8AndroidParams =
- (const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE*) param;
-
- if (!isValidOMXParam(vp8AndroidParams)) {
- return OMX_ErrorBadParameter;
- }
-
- return internalSetAndroidVp8Params(vp8AndroidParams);
- }
+ case OMX_IndexParamVideoAndroidVp8Encoder:
+ return internalSetAndroidVpxParams(
+ (const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)param);
default:
return SoftVideoEncoderOMXComponent::internalSetParameter(index, param);
@@ -530,77 +445,21 @@
}
}
-OMX_ERRORTYPE SoftVPXEncoder::internalSetVp8Params(
- const OMX_VIDEO_PARAM_VP8TYPE* vp8Params) {
- if (vp8Params->nPortIndex != kOutputPortIndex) {
+OMX_ERRORTYPE SoftVPXEncoder::internalGetBitrateParams(
+ OMX_VIDEO_PARAM_BITRATETYPE* bitrate) {
+ if (bitrate->nPortIndex != kOutputPortIndex) {
return OMX_ErrorUnsupportedIndex;
}
- if (vp8Params->eProfile != OMX_VIDEO_VP8ProfileMain) {
- return OMX_ErrorBadParameter;
- }
+ bitrate->nTargetBitrate = mBitrate;
- if (vp8Params->eLevel == OMX_VIDEO_VP8Level_Version0 ||
- vp8Params->eLevel == OMX_VIDEO_VP8Level_Version1 ||
- vp8Params->eLevel == OMX_VIDEO_VP8Level_Version2 ||
- vp8Params->eLevel == OMX_VIDEO_VP8Level_Version3) {
- mLevel = vp8Params->eLevel;
+ if (mBitrateControlMode == VPX_VBR) {
+ bitrate->eControlRate = OMX_Video_ControlRateVariable;
+ } else if (mBitrateControlMode == VPX_CBR) {
+ bitrate->eControlRate = OMX_Video_ControlRateConstant;
} else {
- return OMX_ErrorBadParameter;
+ return OMX_ErrorUnsupportedSetting;
}
-
- if (vp8Params->nDCTPartitions <= kMaxDCTPartitions) {
- mDCTPartitions = vp8Params->nDCTPartitions;
- } else {
- return OMX_ErrorBadParameter;
- }
-
- mErrorResilience = vp8Params->bErrorResilientMode;
- return OMX_ErrorNone;
-}
-
-OMX_ERRORTYPE SoftVPXEncoder::internalSetAndroidVp8Params(
- const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE* vp8AndroidParams) {
- if (vp8AndroidParams->nPortIndex != kOutputPortIndex) {
- return OMX_ErrorUnsupportedIndex;
- }
- if (vp8AndroidParams->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternNone &&
- vp8AndroidParams->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
- return OMX_ErrorBadParameter;
- }
- if (vp8AndroidParams->nTemporalLayerCount > OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS) {
- return OMX_ErrorBadParameter;
- }
- if (vp8AndroidParams->nMinQuantizer > vp8AndroidParams->nMaxQuantizer) {
- return OMX_ErrorBadParameter;
- }
-
- mTemporalPatternType = vp8AndroidParams->eTemporalPattern;
- if (vp8AndroidParams->eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
- mTemporalLayers = vp8AndroidParams->nTemporalLayerCount;
- } else if (vp8AndroidParams->eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternNone) {
- mTemporalLayers = 0;
- }
- // Check the bitrate distribution between layers is in increasing order
- if (mTemporalLayers > 1) {
- for (size_t i = 0; i < mTemporalLayers - 1; i++) {
- if (vp8AndroidParams->nTemporalLayerBitrateRatio[i + 1] <=
- vp8AndroidParams->nTemporalLayerBitrateRatio[i]) {
- ALOGE("Wrong bitrate ratio - should be in increasing order.");
- return OMX_ErrorBadParameter;
- }
- }
- }
- mKeyFrameInterval = vp8AndroidParams->nKeyFrameInterval;
- mMinQuantizer = vp8AndroidParams->nMinQuantizer;
- mMaxQuantizer = vp8AndroidParams->nMaxQuantizer;
- memcpy(mTemporalLayerBitrateRatio, vp8AndroidParams->nTemporalLayerBitrateRatio,
- sizeof(mTemporalLayerBitrateRatio));
- ALOGD("VP8: internalSetAndroidVp8Params. BRMode: %u. TS: %zu. KF: %u."
- " QP: %u - %u BR0: %u. BR1: %u. BR2: %u",
- (uint32_t)mBitrateControlMode, mTemporalLayers, mKeyFrameInterval,
- mMinQuantizer, mMaxQuantizer, mTemporalLayerBitrateRatio[0],
- mTemporalLayerBitrateRatio[1], mTemporalLayerBitrateRatio[2]);
return OMX_ErrorNone;
}
@@ -623,71 +482,134 @@
return OMX_ErrorNone;
}
+OMX_ERRORTYPE SoftVPXEncoder::internalGetAndroidVpxParams(
+ OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vpxAndroidParams) {
+ if (vpxAndroidParams->nPortIndex != kOutputPortIndex) {
+ return OMX_ErrorUnsupportedIndex;
+ }
+
+ vpxAndroidParams->nKeyFrameInterval = mKeyFrameInterval;
+ vpxAndroidParams->eTemporalPattern = mTemporalPatternType;
+ vpxAndroidParams->nTemporalLayerCount = mTemporalLayers;
+ vpxAndroidParams->nMinQuantizer = mMinQuantizer;
+ vpxAndroidParams->nMaxQuantizer = mMaxQuantizer;
+ memcpy(vpxAndroidParams->nTemporalLayerBitrateRatio,
+ mTemporalLayerBitrateRatio, sizeof(mTemporalLayerBitrateRatio));
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftVPXEncoder::internalSetAndroidVpxParams(
+ const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vpxAndroidParams) {
+ if (vpxAndroidParams->nPortIndex != kOutputPortIndex) {
+ return OMX_ErrorUnsupportedIndex;
+ }
+ if (vpxAndroidParams->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternNone &&
+ vpxAndroidParams->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
+ return OMX_ErrorBadParameter;
+ }
+ if (vpxAndroidParams->nTemporalLayerCount > OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS) {
+ return OMX_ErrorBadParameter;
+ }
+ if (vpxAndroidParams->nMinQuantizer > vpxAndroidParams->nMaxQuantizer) {
+ return OMX_ErrorBadParameter;
+ }
+
+ mTemporalPatternType = vpxAndroidParams->eTemporalPattern;
+ if (vpxAndroidParams->eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
+ mTemporalLayers = vpxAndroidParams->nTemporalLayerCount;
+ } else if (vpxAndroidParams->eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternNone) {
+ mTemporalLayers = 0;
+ }
+ // Check the bitrate distribution between layers is in increasing order
+ if (mTemporalLayers > 1) {
+ for (size_t i = 0; i < mTemporalLayers - 1; i++) {
+ if (vpxAndroidParams->nTemporalLayerBitrateRatio[i + 1] <=
+ vpxAndroidParams->nTemporalLayerBitrateRatio[i]) {
+ ALOGE("Wrong bitrate ratio - should be in increasing order.");
+ return OMX_ErrorBadParameter;
+ }
+ }
+ }
+ mKeyFrameInterval = vpxAndroidParams->nKeyFrameInterval;
+ mMinQuantizer = vpxAndroidParams->nMinQuantizer;
+ mMaxQuantizer = vpxAndroidParams->nMaxQuantizer;
+ memcpy(mTemporalLayerBitrateRatio, vpxAndroidParams->nTemporalLayerBitrateRatio,
+ sizeof(mTemporalLayerBitrateRatio));
+ ALOGD("VPx: internalSetAndroidVpxParams. BRMode: %u. TS: %zu. KF: %u."
+ " QP: %u - %u BR0: %u. BR1: %u. BR2: %u",
+ (uint32_t)mBitrateControlMode, mTemporalLayers, mKeyFrameInterval,
+ mMinQuantizer, mMaxQuantizer, mTemporalLayerBitrateRatio[0],
+ mTemporalLayerBitrateRatio[1], mTemporalLayerBitrateRatio[2]);
+ return OMX_ErrorNone;
+}
+
vpx_enc_frame_flags_t SoftVPXEncoder::getEncodeFlags() {
vpx_enc_frame_flags_t flags = 0;
- int patternIdx = mTemporalPatternIdx % mTemporalPatternLength;
- mTemporalPatternIdx++;
- switch (mTemporalPattern[patternIdx]) {
- case kTemporalUpdateLast:
- flags |= VP8_EFLAG_NO_UPD_GF;
- flags |= VP8_EFLAG_NO_UPD_ARF;
- flags |= VP8_EFLAG_NO_REF_GF;
- flags |= VP8_EFLAG_NO_REF_ARF;
- break;
- case kTemporalUpdateGoldenWithoutDependency:
- flags |= VP8_EFLAG_NO_REF_GF;
- // Deliberately no break here.
- case kTemporalUpdateGolden:
- flags |= VP8_EFLAG_NO_REF_ARF;
- flags |= VP8_EFLAG_NO_UPD_ARF;
- flags |= VP8_EFLAG_NO_UPD_LAST;
- break;
- case kTemporalUpdateAltrefWithoutDependency:
- flags |= VP8_EFLAG_NO_REF_ARF;
- flags |= VP8_EFLAG_NO_REF_GF;
- // Deliberately no break here.
- case kTemporalUpdateAltref:
- flags |= VP8_EFLAG_NO_UPD_GF;
- flags |= VP8_EFLAG_NO_UPD_LAST;
- break;
- case kTemporalUpdateNoneNoRefAltref:
- flags |= VP8_EFLAG_NO_REF_ARF;
- // Deliberately no break here.
- case kTemporalUpdateNone:
- flags |= VP8_EFLAG_NO_UPD_GF;
- flags |= VP8_EFLAG_NO_UPD_ARF;
- flags |= VP8_EFLAG_NO_UPD_LAST;
- flags |= VP8_EFLAG_NO_UPD_ENTROPY;
- break;
- case kTemporalUpdateNoneNoRefGoldenRefAltRef:
- flags |= VP8_EFLAG_NO_REF_GF;
- flags |= VP8_EFLAG_NO_UPD_GF;
- flags |= VP8_EFLAG_NO_UPD_ARF;
- flags |= VP8_EFLAG_NO_UPD_LAST;
- flags |= VP8_EFLAG_NO_UPD_ENTROPY;
- break;
- case kTemporalUpdateGoldenWithoutDependencyRefAltRef:
- flags |= VP8_EFLAG_NO_REF_GF;
- flags |= VP8_EFLAG_NO_UPD_ARF;
- flags |= VP8_EFLAG_NO_UPD_LAST;
- break;
- case kTemporalUpdateLastRefAltRef:
- flags |= VP8_EFLAG_NO_UPD_GF;
- flags |= VP8_EFLAG_NO_UPD_ARF;
- flags |= VP8_EFLAG_NO_REF_GF;
- break;
- case kTemporalUpdateGoldenRefAltRef:
- flags |= VP8_EFLAG_NO_UPD_ARF;
- flags |= VP8_EFLAG_NO_UPD_LAST;
- break;
- case kTemporalUpdateLastAndGoldenRefAltRef:
- flags |= VP8_EFLAG_NO_UPD_ARF;
- flags |= VP8_EFLAG_NO_REF_GF;
- break;
- case kTemporalUpdateLastRefAll:
- flags |= VP8_EFLAG_NO_UPD_ARF;
- flags |= VP8_EFLAG_NO_UPD_GF;
- break;
+ if (mTemporalPatternLength > 0) {
+ int patternIdx = mTemporalPatternIdx % mTemporalPatternLength;
+ mTemporalPatternIdx++;
+ switch (mTemporalPattern[patternIdx]) {
+ case kTemporalUpdateLast:
+ flags |= VP8_EFLAG_NO_UPD_GF;
+ flags |= VP8_EFLAG_NO_UPD_ARF;
+ flags |= VP8_EFLAG_NO_REF_GF;
+ flags |= VP8_EFLAG_NO_REF_ARF;
+ break;
+ case kTemporalUpdateGoldenWithoutDependency:
+ flags |= VP8_EFLAG_NO_REF_GF;
+ // Deliberately no break here.
+ case kTemporalUpdateGolden:
+ flags |= VP8_EFLAG_NO_REF_ARF;
+ flags |= VP8_EFLAG_NO_UPD_ARF;
+ flags |= VP8_EFLAG_NO_UPD_LAST;
+ break;
+ case kTemporalUpdateAltrefWithoutDependency:
+ flags |= VP8_EFLAG_NO_REF_ARF;
+ flags |= VP8_EFLAG_NO_REF_GF;
+ // Deliberately no break here.
+ case kTemporalUpdateAltref:
+ flags |= VP8_EFLAG_NO_UPD_GF;
+ flags |= VP8_EFLAG_NO_UPD_LAST;
+ break;
+ case kTemporalUpdateNoneNoRefAltref:
+ flags |= VP8_EFLAG_NO_REF_ARF;
+ // Deliberately no break here.
+ case kTemporalUpdateNone:
+ flags |= VP8_EFLAG_NO_UPD_GF;
+ flags |= VP8_EFLAG_NO_UPD_ARF;
+ flags |= VP8_EFLAG_NO_UPD_LAST;
+ flags |= VP8_EFLAG_NO_UPD_ENTROPY;
+ break;
+ case kTemporalUpdateNoneNoRefGoldenRefAltRef:
+ flags |= VP8_EFLAG_NO_REF_GF;
+ flags |= VP8_EFLAG_NO_UPD_GF;
+ flags |= VP8_EFLAG_NO_UPD_ARF;
+ flags |= VP8_EFLAG_NO_UPD_LAST;
+ flags |= VP8_EFLAG_NO_UPD_ENTROPY;
+ break;
+ case kTemporalUpdateGoldenWithoutDependencyRefAltRef:
+ flags |= VP8_EFLAG_NO_REF_GF;
+ flags |= VP8_EFLAG_NO_UPD_ARF;
+ flags |= VP8_EFLAG_NO_UPD_LAST;
+ break;
+ case kTemporalUpdateLastRefAltRef:
+ flags |= VP8_EFLAG_NO_UPD_GF;
+ flags |= VP8_EFLAG_NO_UPD_ARF;
+ flags |= VP8_EFLAG_NO_REF_GF;
+ break;
+ case kTemporalUpdateGoldenRefAltRef:
+ flags |= VP8_EFLAG_NO_UPD_ARF;
+ flags |= VP8_EFLAG_NO_UPD_LAST;
+ break;
+ case kTemporalUpdateLastAndGoldenRefAltRef:
+ flags |= VP8_EFLAG_NO_UPD_ARF;
+ flags |= VP8_EFLAG_NO_REF_GF;
+ break;
+ case kTemporalUpdateLastRefAll:
+ flags |= VP8_EFLAG_NO_UPD_ARF;
+ flags |= VP8_EFLAG_NO_UPD_GF;
+ break;
+ }
}
return flags;
}
@@ -765,10 +687,7 @@
vpx_img_wrap(&raw_frame, VPX_IMG_FMT_I420, mWidth, mHeight,
kInputBufferAlignment, (uint8_t *)source);
- vpx_enc_frame_flags_t flags = 0;
- if (mTemporalPatternLength > 0) {
- flags = getEncodeFlags();
- }
+ vpx_enc_frame_flags_t flags = getEncodeFlags();
if (mKeyFrameRequested) {
flags |= VPX_EFLAG_FORCE_KF;
mKeyFrameRequested = false;
@@ -779,7 +698,7 @@
vpx_codec_err_t res = vpx_codec_enc_config_set(mCodecContext,
mCodecConfiguration);
if (res != VPX_CODEC_OK) {
- ALOGE("vp8 encoder failed to update bitrate: %s",
+ ALOGE("vpx encoder failed to update bitrate: %s",
vpx_codec_err_to_string(res));
notify(OMX_EventError,
OMX_ErrorUndefined,
@@ -849,9 +768,15 @@
} // namespace android
-
android::SoftOMXComponent *createSoftOMXComponent(
const char *name, const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData, OMX_COMPONENTTYPE **component) {
- return new android::SoftVPXEncoder(name, callbacks, appData, component);
+ if (!strcmp(name, "OMX.google.vp8.encoder")) {
+ return new android::SoftVP8Encoder(name, callbacks, appData, component);
+ } else if (!strcmp(name, "OMX.google.vp9.encoder")) {
+ return new android::SoftVP9Encoder(name, callbacks, appData, component);
+ } else {
+ CHECK(!"Unknown component");
+ }
+ return NULL;
}
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
index cd0a0cf..86e71da 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
@@ -31,18 +31,18 @@
namespace android {
-// Exposes a vpx encoder as an OMX Component
+// Base class for a VPX Encoder OMX Component
//
// Boilerplate for callback bindings are taken care
// by the base class SimpleSoftOMXComponent and its
// parent SoftOMXComponent.
//
-// Only following encoder settings are available
+// Only following encoder settings are available (codec specific settings might
+// be available in the sub-classes):
// - target bitrate
// - rate control (constant / variable)
// - frame rate
// - error resilience
-// - token partitioning
// - reconstruction & loop filters (g_profile)
//
// Only following color formats are recognized
@@ -54,7 +54,7 @@
// - encoding deadline is realtime
// - multithreaded encoding utilizes a number of threads equal
// to online cpu's available
-// - the algorithm interface for encoder is vp8
+// - the algorithm interface for encoder is decided by the sub-class in use
// - fractional bits of frame rate is discarded
// - OMX timestamps are in microseconds, therefore
// encoder timebase is fixed to 1/1000000
@@ -63,7 +63,13 @@
SoftVPXEncoder(const char *name,
const OMX_CALLBACKTYPE *callbacks,
OMX_PTR appData,
- OMX_COMPONENTTYPE **component);
+ OMX_COMPONENTTYPE **component,
+ const char* role,
+ OMX_VIDEO_CODINGTYPE codingType,
+ const char* mimeType,
+ int32_t minCompressionRatio,
+ const CodecProfileLevel *profileLevels,
+ size_t numProfileLevels);
protected:
virtual ~SoftVPXEncoder();
@@ -87,7 +93,44 @@
// encoding of the frame
virtual void onQueueFilled(OMX_U32 portIndex);
-private:
+ // Initializes vpx encoder with available settings.
+ status_t initEncoder();
+
+ // Populates mCodecInterface with codec specific settings.
+ virtual void setCodecSpecificInterface() = 0;
+
+ // Sets codec specific configuration.
+ virtual void setCodecSpecificConfiguration() = 0;
+
+ // Sets codec specific encoder controls.
+ virtual vpx_codec_err_t setCodecSpecificControls() = 0;
+
+ // Get current encode flags.
+ virtual vpx_enc_frame_flags_t getEncodeFlags();
+
+ // Releases vpx encoder instance, with it's associated
+ // data structures.
+ //
+ // Unless called earlier, this is handled by the
+ // dtor.
+ status_t releaseEncoder();
+
+ // Get bitrate parameters.
+ virtual OMX_ERRORTYPE internalGetBitrateParams(
+ OMX_VIDEO_PARAM_BITRATETYPE* bitrate);
+
+ // Updates bitrate to reflect port settings.
+ virtual OMX_ERRORTYPE internalSetBitrateParams(
+ const OMX_VIDEO_PARAM_BITRATETYPE* bitrate);
+
+ // Gets Android vpx specific parameters.
+ OMX_ERRORTYPE internalGetAndroidVpxParams(
+ OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vpxAndroidParams);
+
+ // Handles Android vpx specific parameters.
+ OMX_ERRORTYPE internalSetAndroidVpxParams(
+ const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vpxAndroidParams);
+
enum TemporalReferences {
// For 1 layer case: reference all (last, golden, and alt ref), but only
// update last.
@@ -137,9 +180,6 @@
static const uint32_t kInputBufferAlignment = 1;
static const uint32_t kOutputBufferAlignment = 2;
- // Max value supported for DCT partitions
- static const uint32_t kMaxDCTPartitions = 3;
-
// Number of supported input color formats
static const uint32_t kNumberOfSupportedColorFormats = 3;
@@ -161,23 +201,10 @@
// Bitrate control mode, either constant or variable
vpx_rc_mode mBitrateControlMode;
- // vp8 specific configuration parameter
- // that enables token partitioning of
- // the stream into substreams
- int32_t mDCTPartitions;
-
// Parameter that denotes whether error resilience
// is enabled in encoder
OMX_BOOL mErrorResilience;
- // Encoder profile corresponding to OMX level parameter
- //
- // The inconsistency in the naming is caused by
- // OMX spec referring vpx profiles (g_profile)
- // as "levels" whereas using the name "profile" for
- // something else.
- OMX_VIDEO_VP8LEVELTYPE mLevel;
-
// Key frame interval in frames
uint32_t mKeyFrameInterval;
@@ -216,31 +243,6 @@
bool mKeyFrameRequested;
- // Initializes vpx encoder with available settings.
- status_t initEncoder();
-
- // Releases vpx encoder instance, with it's associated
- // data structures.
- //
- // Unless called earlier, this is handled by the
- // dtor.
- status_t releaseEncoder();
-
- // Get current encode flags
- vpx_enc_frame_flags_t getEncodeFlags();
-
- // Updates bitrate to reflect port settings.
- OMX_ERRORTYPE internalSetBitrateParams(
- const OMX_VIDEO_PARAM_BITRATETYPE* bitrate);
-
- // Handles vp8 specific parameters.
- OMX_ERRORTYPE internalSetVp8Params(
- const OMX_VIDEO_PARAM_VP8TYPE* vp8Params);
-
- // Handles Android vp8 specific parameters.
- OMX_ERRORTYPE internalSetAndroidVp8Params(
- const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE* vp8AndroidParams);
-
DISALLOW_EVIL_CONSTRUCTORS(SoftVPXEncoder);
};
diff --git a/media/libstagefright/codecs/on2/h264dec/Android.mk b/media/libstagefright/codecs/on2/h264dec/Android.mk
index 7159674..f28e17b 100644
--- a/media/libstagefright/codecs/on2/h264dec/Android.mk
+++ b/media/libstagefright/codecs/on2/h264dec/Android.mk
@@ -95,11 +95,10 @@
$(LOCAL_PATH)/./omxdl/arm_neon/vc/m4p10/api
endif
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
LOCAL_SHARED_LIBRARIES := \
- libstagefright libstagefright_omx libstagefright_foundation libutils liblog \
+ libmedia libstagefright_omx libstagefright_foundation libutils liblog \
LOCAL_MODULE := libstagefright_soft_h264dec
diff --git a/media/libstagefright/codecs/opus/dec/Android.mk b/media/libstagefright/codecs/opus/dec/Android.mk
index f272763..7b0ad2c 100644
--- a/media/libstagefright/codecs/opus/dec/Android.mk
+++ b/media/libstagefright/codecs/opus/dec/Android.mk
@@ -10,10 +10,9 @@
frameworks/native/include/media/openmax \
LOCAL_SHARED_LIBRARIES := \
- libopus libstagefright libstagefright_omx \
+ libopus libmedia libstagefright_omx \
libstagefright_foundation libutils liblog
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow unsigned-integer-overflow
LOCAL_MODULE := libstagefright_soft_opusdec
diff --git a/media/libstagefright/codecs/raw/Android.mk b/media/libstagefright/codecs/raw/Android.mk
index e454c84..caed2cc 100644
--- a/media/libstagefright/codecs/raw/Android.mk
+++ b/media/libstagefright/codecs/raw/Android.mk
@@ -9,7 +9,6 @@
frameworks/native/include/media/openmax
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow unsigned-integer-overflow
LOCAL_SHARED_LIBRARIES := \
diff --git a/media/libstagefright/codecs/vorbis/dec/Android.mk b/media/libstagefright/codecs/vorbis/dec/Android.mk
index 039be6f..3d72d3a 100644
--- a/media/libstagefright/codecs/vorbis/dec/Android.mk
+++ b/media/libstagefright/codecs/vorbis/dec/Android.mk
@@ -10,14 +10,13 @@
frameworks/native/include/media/openmax \
LOCAL_SHARED_LIBRARIES := \
- libvorbisidec libstagefright libstagefright_omx \
+ libvorbisidec libmedia libstagefright_omx \
libstagefright_foundation libutils liblog
LOCAL_MODULE := libstagefright_soft_vorbisdec
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow unsigned-integer-overflow
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/colorconversion/Android.mk b/media/libstagefright/colorconversion/Android.mk
index 0bf9701..ba74740 100644
--- a/media/libstagefright/colorconversion/Android.mk
+++ b/media/libstagefright/colorconversion/Android.mk
@@ -14,7 +14,6 @@
libyuv_static \
LOCAL_CFLAGS += -Werror
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
LOCAL_MODULE:= libstagefright_color_conversion
diff --git a/media/libstagefright/data/media_codecs_google_video.xml b/media/libstagefright/data/media_codecs_google_video.xml
index b03c769..ce164a2 100644
--- a/media/libstagefright/data/media_codecs_google_video.xml
+++ b/media/libstagefright/data/media_codecs_google_video.xml
@@ -101,5 +101,12 @@
<Limit name="bitrate" range="1-40000000" />
<Feature name="bitrate-modes" value="VBR,CBR" />
</MediaCodec>
+ <MediaCodec name="OMX.google.vp9.encoder" type="video/x-vnd.on2.vp9">
+ <!-- profiles and levels: ProfileMain : Level_Version0-3 -->
+ <Limit name="size" min="2x2" max="2048x2048" />
+ <Limit name="alignment" value="2x2" />
+ <Limit name="bitrate" range="1-40000000" />
+ <Feature name="bitrate-modes" value="VBR,CBR" />
+ </MediaCodec>
</Encoders>
</Included>
diff --git a/media/libstagefright/filters/Android.mk b/media/libstagefright/filters/Android.mk
index bd75a88..f8e8352 100644
--- a/media/libstagefright/filters/Android.mk
+++ b/media/libstagefright/filters/Android.mk
@@ -21,7 +21,6 @@
LOCAL_C_INCLUDES += $(intermediates)
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
-LOCAL_CLANG := true
LOCAL_SHARED_LIBRARIES := libmedia
diff --git a/media/libstagefright/filters/IntrinsicBlurFilter.cpp b/media/libstagefright/filters/IntrinsicBlurFilter.cpp
index cbcf699..e00afd9 100644
--- a/media/libstagefright/filters/IntrinsicBlurFilter.cpp
+++ b/media/libstagefright/filters/IntrinsicBlurFilter.cpp
@@ -19,7 +19,7 @@
#include <utils/Log.h>
-#include <media/stagefright/foundation/ABuffer.h>
+#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -88,7 +88,7 @@
}
status_t IntrinsicBlurFilter::processBuffers(
- const sp<ABuffer> &srcBuffer, const sp<ABuffer> &outBuffer) {
+ const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
mAllocIn->copy1DRangeFrom(0, mWidth * mHeight, srcBuffer->data());
mBlur->forEach(mAllocOut);
mAllocOut->copy1DRangeTo(0, mWidth * mHeight, outBuffer->data());
diff --git a/media/libstagefright/filters/IntrinsicBlurFilter.h b/media/libstagefright/filters/IntrinsicBlurFilter.h
index 4707ab7..a2aabfa 100644
--- a/media/libstagefright/filters/IntrinsicBlurFilter.h
+++ b/media/libstagefright/filters/IntrinsicBlurFilter.h
@@ -31,7 +31,7 @@
virtual void reset();
virtual status_t setParameters(const sp<AMessage> &msg);
virtual status_t processBuffers(
- const sp<ABuffer> &srcBuffer, const sp<ABuffer> &outBuffer);
+ const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
protected:
virtual ~IntrinsicBlurFilter() {};
diff --git a/media/libstagefright/filters/MediaFilter.cpp b/media/libstagefright/filters/MediaFilter.cpp
index cd69418..f26c840 100644
--- a/media/libstagefright/filters/MediaFilter.cpp
+++ b/media/libstagefright/filters/MediaFilter.cpp
@@ -31,6 +31,8 @@
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MediaFilter.h>
+#include <media/MediaCodecBuffer.h>
+
#include <gui/BufferItem.h>
#include "ColorConvert.h"
@@ -40,6 +42,8 @@
#include "SaturationFilter.h"
#include "ZeroFilter.h"
+#include "../include/SharedMemoryBuffer.h"
+
namespace android {
// parameter: number of input and output buffers
@@ -195,7 +199,7 @@
}
void MediaFilter::PortDescription::addBuffer(
- IOMX::buffer_id id, const sp<ABuffer> &buffer) {
+ IOMX::buffer_id id, const sp<MediaCodecBuffer> &buffer) {
mBufferIDs.push_back(id);
mBuffers.push_back(buffer);
}
@@ -208,7 +212,7 @@
return mBufferIDs.itemAt(index);
}
-sp<ABuffer> MediaFilter::PortDescription::bufferAt(size_t index) const {
+sp<MediaCodecBuffer> MediaFilter::PortDescription::bufferAt(size_t index) const {
return mBuffers.itemAt(index);
}
@@ -250,7 +254,8 @@
info.mBufferID = i;
info.mGeneration = mGeneration;
info.mOutputFlags = 0;
- info.mData = new ABuffer(mem->pointer(), bufferSize);
+ info.mData = new SharedMemoryBuffer(
+ isInput ? mInputFormat : mOutputFormat, mem);
info.mData->meta()->setInt64("timeUs", 0);
mBuffers[portIndex].push_back(info);
@@ -314,7 +319,7 @@
notify->setInt32("buffer-id", info->mBufferID);
info->mData->meta()->clear();
- notify->setBuffer("buffer", info->mData);
+ notify->setObject("buffer", info->mData);
sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, this);
reply->setInt32("buffer-id", info->mBufferID);
@@ -334,7 +339,7 @@
notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
notify->setInt32("buffer-id", info->mBufferID);
notify->setInt32("flags", info->mOutputFlags);
- notify->setBuffer("buffer", info->mData);
+ notify->setObject("buffer", info->mData);
sp<AMessage> reply = new AMessage(kWhatOutputBufferDrained, this);
reply->setInt32("buffer-id", info->mBufferID);
@@ -597,11 +602,12 @@
CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_UPSTREAM);
info->mStatus = BufferInfo::OWNED_BY_US;
- sp<ABuffer> buffer;
+ sp<MediaCodecBuffer> buffer;
int32_t err = OK;
bool eos = false;
- if (!msg->findBuffer("buffer", &buffer)) {
+ sp<RefBase> obj;
+ if (!msg->findObject("buffer", &obj)) {
// these are unfilled buffers returned by client
CHECK(msg->findInt32("err", &err));
@@ -616,6 +622,8 @@
}
buffer.clear();
+ } else {
+ buffer = static_cast<MediaCodecBuffer *>(obj.get());
}
int32_t isCSD;
@@ -768,7 +776,8 @@
// TODO: check input format and convert only if necessary
// copy RGBA graphic buffer into temporary ARGB input buffer
BufferInfo *inputInfo = new BufferInfo;
- inputInfo->mData = new ABuffer(buf->getWidth() * buf->getHeight() * 4);
+ inputInfo->mData = new MediaCodecBuffer(
+ mInputFormat, new ABuffer(buf->getWidth() * buf->getHeight() * 4));
ALOGV("Copying surface data into temp buffer.");
convertRGBAToARGB(
(uint8_t*)bufPtr, buf->getWidth(), buf->getHeight(),
diff --git a/media/libstagefright/filters/RSFilter.cpp b/media/libstagefright/filters/RSFilter.cpp
index b569945..225a375 100644
--- a/media/libstagefright/filters/RSFilter.cpp
+++ b/media/libstagefright/filters/RSFilter.cpp
@@ -19,7 +19,7 @@
#include <utils/Log.h>
-#include <media/stagefright/foundation/ABuffer.h>
+#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -85,7 +85,7 @@
}
status_t RSFilter::processBuffers(
- const sp<ABuffer> &srcBuffer, const sp<ABuffer> &outBuffer) {
+ const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
mAllocIn->copy1DRangeFrom(0, mWidth * mHeight, srcBuffer->data());
mCallback->processBuffers(mAllocIn.get(), mAllocOut.get());
mAllocOut->copy1DRangeTo(0, mWidth * mHeight, outBuffer->data());
diff --git a/media/libstagefright/filters/RSFilter.h b/media/libstagefright/filters/RSFilter.h
index c5b5074..3326284 100644
--- a/media/libstagefright/filters/RSFilter.h
+++ b/media/libstagefright/filters/RSFilter.h
@@ -35,7 +35,7 @@
virtual void reset();
virtual status_t setParameters(const sp<AMessage> &msg);
virtual status_t processBuffers(
- const sp<ABuffer> &srcBuffer, const sp<ABuffer> &outBuffer);
+ const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
protected:
virtual ~RSFilter();
diff --git a/media/libstagefright/filters/SaturationFilter.cpp b/media/libstagefright/filters/SaturationFilter.cpp
index ba5f75a..0a1df05 100644
--- a/media/libstagefright/filters/SaturationFilter.cpp
+++ b/media/libstagefright/filters/SaturationFilter.cpp
@@ -19,7 +19,7 @@
#include <utils/Log.h>
-#include <media/stagefright/foundation/ABuffer.h>
+#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -88,7 +88,7 @@
}
status_t SaturationFilter::processBuffers(
- const sp<ABuffer> &srcBuffer, const sp<ABuffer> &outBuffer) {
+ const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
mAllocIn->copy1DRangeFrom(0, mWidth * mHeight, srcBuffer->data());
mScript->forEach_root(mAllocIn, mAllocOut);
mAllocOut->copy1DRangeTo(0, mWidth * mHeight, outBuffer->data());
diff --git a/media/libstagefright/filters/SaturationFilter.h b/media/libstagefright/filters/SaturationFilter.h
index 0545021..317e469 100644
--- a/media/libstagefright/filters/SaturationFilter.h
+++ b/media/libstagefright/filters/SaturationFilter.h
@@ -33,7 +33,7 @@
virtual void reset();
virtual status_t setParameters(const sp<AMessage> &msg);
virtual status_t processBuffers(
- const sp<ABuffer> &srcBuffer, const sp<ABuffer> &outBuffer);
+ const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
protected:
virtual ~SaturationFilter() {};
diff --git a/media/libstagefright/filters/SimpleFilter.h b/media/libstagefright/filters/SimpleFilter.h
index 4cd37ef..a3c2d76 100644
--- a/media/libstagefright/filters/SimpleFilter.h
+++ b/media/libstagefright/filters/SimpleFilter.h
@@ -21,11 +21,11 @@
#include <utils/Errors.h>
#include <utils/RefBase.h>
-struct ABuffer;
-struct AMessage;
-
namespace android {
+struct AMessage;
+class MediaCodecBuffer;
+
struct SimpleFilter : public RefBase {
public:
SimpleFilter() : mWidth(0), mHeight(0), mStride(0), mSliceHeight(0),
@@ -37,7 +37,7 @@
virtual void reset() = 0;
virtual status_t setParameters(const sp<AMessage> &msg) = 0;
virtual status_t processBuffers(
- const sp<ABuffer> &srcBuffer, const sp<ABuffer> &outBuffer) = 0;
+ const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) = 0;
protected:
int32_t mWidth, mHeight;
diff --git a/media/libstagefright/filters/ZeroFilter.cpp b/media/libstagefright/filters/ZeroFilter.cpp
index 3f1243c..74b94b7 100644
--- a/media/libstagefright/filters/ZeroFilter.cpp
+++ b/media/libstagefright/filters/ZeroFilter.cpp
@@ -17,7 +17,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "ZeroFilter"
-#include <media/stagefright/foundation/ABuffer.h>
+#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -38,7 +38,7 @@
}
status_t ZeroFilter::processBuffers(
- const sp<ABuffer> &srcBuffer, const sp<ABuffer> &outBuffer) {
+ const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
// assuming identical input & output buffers, since we're a copy filter
if (mInvertData) {
uint32_t* src = (uint32_t*)srcBuffer->data();
diff --git a/media/libstagefright/filters/ZeroFilter.h b/media/libstagefright/filters/ZeroFilter.h
index bd34dfb..f941cc8 100644
--- a/media/libstagefright/filters/ZeroFilter.h
+++ b/media/libstagefright/filters/ZeroFilter.h
@@ -29,7 +29,7 @@
virtual void reset() {};
virtual status_t setParameters(const sp<AMessage> &msg);
virtual status_t processBuffers(
- const sp<ABuffer> &srcBuffer, const sp<ABuffer> &outBuffer);
+ const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
protected:
virtual ~ZeroFilter() {};
diff --git a/media/libstagefright/foundation/ALooperRoster.cpp b/media/libstagefright/foundation/ALooperRoster.cpp
index 5f11fb6..8a7c3eb 100644
--- a/media/libstagefright/foundation/ALooperRoster.cpp
+++ b/media/libstagefright/foundation/ALooperRoster.cpp
@@ -100,7 +100,7 @@
}
}
-static void makeFourCC(uint32_t fourcc, char *s) {
+static void makeFourCC(uint32_t fourcc, char *s, size_t bufsz) {
s[0] = (fourcc >> 24) & 0xff;
if (s[0]) {
s[1] = (fourcc >> 16) & 0xff;
@@ -108,7 +108,7 @@
s[3] = fourcc & 0xff;
s[4] = 0;
} else {
- sprintf(s, "%u", fourcc);
+ snprintf(s, bufsz, "%u", fourcc);
}
}
@@ -146,7 +146,7 @@
if (verboseStats) {
for (size_t j = 0; j < handler->mMessages.size(); j++) {
char fourcc[15];
- makeFourCC(handler->mMessages.keyAt(j), fourcc);
+ makeFourCC(handler->mMessages.keyAt(j), fourcc, sizeof(fourcc));
s.appendFormat("\n %s: %u",
fourcc,
handler->mMessages.valueAt(j));
diff --git a/media/libstagefright/foundation/AString.cpp b/media/libstagefright/foundation/AString.cpp
index b167543..04fac19 100644
--- a/media/libstagefright/foundation/AString.cpp
+++ b/media/libstagefright/foundation/AString.cpp
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+#define LOG_TAG "AString"
+#include <utils/Log.h>
+
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
@@ -40,14 +43,24 @@
: mData(NULL),
mSize(0),
mAllocSize(1) {
- setTo(s);
+ if (!s) {
+ ALOGW("ctor got NULL, using empty string instead");
+ clear();
+ } else {
+ setTo(s);
+ }
}
AString::AString(const char *s, size_t size)
: mData(NULL),
mSize(0),
mAllocSize(1) {
- setTo(s, size);
+ if (!s) {
+ ALOGW("ctor got NULL, using empty string instead");
+ clear();
+ } else {
+ setTo(s, size);
+ }
}
AString::AString(const String8 &from)
diff --git a/media/libstagefright/foundation/ColorUtils.cpp b/media/libstagefright/foundation/ColorUtils.cpp
index d7439b2..88a8351 100644
--- a/media/libstagefright/foundation/ColorUtils.cpp
+++ b/media/libstagefright/foundation/ColorUtils.cpp
@@ -343,6 +343,23 @@
}
// static
+ColorAspects ColorUtils::unpackToColorAspects(uint32_t packed) {
+ ColorAspects aspects;
+ aspects.mRange = (ColorAspects::Range)((packed >> 24) & 0xFF);
+ aspects.mPrimaries = (ColorAspects::Primaries)((packed >> 16) & 0xFF);
+ aspects.mMatrixCoeffs = (ColorAspects::MatrixCoeffs)((packed >> 8) & 0xFF);
+ aspects.mTransfer = (ColorAspects::Transfer)(packed & 0xFF);
+
+ return aspects;
+}
+
+// static
+uint32_t ColorUtils::packToU32(const ColorAspects &aspects) {
+ return (aspects.mRange << 24) | (aspects.mPrimaries << 16)
+ | (aspects.mMatrixCoeffs << 8) | aspects.mTransfer;
+}
+
+// static
void ColorUtils::setDefaultCodecColorAspectsIfNeeded(
ColorAspects &aspects, int32_t width, int32_t height) {
ColorAspects::MatrixCoeffs coeffs;
diff --git a/media/libstagefright/foundation/hexdump.cpp b/media/libstagefright/foundation/hexdump.cpp
index a44d832..872c5f3 100644
--- a/media/libstagefright/foundation/hexdump.cpp
+++ b/media/libstagefright/foundation/hexdump.cpp
@@ -49,7 +49,7 @@
appendIndent(&line, indent);
char tmp[32];
- sprintf(tmp, "%08lx: ", (unsigned long)offset);
+ snprintf(tmp, sizeof(tmp), "%08lx: ", (unsigned long)offset);
line.append(tmp);
@@ -60,7 +60,7 @@
if (offset + i >= size) {
line.append(" ");
} else {
- sprintf(tmp, "%02x ", data[offset + i]);
+ snprintf(tmp, sizeof(tmp), "%02x ", data[offset + i]);
line.append(tmp);
}
}
diff --git a/media/libstagefright/http/Android.mk b/media/libstagefright/http/Android.mk
index bc71134..b3ca6d5 100644
--- a/media/libstagefright/http/Android.mk
+++ b/media/libstagefright/http/Android.mk
@@ -22,7 +22,6 @@
LOCAL_CFLAGS += -Wno-multichar
LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/httplive/Android.mk b/media/libstagefright/httplive/Android.mk
index 2c985fc..6a71b7c 100644
--- a/media/libstagefright/httplive/Android.mk
+++ b/media/libstagefright/httplive/Android.mk
@@ -14,7 +14,6 @@
$(TOP)/frameworks/native/include/media/openmax
LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow
LOCAL_SHARED_LIBRARIES := \
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 7ad7fee..bbcea51 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -956,6 +956,38 @@
return false;
}
+void PlaylistFetcher::initSeqNumberForLiveStream(
+ int32_t &firstSeqNumberInPlaylist,
+ int32_t &lastSeqNumberInPlaylist) {
+ // start at least 3 target durations from the end.
+ int64_t timeFromEnd = 0;
+ size_t index = mPlaylist->size();
+ sp<AMessage> itemMeta;
+ int64_t itemDurationUs;
+ int32_t targetDuration;
+ if (mPlaylist->meta()->findInt32("target-duration", &targetDuration)) {
+ do {
+ --index;
+ if (!mPlaylist->itemAt(index, NULL /* uri */, &itemMeta)
+ || !itemMeta->findInt64("durationUs", &itemDurationUs)) {
+ ALOGW("item or itemDurationUs missing");
+ mSeqNumber = lastSeqNumberInPlaylist - 3;
+ break;
+ }
+
+ timeFromEnd += itemDurationUs;
+ mSeqNumber = firstSeqNumberInPlaylist + index;
+ } while (timeFromEnd < targetDuration * 3E6 && index > 0);
+ } else {
+ ALOGW("target-duration missing");
+ mSeqNumber = lastSeqNumberInPlaylist - 3;
+ }
+
+ if (mSeqNumber < firstSeqNumberInPlaylist) {
+ mSeqNumber = firstSeqNumberInPlaylist;
+ }
+}
+
bool PlaylistFetcher::initDownloadState(
AString &uri,
sp<AMessage> &itemMeta,
@@ -982,11 +1014,8 @@
if (mSegmentStartTimeUs < 0) {
if (!mPlaylist->isComplete() && !mPlaylist->isEvent()) {
- // If this is a live session, start 3 segments from the end on connect
- mSeqNumber = lastSeqNumberInPlaylist - 3;
- if (mSeqNumber < firstSeqNumberInPlaylist) {
- mSeqNumber = firstSeqNumberInPlaylist;
- }
+ // this is a live session
+ initSeqNumberForLiveStream(firstSeqNumberInPlaylist, lastSeqNumberInPlaylist);
} else {
// When seeking mSegmentStartTimeUs is unavailable (< 0), we
// use mStartTimeUs (client supplied timestamp) to determine both start segment
diff --git a/media/libstagefright/httplive/PlaylistFetcher.h b/media/libstagefright/httplive/PlaylistFetcher.h
index c8ca457..ee7d3a1 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.h
+++ b/media/libstagefright/httplive/PlaylistFetcher.h
@@ -218,6 +218,9 @@
void onStop(const sp<AMessage> &msg);
void onMonitorQueue();
void onDownloadNext();
+ void initSeqNumberForLiveStream(
+ int32_t &firstSeqNumberInPlaylist,
+ int32_t &lastSeqNumberInPlaylist);
bool initDownloadState(
AString &uri,
sp<AMessage> &itemMeta,
diff --git a/media/libstagefright/id3/Android.mk b/media/libstagefright/id3/Android.mk
index bd2e459..19ada73 100644
--- a/media/libstagefright/id3/Android.mk
+++ b/media/libstagefright/id3/Android.mk
@@ -5,7 +5,6 @@
ID3.cpp
LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow
LOCAL_SHARED_LIBRARIES := libmedia
@@ -22,7 +21,6 @@
testid3.cpp
LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
LOCAL_SHARED_LIBRARIES := \
libstagefright libutils liblog libbinder libstagefright_foundation
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index aaf6b3d..bffed52 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -517,7 +517,7 @@
if (mOffset == 126 || mOffset == 127) {
// Special treatment for the track number and genre.
char tmp[16];
- sprintf(tmp, "%d", (int)*frameData);
+ snprintf(tmp, sizeof(tmp), "%d", (int)*frameData);
id->setTo(tmp);
return;
diff --git a/media/libstagefright/include/DataConverter.h b/media/libstagefright/include/DataConverter.h
index 8d67921..60ebad1 100644
--- a/media/libstagefright/include/DataConverter.h
+++ b/media/libstagefright/include/DataConverter.h
@@ -24,18 +24,18 @@
namespace android {
-struct ABuffer;
+class MediaCodecBuffer;
// DataConverter base class, defaults to memcpy
struct DataConverter : public RefBase {
virtual size_t sourceSize(size_t targetSize); // will clamp to SIZE_MAX
virtual size_t targetSize(size_t sourceSize); // will clamp to SIZE_MAX
- status_t convert(const sp<ABuffer> &source, sp<ABuffer> &target);
+ status_t convert(const sp<MediaCodecBuffer> &source, sp<MediaCodecBuffer> &target);
virtual ~DataConverter();
protected:
- virtual status_t safeConvert(const sp<ABuffer> &source, sp<ABuffer> &target);
+ virtual status_t safeConvert(const sp<MediaCodecBuffer> &source, sp<MediaCodecBuffer> &target);
};
// SampleConverterBase uses a ratio to calculate the source and target sizes
@@ -45,7 +45,7 @@
virtual size_t targetSize(size_t sourceSize);
protected:
- virtual status_t safeConvert(const sp<ABuffer> &source, sp<ABuffer> &target) = 0;
+ virtual status_t safeConvert(const sp<MediaCodecBuffer> &source, sp<MediaCodecBuffer> &target) = 0;
// sourceSize = sourceSampleSize / targetSampleSize * targetSize
SampleConverterBase(uint32_t sourceSampleSize, uint32_t targetSampleSize)
@@ -61,7 +61,7 @@
static AudioConverter *Create(AudioEncoding source, AudioEncoding target);
protected:
- virtual status_t safeConvert(const sp<ABuffer> &src, sp<ABuffer> &tgt);
+ virtual status_t safeConvert(const sp<MediaCodecBuffer> &source, sp<MediaCodecBuffer> &target);
private:
AudioConverter(
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index 89ad137..fa05886 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -140,6 +140,9 @@
Track *findTrackByMimePrefix(const char *mimePrefix);
+ status_t parseAC3SampleEntry(off64_t offset);
+ status_t parseAC3SpecificBox(off64_t offset, uint16_t sampleRate);
+
MPEG4Extractor(const MPEG4Extractor &);
MPEG4Extractor &operator=(const MPEG4Extractor &);
};
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index 6c073f0..9edd0de 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -31,158 +31,28 @@
public:
OMX();
- virtual bool livesLocally(node_id node, pid_t pid);
-
virtual status_t listNodes(List<ComponentInfo> *list);
virtual status_t allocateNode(
const char *name, const sp<IOMXObserver> &observer,
- sp<IBinder> *nodeBinder,
- node_id *node);
-
- virtual status_t freeNode(node_id node);
-
- virtual status_t sendCommand(
- node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param);
-
- virtual status_t getParameter(
- node_id node, OMX_INDEXTYPE index,
- void *params, size_t size);
-
- virtual status_t setParameter(
- node_id node, OMX_INDEXTYPE index,
- const void *params, size_t size);
-
- virtual status_t getConfig(
- node_id node, OMX_INDEXTYPE index,
- void *params, size_t size);
-
- virtual status_t setConfig(
- node_id node, OMX_INDEXTYPE index,
- const void *params, size_t size);
-
- virtual status_t getState(
- node_id node, OMX_STATETYPE* state);
-
- virtual status_t enableNativeBuffers(
- node_id node, OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable);
-
- virtual status_t getGraphicBufferUsage(
- node_id node, OMX_U32 port_index, OMX_U32* usage);
-
- virtual status_t storeMetaDataInBuffers(
- node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type);
-
- virtual status_t prepareForAdaptivePlayback(
- node_id node, OMX_U32 portIndex, OMX_BOOL enable,
- OMX_U32 max_frame_width, OMX_U32 max_frame_height);
-
- virtual status_t configureVideoTunnelMode(
- node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
- OMX_U32 audioHwSync, native_handle_t **sidebandHandle);
-
- virtual status_t useBuffer(
- node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
- buffer_id *buffer, OMX_U32 allottedSize);
-
- virtual status_t useGraphicBuffer(
- node_id node, OMX_U32 port_index,
- const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer);
-
- virtual status_t updateGraphicBufferInMeta(
- node_id node, OMX_U32 port_index,
- const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer);
-
- virtual status_t updateNativeHandleInMeta(
- node_id node, OMX_U32 port_index,
- const sp<NativeHandle> &nativeHandle, buffer_id buffer);
+ sp<IOMXNode> *omxNode);
virtual status_t createInputSurface(
- node_id node, OMX_U32 port_index, android_dataspace dataSpace,
sp<IGraphicBufferProducer> *bufferProducer,
- MetadataBufferType *type);
-
- virtual status_t createPersistentInputSurface(
- sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferConsumer> *bufferConsumer);
-
- virtual status_t setInputSurface(
- node_id node, OMX_U32 port_index,
- const sp<IGraphicBufferConsumer> &bufferConsumer,
- MetadataBufferType *type);
-
- virtual status_t signalEndOfInputStream(node_id node);
-
- virtual status_t allocateSecureBuffer(
- node_id node, OMX_U32 port_index, size_t size,
- buffer_id *buffer, void **buffer_data, sp<NativeHandle> *native_handle);
-
- virtual status_t allocateBufferWithBackup(
- node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
- buffer_id *buffer, OMX_U32 allottedSize);
-
- virtual status_t freeBuffer(
- node_id node, OMX_U32 port_index, buffer_id buffer);
-
- virtual status_t fillBuffer(node_id node, buffer_id buffer, int fenceFd);
-
- virtual status_t emptyBuffer(
- node_id node,
- buffer_id buffer,
- OMX_U32 range_offset, OMX_U32 range_length,
- OMX_U32 flags, OMX_TICKS timestamp, int fenceFd);
-
- virtual status_t getExtensionIndex(
- node_id node,
- const char *parameter_name,
- OMX_INDEXTYPE *index);
-
- virtual status_t setInternalOption(
- node_id node,
- OMX_U32 port_index,
- InternalOptionType type,
- const void *data,
- size_t size);
+ sp<IGraphicBufferSource> *bufferSource);
virtual void binderDied(const wp<IBinder> &the_late_who);
- virtual bool isSecure(IOMX::node_id node);
-
- OMX_ERRORTYPE OnEvent(
- node_id node,
- OMX_IN OMX_EVENTTYPE eEvent,
- OMX_IN OMX_U32 nData1,
- OMX_IN OMX_U32 nData2,
- OMX_IN OMX_PTR pEventData);
-
- OMX_ERRORTYPE OnEmptyBufferDone(
- node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer, int fenceFd);
-
- OMX_ERRORTYPE OnFillBufferDone(
- node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer, int fenceFd);
-
- void invalidateNodeID(node_id node);
+ status_t freeNode(const sp<OMXNodeInstance>& instance);
protected:
virtual ~OMX();
private:
- struct CallbackDispatcherThread;
- struct CallbackDispatcher;
-
Mutex mLock;
OMXMaster *mMaster;
- size_t mNodeCounter;
- KeyedVector<wp<IBinder>, OMXNodeInstance *> mLiveNodes;
- KeyedVector<node_id, OMXNodeInstance *> mNodeIDToInstance;
- KeyedVector<node_id, sp<CallbackDispatcher> > mDispatchers;
-
- node_id makeNodeID_l(OMXNodeInstance *instance);
- OMXNodeInstance *findInstance(node_id node);
- sp<CallbackDispatcher> findDispatcher(node_id node);
-
- void invalidateNodeID_l(node_id node);
+ KeyedVector<wp<IBinder>, sp<OMXNodeInstance> > mLiveNodes;
OMX(const OMX &);
OMX &operator=(const OMX &);
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index 6411267..d911508 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -25,22 +25,20 @@
#include <utils/threads.h>
namespace android {
-
+class IOMXBufferSource;
class IOMXObserver;
struct OMXMaster;
-class GraphicBufferSource;
-struct OMXNodeInstance {
+struct OMXNodeInstance : public BnOMXNode {
OMXNodeInstance(
OMX *owner, const sp<IOMXObserver> &observer, const char *name);
- void setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle);
+ void setHandle(OMX_HANDLETYPE handle);
- OMX *owner();
+ OMX_HANDLETYPE handle();
sp<IOMXObserver> observer();
- OMX::node_id nodeID();
- status_t freeNode(OMXMaster *master);
+ status_t freeNode() override;
status_t sendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param);
status_t getParameter(OMX_INDEXTYPE index, void *params, size_t size);
@@ -51,8 +49,6 @@
status_t getConfig(OMX_INDEXTYPE index, void *params, size_t size);
status_t setConfig(OMX_INDEXTYPE index, const void *params, size_t size);
- status_t getState(OMX_STATETYPE* state);
-
status_t enableNativeBuffers(OMX_U32 portIndex, OMX_BOOL graphic, OMX_BOOL enable);
status_t getGraphicBufferUsage(OMX_U32 portIndex, OMX_U32* usage);
@@ -84,31 +80,13 @@
OMX_U32 portIndex, const sp<NativeHandle> &nativeHandle,
OMX::buffer_id buffer);
- status_t createInputSurface(
- OMX_U32 portIndex, android_dataspace dataSpace,
- sp<IGraphicBufferProducer> *bufferProducer,
- MetadataBufferType *type);
-
- static status_t createPersistentInputSurface(
- sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferConsumer> *bufferConsumer);
-
status_t setInputSurface(
- OMX_U32 portIndex, const sp<IGraphicBufferConsumer> &bufferConsumer,
- MetadataBufferType *type);
-
- status_t signalEndOfInputStream();
-
- void signalEvent(OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2);
+ const sp<IOMXBufferSource> &bufferSource);
status_t allocateSecureBuffer(
OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
void **buffer_data, sp<NativeHandle> *native_handle);
- status_t allocateBufferWithBackup(
- OMX_U32 portIndex, const sp<IMemory> ¶ms,
- OMX::buffer_id *buffer, OMX_U32 allottedSize);
-
status_t freeBuffer(OMX_U32 portIndex, OMX::buffer_id buffer);
status_t fillBuffer(OMX::buffer_id buffer, int fenceFd);
@@ -119,50 +97,50 @@
OMX_U32 flags, OMX_TICKS timestamp, int fenceFd);
status_t emptyGraphicBuffer(
- OMX_BUFFERHEADERTYPE *header, const sp<GraphicBuffer> &buffer,
- OMX_U32 flags, OMX_TICKS timestamp, int fenceFd);
+ OMX::buffer_id buffer,
+ const sp<GraphicBuffer> &graphicBuffer, OMX_U32 flags,
+ OMX_TICKS timestamp, OMX_TICKS origTimestamp, int fenceFd);
status_t getExtensionIndex(
const char *parameterName, OMX_INDEXTYPE *index);
- status_t setInternalOption(
- OMX_U32 portIndex,
- IOMX::InternalOptionType type,
- const void *data,
- size_t size);
+ status_t setQuirks(OMX_U32 quirks);
bool isSecure() const {
return mIsSecure;
}
+ status_t dispatchMessage(const omx_message &msg) override;
+
// handles messages and removes them from the list
void onMessages(std::list<omx_message> &messages);
- void onMessage(const omx_message &msg);
- void onObserverDied(OMXMaster *master);
- void onGetHandleFailed();
+ void onObserverDied();
void onEvent(OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2);
static OMX_CALLBACKTYPE kCallbacks;
private:
+ struct CallbackDispatcherThread;
+ struct CallbackDispatcher;
+
Mutex mLock;
OMX *mOwner;
- OMX::node_id mNodeID;
OMX_HANDLETYPE mHandle;
sp<IOMXObserver> mObserver;
+ sp<CallbackDispatcher> mDispatcher;
bool mDying;
bool mSailed; // configuration is set (no more meta-mode changes)
bool mQueriedProhibitedExtensions;
SortedVector<OMX_INDEXTYPE> mProhibitedExtensions;
bool mIsSecure;
+ uint32_t mQuirks;
- // Lock only covers mGraphicBufferSource. We can't always use mLock
- // because of rare instances where we'd end up locking it recursively.
- Mutex mGraphicBufferSourceLock;
- // Access this through getGraphicBufferSource().
- sp<GraphicBufferSource> mGraphicBufferSource;
-
+ // Lock only covers mOMXBufferSource and mOMXOutputListener. We can't always
+ // use mLock because of rare instances where we'd end up locking it recursively.
+ Mutex mOMXBufferSourceLock;
+ // Access these through getBufferSource().
+ sp<IOMXBufferSource> mOMXBufferSource;
struct ActiveBuffer {
OMX_U32 mPortIndex;
@@ -184,6 +162,10 @@
};
SecureBufferType mSecureBufferType[2];
+ KeyedVector<int64_t, int64_t> mOriginalTimeUs;
+ bool mShouldRestorePts;
+ bool mRestorePtsFailed;
+
// For debug support
char *mName;
int DEBUG;
@@ -254,18 +236,20 @@
// buffer.)
status_t updateGraphicBufferInMeta_l(
OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
- OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header, bool updateCodecBuffer);
+ OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header);
- status_t createGraphicBufferSource(
- OMX_U32 portIndex, const sp<IGraphicBufferConsumer> &consumer /* nullable */,
- MetadataBufferType *type);
- sp<GraphicBufferSource> getGraphicBufferSource();
- void setGraphicBufferSource(const sp<GraphicBufferSource> &bufferSource);
+ sp<IOMXBufferSource> getBufferSource();
+ void setBufferSource(const sp<IOMXBufferSource> &bufferSource);
+ // Called when omx_message::FILL_BUFFER_DONE is received. (Currently the
+ // buffer source will fix timestamp in the header if needed.)
+ void codecBufferFilled(omx_message &msg);
// Handles |msg|, and may modify it. Returns true iff completely handled it and
// |msg| does not need to be sent to the event listener.
bool handleMessage(omx_message &msg);
+ bool handleDataSpaceChanged(omx_message &msg);
+
OMXNodeInstance(const OMXNodeInstance &);
OMXNodeInstance &operator=(const OMXNodeInstance &);
};
diff --git a/media/libstagefright/include/SharedMemoryBuffer.h b/media/libstagefright/include/SharedMemoryBuffer.h
new file mode 100644
index 0000000..1d7f7a6
--- /dev/null
+++ b/media/libstagefright/include/SharedMemoryBuffer.h
@@ -0,0 +1,45 @@
+/*
+ * 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 SHARED_MEMORY_BUFFER_H_
+
+#define SHARED_MEMORY_BUFFER_H_
+
+#include <media/MediaCodecBuffer.h>
+
+namespace android {
+
+struct AMessage;
+class IMemory;
+
+/**
+ * MediaCodecBuffer implementation based on IMemory.
+ */
+class SharedMemoryBuffer : public MediaCodecBuffer {
+public:
+ SharedMemoryBuffer(const sp<AMessage> &format, const sp<IMemory> &mem);
+
+ virtual ~SharedMemoryBuffer() = default;
+
+private:
+ SharedMemoryBuffer() = delete;
+
+ const sp<IMemory> mMemory;
+};
+
+} // namespace android
+
+#endif // SHARED_MEMORY_BUFFER_H_
diff --git a/media/libstagefright/include/avc_utils.h b/media/libstagefright/include/avc_utils.h
index b2ef360..d05906a 100644
--- a/media/libstagefright/include/avc_utils.h
+++ b/media/libstagefright/include/avc_utils.h
@@ -18,6 +18,7 @@
#define AVC_UTILS_H_
+#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <utils/Errors.h>
@@ -84,6 +85,7 @@
sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit);
bool IsIDR(const sp<ABuffer> &accessUnit);
+bool IsIDR(const sp<MediaCodecBuffer> &accessUnit);
bool IsAVCReferenceFrame(const sp<ABuffer> &accessUnit);
uint32_t FindAVCLayerId(const uint8_t *data, size_t size);
diff --git a/media/libstagefright/matroska/Android.mk b/media/libstagefright/matroska/Android.mk
index 89d7ff2..7dd0863 100644
--- a/media/libstagefright/matroska/Android.mk
+++ b/media/libstagefright/matroska/Android.mk
@@ -10,7 +10,6 @@
$(TOP)/frameworks/av/media/libstagefright/include \
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
-LOCAL_CLANG := true
LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow
LOCAL_SHARED_LIBRARIES := libmedia
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
index 8e82486..b060628 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.cpp
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -605,16 +605,27 @@
int64_t timeUs = mBlockIter.blockTimeUs();
for (int i = 0; i < block->GetFrameCount(); ++i) {
+ MatroskaExtractor::TrackInfo *trackInfo = &mExtractor->mTracks.editItemAt(mTrackIndex);
const mkvparser::Block::Frame &frame = block->GetFrame(i);
+ size_t len = frame.len;
+ if (SIZE_MAX - len < trackInfo->mHeaderLen) {
+ return ERROR_MALFORMED;
+ }
- MediaBuffer *mbuf = new MediaBuffer(frame.len);
+ len += trackInfo->mHeaderLen;
+ MediaBuffer *mbuf = new MediaBuffer(len);
+ uint8_t *data = static_cast<uint8_t *>(mbuf->data());
+ if (trackInfo->mHeader) {
+ memcpy(data, trackInfo->mHeader, trackInfo->mHeaderLen);
+ }
+
mbuf->meta_data()->setInt64(kKeyTime, timeUs);
mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey());
- status_t err = frame.Read(mExtractor->mReader, static_cast<uint8_t *>(mbuf->data()));
+ status_t err = frame.Read(mExtractor->mReader, data + trackInfo->mHeaderLen);
if (err == OK
&& mExtractor->mIsWebm
- && mExtractor->mTracks.itemAt(mTrackIndex).mEncrypted) {
+ && trackInfo->mEncrypted) {
err = setWebmBlockCryptoInfo(mbuf);
}
@@ -1164,6 +1175,42 @@
}
}
+status_t MatroskaExtractor::initTrackInfo(
+ const mkvparser::Track *track, const sp<MetaData> &meta, TrackInfo *trackInfo) {
+ trackInfo->mTrackNum = track->GetNumber();
+ trackInfo->mMeta = meta;
+ trackInfo->mExtractor = this;
+ trackInfo->mEncrypted = false;
+ trackInfo->mHeader = NULL;
+ trackInfo->mHeaderLen = 0;
+
+ for(size_t i = 0; i < track->GetContentEncodingCount(); i++) {
+ const mkvparser::ContentEncoding *encoding = track->GetContentEncodingByIndex(i);
+ for(size_t j = 0; j < encoding->GetEncryptionCount(); j++) {
+ const mkvparser::ContentEncoding::ContentEncryption *encryption;
+ encryption = encoding->GetEncryptionByIndex(j);
+ trackInfo->mMeta->setData(kKeyCryptoKey, 0, encryption->key_id, encryption->key_id_len);
+ trackInfo->mEncrypted = true;
+ break;
+ }
+
+ for(size_t j = 0; j < encoding->GetCompressionCount(); j++) {
+ const mkvparser::ContentEncoding::ContentCompression *compression;
+ compression = encoding->GetCompressionByIndex(j);
+ ALOGV("compression algo %llu settings_len %lld",
+ compression->algo, compression->settings_len);
+ if (compression->algo == 3
+ && compression->settings
+ && compression->settings_len > 0) {
+ trackInfo->mHeader = compression->settings;
+ trackInfo->mHeaderLen = compression->settings_len;
+ }
+ }
+ }
+
+ return OK;
+}
+
void MatroskaExtractor::addTracks() {
const mkvparser::Tracks *tracks = mSegment->GetTracks();
@@ -1288,21 +1335,7 @@
mTracks.push();
size_t n = mTracks.size() - 1;
TrackInfo *trackInfo = &mTracks.editItemAt(n);
- trackInfo->mTrackNum = track->GetNumber();
- trackInfo->mMeta = meta;
- trackInfo->mExtractor = this;
-
- trackInfo->mEncrypted = false;
- for(size_t i = 0; i < track->GetContentEncodingCount() && !trackInfo->mEncrypted; i++) {
- const mkvparser::ContentEncoding *encoding = track->GetContentEncodingByIndex(i);
- for(size_t j = 0; j < encoding->GetEncryptionCount(); j++) {
- const mkvparser::ContentEncoding::ContentEncryption *encryption;
- encryption = encoding->GetEncryptionByIndex(j);
- meta->setData(kKeyCryptoKey, 0, encryption->key_id, encryption->key_id_len);
- trackInfo->mEncrypted = true;
- break;
- }
- }
+ initTrackInfo(track, meta, trackInfo);
if (!strcmp("V_MPEG4/ISO/AVC", codecID) && codecPrivateSize == 0) {
// Attempt to recover from AVC track without codec private data
diff --git a/media/libstagefright/matroska/MatroskaExtractor.h b/media/libstagefright/matroska/MatroskaExtractor.h
index 588bd39..19775ce 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.h
+++ b/media/libstagefright/matroska/MatroskaExtractor.h
@@ -63,6 +63,12 @@
const MatroskaExtractor *mExtractor;
Vector<const mkvparser::CuePoint*> mCuePoints;
+ // mHeader points to memory managed by mkvparser;
+ // mHeader would be deleted when mSegment is deleted
+ // in ~MatroskaExtractor.
+ unsigned char *mHeader;
+ size_t mHeaderLen;
+
const mkvparser::Track* getTrack() const;
const mkvparser::CuePoint::TrackPosition *find(long long timeNs) const;
};
@@ -79,6 +85,7 @@
int64_t mSeekPreRollNs;
status_t synthesizeAVCC(TrackInfo *trackInfo, size_t index);
+ status_t initTrackInfo(const mkvparser::Track *track, const sp<MetaData> &meta, TrackInfo *trackInfo);
void addTracks();
void findThumbnails();
void getColorInformation(const mkvparser::VideoTrack *vtrack, sp<MetaData> &meta);
diff --git a/media/libstagefright/mpeg2ts/Android.mk b/media/libstagefright/mpeg2ts/Android.mk
index 66722a8..92c386c 100644
--- a/media/libstagefright/mpeg2ts/Android.mk
+++ b/media/libstagefright/mpeg2ts/Android.mk
@@ -14,7 +14,6 @@
$(TOP)/frameworks/native/include/media/openmax
LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow
LOCAL_SHARED_LIBRARIES := libmedia
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index e4fbd81..ee4fc05 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -33,7 +33,6 @@
LOCAL_MODULE:= libstagefright_omx
LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 1d819b5..afb8173 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -23,10 +23,6 @@
#define STRINGIFY_ENUMS // for asString in HardwareAPI.h/VideoAPI.h
#include "GraphicBufferSource.h"
-#include "OMXUtils.h"
-
-#include <OMX_Core.h>
-#include <OMX_IndexExt.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/ColorUtils.h>
@@ -35,97 +31,22 @@
#include <ui/GraphicBuffer.h>
#include <gui/BufferItem.h>
#include <HardwareAPI.h>
+#include "omx/OMXUtils.h"
+#include <OMX_Component.h>
+#include <OMX_IndexExt.h>
#include <inttypes.h>
#include "FrameDropper.h"
namespace android {
-static const bool EXTRA_CHECK = true;
-
static const OMX_U32 kPortIndexInput = 0;
-GraphicBufferSource::PersistentProxyListener::PersistentProxyListener(
- const wp<IGraphicBufferConsumer> &consumer,
- const wp<ConsumerListener>& consumerListener) :
- mConsumerListener(consumerListener),
- mConsumer(consumer) {}
-
-GraphicBufferSource::PersistentProxyListener::~PersistentProxyListener() {}
-
-void GraphicBufferSource::PersistentProxyListener::onFrameAvailable(
- const BufferItem& item) {
- sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onFrameAvailable(item);
- } else {
- sp<IGraphicBufferConsumer> consumer(mConsumer.promote());
- if (consumer == NULL) {
- return;
- }
- BufferItem bi;
- status_t err = consumer->acquireBuffer(&bi, 0);
- if (err != OK) {
- ALOGE("PersistentProxyListener: acquireBuffer failed (%d)", err);
- return;
- }
-
- err = consumer->detachBuffer(bi.mSlot);
- if (err != OK) {
- ALOGE("PersistentProxyListener: detachBuffer failed (%d)", err);
- return;
- }
-
- err = consumer->attachBuffer(&bi.mSlot, bi.mGraphicBuffer);
- if (err != OK) {
- ALOGE("PersistentProxyListener: attachBuffer failed (%d)", err);
- return;
- }
-
- err = consumer->releaseBuffer(bi.mSlot, 0,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, bi.mFence);
- if (err != OK) {
- ALOGE("PersistentProxyListener: releaseBuffer failed (%d)", err);
- }
- }
-}
-
-void GraphicBufferSource::PersistentProxyListener::onFrameReplaced(
- const BufferItem& item) {
- sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onFrameReplaced(item);
- }
-}
-
-void GraphicBufferSource::PersistentProxyListener::onBuffersReleased() {
- sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onBuffersReleased();
- }
-}
-
-void GraphicBufferSource::PersistentProxyListener::onSidebandStreamChanged() {
- sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onSidebandStreamChanged();
- }
-}
-
-GraphicBufferSource::GraphicBufferSource(
- OMXNodeInstance* nodeInstance,
- uint32_t bufferWidth,
- uint32_t bufferHeight,
- uint32_t bufferCount,
- uint32_t consumerUsage,
- const sp<IGraphicBufferConsumer> &consumer) :
+GraphicBufferSource::GraphicBufferSource() :
mInitCheck(UNKNOWN_ERROR),
- mNodeInstance(nodeInstance),
mExecuting(false),
mSuspended(false),
mLastDataSpace(HAL_DATASPACE_UNKNOWN),
- mIsPersistent(false),
- mConsumer(consumer),
mNumFramesAvailable(0),
mNumBufferAcquired(0),
mEndOfStream(false),
@@ -137,6 +58,7 @@
mRepeatAfterUs(-1ll),
mRepeatLastFrameGeneration(0),
mRepeatLastFrameTimestamp(-1ll),
+ mRepeatLastFrameCount(0),
mLatestBufferId(-1),
mLatestBufferFrameNum(0),
mLatestBufferFence(Fence::NO_FENCE),
@@ -146,48 +68,21 @@
mPrevCaptureUs(-1ll),
mPrevFrameUs(-1ll),
mInputBufferTimeOffsetUs(0ll) {
+ ALOGV("GraphicBufferSource");
- ALOGV("GraphicBufferSource w=%u h=%u c=%u",
- bufferWidth, bufferHeight, bufferCount);
+ String8 name("GraphicBufferSource");
- if (bufferWidth == 0 || bufferHeight == 0) {
- ALOGE("Invalid dimensions %ux%u", bufferWidth, bufferHeight);
- mInitCheck = BAD_VALUE;
- return;
- }
+ BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+ mConsumer->setConsumerName(name);
- if (mConsumer == NULL) {
- String8 name("GraphicBufferSource");
-
- BufferQueue::createBufferQueue(&mProducer, &mConsumer);
- mConsumer->setConsumerName(name);
-
- // use consumer usage bits queried from encoder, but always add HW_VIDEO_ENCODER
- // for backward compatibility.
- consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
- mConsumer->setConsumerUsageBits(consumerUsage);
-
- mInitCheck = mConsumer->setMaxAcquiredBufferCount(bufferCount);
- if (mInitCheck != NO_ERROR) {
- ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
- bufferCount, mInitCheck);
- return;
- }
- } else {
- mIsPersistent = true;
- }
- mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight);
// Note that we can't create an sp<...>(this) in a ctor that will not keep a
// reference once the ctor ends, as that would cause the refcount of 'this'
// dropping to 0 at the end of the ctor. Since all we need is a wp<...>
// that's what we create.
- wp<BufferQueue::ConsumerListener> listener = static_cast<BufferQueue::ConsumerListener*>(this);
- sp<IConsumerListener> proxy;
- if (!mIsPersistent) {
- proxy = new BufferQueue::ProxyConsumerListener(listener);
- } else {
- proxy = new PersistentProxyListener(mConsumer, listener);
- }
+ wp<BufferQueue::ConsumerListener> listener =
+ static_cast<BufferQueue::ConsumerListener*>(this);
+ sp<IConsumerListener> proxy =
+ new BufferQueue::ProxyConsumerListener(listener);
mInitCheck = mConsumer->consumerConnect(proxy, false);
if (mInitCheck != NO_ERROR) {
@@ -202,15 +97,14 @@
}
GraphicBufferSource::~GraphicBufferSource() {
+ ALOGV("~GraphicBufferSource");
if (mLatestBufferId >= 0) {
- releaseBuffer(
- mLatestBufferId, mLatestBufferFrameNum,
- mBufferSlot[mLatestBufferId], mLatestBufferFence);
+ releaseBuffer(mLatestBufferId, mLatestBufferFrameNum, mLatestBufferFence);
}
if (mNumBufferAcquired != 0) {
ALOGW("potential buffer leak (acquired %d)", mNumBufferAcquired);
}
- if (mConsumer != NULL && !mIsPersistent) {
+ if (mConsumer != NULL) {
status_t err = mConsumer->consumerDisconnect();
if (err != NO_ERROR) {
ALOGW("consumerDisconnect failed: %d", err);
@@ -218,7 +112,7 @@
}
}
-void GraphicBufferSource::omxExecuting() {
+Status GraphicBufferSource::onOmxExecuting() {
Mutex::Autolock autoLock(mMutex);
ALOGV("--> executing; avail=%zu, codec vec size=%zd",
mNumFramesAvailable, mCodecBuffers.size());
@@ -267,9 +161,11 @@
msg->post(mRepeatAfterUs);
}
}
+
+ return Status::ok();
}
-void GraphicBufferSource::omxIdle() {
+Status GraphicBufferSource::onOmxIdle() {
ALOGV("omxIdle");
Mutex::Autolock autoLock(mMutex);
@@ -279,9 +175,10 @@
// not loaded->idle.
mExecuting = false;
}
+ return Status::ok();
}
-void GraphicBufferSource::omxLoaded(){
+Status GraphicBufferSource::onOmxLoaded(){
Mutex::Autolock autoLock(mMutex);
if (!mExecuting) {
// This can happen if something failed very early.
@@ -296,53 +193,77 @@
mLooper.clear();
}
- ALOGV("--> loaded; avail=%zu eos=%d eosSent=%d",
- mNumFramesAvailable, mEndOfStream, mEndOfStreamSent);
+ ALOGV("--> loaded; avail=%zu eos=%d eosSent=%d acquired=%d",
+ mNumFramesAvailable, mEndOfStream, mEndOfStreamSent, mNumBufferAcquired);
- // Codec is no longer executing. Discard all codec-related state.
+ // Codec is no longer executing. Releasing all buffers to bq.
+ for (int i = (int)mCodecBuffers.size() - 1; i >= 0; --i) {
+ if (mCodecBuffers[i].mGraphicBuffer != NULL) {
+ int id = mCodecBuffers[i].mSlot;
+ if (id != mLatestBufferId) {
+ ALOGV("releasing buffer for codec: slot=%d, useCount=%d, latest=%d",
+ id, mBufferUseCount[id], mLatestBufferId);
+ sp<Fence> fence = new Fence(-1);
+ releaseBuffer(id, mCodecBuffers[i].mFrameNumber, fence);
+ mBufferUseCount[id] = 0;
+ }
+ }
+ }
+ // Also release the latest buffer
+ if (mLatestBufferId >= 0) {
+ releaseBuffer(mLatestBufferId, mLatestBufferFrameNum, mLatestBufferFence);
+ mBufferUseCount[mLatestBufferId] = 0;
+ mLatestBufferId = -1;
+ }
+
mCodecBuffers.clear();
- // TODO: scan mCodecBuffers to verify that all mGraphicBuffer entries
- // are null; complain if not
-
+ mOMXNode.clear();
mExecuting = false;
+
+ return Status::ok();
}
-void GraphicBufferSource::addCodecBuffer(OMX_BUFFERHEADERTYPE* header) {
+Status GraphicBufferSource::onInputBufferAdded(int32_t bufferID) {
Mutex::Autolock autoLock(mMutex);
if (mExecuting) {
// This should never happen -- buffers can only be allocated when
// transitioning from "loaded" to "idle".
ALOGE("addCodecBuffer: buffer added while executing");
- return;
+ return Status::fromServiceSpecificError(INVALID_OPERATION);
}
- ALOGV("addCodecBuffer h=%p size=%" PRIu32 " p=%p",
- header, header->nAllocLen, header->pBuffer);
+ ALOGV("addCodecBuffer: bufferID=%u", bufferID);
+
CodecBuffer codecBuffer;
- codecBuffer.mHeader = header;
+ codecBuffer.mBufferID = bufferID;
mCodecBuffers.add(codecBuffer);
+ return Status::ok();
}
-void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header, int fenceFd) {
+Status GraphicBufferSource::onInputBufferEmptied(
+ int32_t bufferID, const OMXFenceParcelable &fenceParcel) {
+ int fenceFd = fenceParcel.get();
+
Mutex::Autolock autoLock(mMutex);
if (!mExecuting) {
- return;
- }
-
- int cbi = findMatchingCodecBuffer_l(header);
- if (cbi < 0) {
- // This should never happen.
- ALOGE("codecBufferEmptied: buffer not recognized (h=%p)", header);
if (fenceFd >= 0) {
::close(fenceFd);
}
- return;
+ return Status::fromServiceSpecificError(INVALID_OPERATION);
}
- ALOGV("codecBufferEmptied h=%p size=%" PRIu32 " filled=%" PRIu32 " p=%p",
- header, header->nAllocLen, header->nFilledLen,
- header->pBuffer);
+ int cbi = findMatchingCodecBuffer_l(bufferID);
+ if (cbi < 0) {
+ // This should never happen.
+ ALOGE("codecBufferEmptied: buffer not recognized (bufferID=%u)", bufferID);
+ if (fenceFd >= 0) {
+ ::close(fenceFd);
+ }
+ return Status::fromServiceSpecificError(BAD_VALUE);
+ }
+
+ ALOGV("codecBufferEmptied: bufferID=%u, cbi=%d", bufferID, cbi);
CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
// header->nFilledLen may not be the original value, so we can't compare
@@ -361,33 +282,7 @@
if (fenceFd >= 0) {
::close(fenceFd);
}
- return;
- }
-
- if (EXTRA_CHECK && header->nAllocLen >= sizeof(MetadataBufferType)) {
- // Pull the graphic buffer handle back out of the buffer, and confirm
- // that it matches expectations.
- OMX_U8* data = header->pBuffer;
- MetadataBufferType type = *(MetadataBufferType *)data;
- if (type == kMetadataBufferTypeGrallocSource
- && header->nAllocLen >= sizeof(VideoGrallocMetadata)) {
- VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)data;
- if (grallocMeta.pHandle != codecBuffer.mGraphicBuffer->handle) {
- // should never happen
- ALOGE("codecBufferEmptied: buffer's handle is %p, expected %p",
- grallocMeta.pHandle, codecBuffer.mGraphicBuffer->handle);
- CHECK(!"codecBufferEmptied: mismatched buffer");
- }
- } else if (type == kMetadataBufferTypeANWBuffer
- && header->nAllocLen >= sizeof(VideoNativeMetadata)) {
- VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)data;
- if (nativeMeta.pBuffer != codecBuffer.mGraphicBuffer->getNativeBuffer()) {
- // should never happen
- ALOGE("codecBufferEmptied: buffer is %p, expected %p",
- nativeMeta.pBuffer, codecBuffer.mGraphicBuffer->getNativeBuffer());
- CHECK(!"codecBufferEmptied: mismatched buffer");
- }
- }
+ return Status::fromServiceSpecificError(BAD_VALUE);
}
// Find matching entry in our cached copy of the BufferQueue slots.
@@ -399,19 +294,19 @@
mBufferSlot[id]->handle == codecBuffer.mGraphicBuffer->handle) {
mBufferUseCount[id]--;
- ALOGV("codecBufferEmptied: slot=%d, cbi=%d, useCount=%d, handle=%p",
- id, cbi, mBufferUseCount[id], mBufferSlot[id]->handle);
-
if (mBufferUseCount[id] < 0) {
ALOGW("mBufferUseCount for bq slot %d < 0 (=%d)", id, mBufferUseCount[id]);
mBufferUseCount[id] = 0;
}
if (id != mLatestBufferId && mBufferUseCount[id] == 0) {
- releaseBuffer(id, codecBuffer.mFrameNumber, mBufferSlot[id], fence);
+ releaseBuffer(id, codecBuffer.mFrameNumber, fence);
}
+ ALOGV("codecBufferEmptied: slot=%d, cbi=%d, useCount=%d, acquired=%d, handle=%p",
+ id, cbi, mBufferUseCount[id], mNumBufferAcquired, mBufferSlot[id]->handle);
} else {
- ALOGV("codecBufferEmptied: no match for emptied buffer in cbi %d",
- cbi);
+ ALOGV("codecBufferEmptied: no match for emptied buffer, "
+ "slot=%d, cbi=%d, useCount=%d, acquired=%d",
+ id, cbi, mBufferUseCount[id], mNumBufferAcquired);
// we will not reuse codec buffer, so there is no need to wait for fence
}
@@ -439,75 +334,7 @@
mRepeatBufferDeferred = false;
}
- return;
-}
-
-void GraphicBufferSource::codecBufferFilled(OMX_BUFFERHEADERTYPE* header) {
- Mutex::Autolock autoLock(mMutex);
-
- if (mMaxTimestampGapUs > 0ll
- && !(header->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
- ssize_t index = mOriginalTimeUs.indexOfKey(header->nTimeStamp);
- if (index >= 0) {
- ALOGV("OUT timestamp: %lld -> %lld",
- static_cast<long long>(header->nTimeStamp),
- static_cast<long long>(mOriginalTimeUs[index]));
- header->nTimeStamp = mOriginalTimeUs[index];
- mOriginalTimeUs.removeItemsAt(index);
- } else {
- // giving up the effort as encoder doesn't appear to preserve pts
- ALOGW("giving up limiting timestamp gap (pts = %lld)",
- header->nTimeStamp);
- mMaxTimestampGapUs = -1ll;
- }
- if (mOriginalTimeUs.size() > BufferQueue::NUM_BUFFER_SLOTS) {
- // something terribly wrong must have happened, giving up...
- ALOGE("mOriginalTimeUs has too many entries (%zu)",
- mOriginalTimeUs.size());
- mMaxTimestampGapUs = -1ll;
- }
- }
-}
-
-void GraphicBufferSource::suspend(bool suspend) {
- Mutex::Autolock autoLock(mMutex);
-
- if (suspend) {
- mSuspended = true;
-
- while (mNumFramesAvailable > 0) {
- BufferItem item;
- status_t err = mConsumer->acquireBuffer(&item, 0);
-
- if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
- // shouldn't happen.
- ALOGW("suspend: frame was not available");
- break;
- } else if (err != OK) {
- ALOGW("suspend: acquireBuffer returned err=%d", err);
- break;
- }
-
- ++mNumBufferAcquired;
- --mNumFramesAvailable;
-
- releaseBuffer(item.mSlot, item.mFrameNumber,
- item.mGraphicBuffer, item.mFence);
- }
- return;
- }
-
- mSuspended = false;
-
- if (mExecuting && mNumFramesAvailable == 0 && mRepeatBufferDeferred) {
- if (repeatLatestBuffer_l()) {
- ALOGV("suspend/deferred repeatLatestBuffer_l SUCCESS");
-
- mRepeatBufferDeferred = false;
- } else {
- ALOGV("suspend/deferred repeatLatestBuffer_l FAILURE");
- }
- }
+ return Status::ok();
}
void GraphicBufferSource::onDataSpaceChanged_l(
@@ -516,67 +343,15 @@
mLastDataSpace = dataSpace;
if (ColorUtils::convertDataSpaceToV0(dataSpace)) {
- ColorAspects aspects = mColorAspects; // initially requested aspects
+ omx_message msg;
+ msg.type = omx_message::EVENT;
+ msg.fenceFd = -1;
+ msg.u.event_data.event = OMX_EventDataSpaceChanged;
+ msg.u.event_data.data1 = mLastDataSpace;
+ msg.u.event_data.data2 = ColorUtils::packToU32(mColorAspects);
+ msg.u.event_data.data3 = pixelFormat;
- // request color aspects to encode
- OMX_INDEXTYPE index;
- status_t err = mNodeInstance->getExtensionIndex(
- "OMX.google.android.index.describeColorAspects", &index);
- if (err == OK) {
- // V0 dataspace
- DescribeColorAspectsParams params;
- InitOMXParams(¶ms);
- params.nPortIndex = kPortIndexInput;
- params.nDataSpace = mLastDataSpace;
- params.nPixelFormat = pixelFormat;
- params.bDataSpaceChanged = OMX_TRUE;
- params.sAspects = mColorAspects;
-
- err = mNodeInstance->getConfig(index, ¶ms, sizeof(params));
- if (err == OK) {
- aspects = params.sAspects;
- ALOGD("Codec resolved it to (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
- params.sAspects.mRange, asString(params.sAspects.mRange),
- params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
- params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
- params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
- err, asString(err));
- } else {
- params.sAspects = aspects;
- err = OK;
- }
- params.bDataSpaceChanged = OMX_FALSE;
- for (int triesLeft = 2; --triesLeft >= 0; ) {
- status_t err = mNodeInstance->setConfig(index, ¶ms, sizeof(params));
- if (err == OK) {
- err = mNodeInstance->getConfig(index, ¶ms, sizeof(params));
- }
- if (err != OK || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(
- params.sAspects, aspects)) {
- // if we can't set or get color aspects, still communicate dataspace to client
- break;
- }
-
- ALOGW_IF(triesLeft == 0, "Codec repeatedly changed requested ColorAspects.");
- }
- }
-
- ALOGV("Set color aspects to (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
- aspects.mRange, asString(aspects.mRange),
- aspects.mPrimaries, asString(aspects.mPrimaries),
- aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs),
- aspects.mTransfer, asString(aspects.mTransfer),
- err, asString(err));
-
- // signal client that the dataspace has changed; this will update the output format
- // TODO: we should tie this to an output buffer somehow, and signal the change
- // just before the output buffer is returned to the client, but there are many
- // ways this could fail (e.g. flushing), and we are not yet supporting this scenario.
-
- mNodeInstance->signalEvent(
- OMX_EventDataSpaceChanged, dataSpace,
- (aspects.mRange << 24) | (aspects.mPrimaries << 16)
- | (aspects.mMatrixCoeffs << 8) | aspects.mTransfer);
+ mOMXNode->dispatchMessage(msg);
}
}
@@ -598,34 +373,19 @@
ALOGV("fillCodecBuffer_l: acquiring buffer, avail=%zu",
mNumFramesAvailable);
BufferItem item;
- status_t err = mConsumer->acquireBuffer(&item, 0);
- if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
- // shouldn't happen
- ALOGW("fillCodecBuffer_l: frame was not available");
- return false;
- } else if (err != OK) {
- // now what? fake end-of-stream?
- ALOGW("fillCodecBuffer_l: acquireBuffer returned err=%d", err);
+ status_t err = acquireBuffer(&item);
+ if (err != OK) {
+ ALOGE("fillCodecBuffer_l: acquireBuffer returned err=%d", err);
return false;
}
- mNumBufferAcquired++;
mNumFramesAvailable--;
- // If this is the first time we're seeing this buffer, add it to our
- // slot table.
- if (item.mGraphicBuffer != NULL) {
- ALOGV("fillCodecBuffer_l: setting mBufferSlot %d", item.mSlot);
- mBufferSlot[item.mSlot] = item.mGraphicBuffer;
- mBufferUseCount[item.mSlot] = 0;
- }
-
if (item.mDataSpace != mLastDataSpace) {
onDataSpaceChanged_l(
item.mDataSpace, (android_pixel_format)mBufferSlot[item.mSlot]->getPixelFormat());
}
-
err = UNKNOWN_ERROR;
// only submit sample if start time is unspecified, or sample
@@ -650,10 +410,18 @@
if (err != OK) {
ALOGV("submitBuffer_l failed, releasing bq slot %d", item.mSlot);
- releaseBuffer(item.mSlot, item.mFrameNumber, item.mGraphicBuffer, item.mFence);
+ releaseBuffer(item.mSlot, item.mFrameNumber, item.mFence);
} else {
- ALOGV("buffer submitted (bq %d, cbi %d)", item.mSlot, cbi);
- setLatestBuffer_l(item, dropped);
+ // Don't set the last buffer id if we're not repeating,
+ // we'll be holding on to the last buffer for nothing.
+ if (mRepeatAfterUs > 0ll) {
+ setLatestBuffer_l(item);
+ }
+ if (!dropped) {
+ ++mBufferUseCount[item.mSlot];
+ }
+ ALOGV("buffer submitted: slot=%d, cbi=%d, useCount=%d, acquired=%d",
+ item.mSlot, cbi, mBufferUseCount[item.mSlot], mNumBufferAcquired);
}
return true;
@@ -722,24 +490,16 @@
return true;
}
-void GraphicBufferSource::setLatestBuffer_l(
- const BufferItem &item, bool dropped) {
- if (mLatestBufferId >= 0) {
- if (mBufferUseCount[mLatestBufferId] == 0) {
- releaseBuffer(mLatestBufferId, mLatestBufferFrameNum,
- mBufferSlot[mLatestBufferId], mLatestBufferFence);
- // mLatestBufferFence will be set to new fence just below
- }
+void GraphicBufferSource::setLatestBuffer_l(const BufferItem &item) {
+ if (mLatestBufferId >= 0 && mBufferUseCount[mLatestBufferId] == 0) {
+ releaseBuffer(mLatestBufferId, mLatestBufferFrameNum, mLatestBufferFence);
+ // mLatestBufferFence will be set to new fence just below
}
mLatestBufferId = item.mSlot;
mLatestBufferFrameNum = item.mFrameNumber;
mRepeatLastFrameTimestamp = item.mTimestamp + mRepeatAfterUs * 1000;
- if (!dropped) {
- ++mBufferUseCount[item.mSlot];
- }
-
ALOGV("setLatestBuffer_l: slot=%d, useCount=%d",
item.mSlot, mBufferUseCount[item.mSlot]);
@@ -754,34 +514,10 @@
}
}
-status_t GraphicBufferSource::signalEndOfInputStream() {
- Mutex::Autolock autoLock(mMutex);
- ALOGV("signalEndOfInputStream: exec=%d avail=%zu eos=%d",
- mExecuting, mNumFramesAvailable, mEndOfStream);
+bool GraphicBufferSource::getTimestamp(
+ const BufferItem &item, int64_t *origTimeUs, int64_t *codecTimeUs) {
+ *origTimeUs = -1ll;
- if (mEndOfStream) {
- ALOGE("EOS was already signaled");
- return INVALID_OPERATION;
- }
-
- // Set the end-of-stream flag. If no frames are pending from the
- // BufferQueue, and a codec buffer is available, and we're executing,
- // we initiate the EOS from here. Otherwise, we'll let
- // codecBufferEmptied() (or omxExecuting) do it.
- //
- // Note: if there are no pending frames and all codec buffers are
- // available, we *must* submit the EOS from here or we'll just
- // stall since no future events are expected.
- mEndOfStream = true;
-
- if (mExecuting && mNumFramesAvailable == 0) {
- submitEndOfInputStream_l();
- }
-
- return OK;
-}
-
-int64_t GraphicBufferSource::getTimestamp(const BufferItem &item) {
int64_t timeUs = item.mTimestamp / 1000;
timeUs += mInputBufferTimeOffsetUs;
@@ -800,7 +536,7 @@
if (nFrames <= 0) {
// skip this frame as it's too close to previous capture
ALOGV("skipping frame, timeUs %lld", static_cast<long long>(timeUs));
- return -1;
+ return false;
}
mPrevCaptureUs = mPrevCaptureUs + nFrames * mTimePerCaptureUs;
mPrevFrameUs += mTimePerFrameUs * nFrames;
@@ -811,14 +547,15 @@
static_cast<long long>(mPrevCaptureUs),
static_cast<long long>(mPrevFrameUs));
- return mPrevFrameUs;
+ *codecTimeUs = mPrevFrameUs;
+ return true;
} else {
int64_t originalTimeUs = timeUs;
if (originalTimeUs <= mPrevOriginalTimeUs) {
// Drop the frame if it's going backward in time. Bad timestamp
// could disrupt encoder's rate control completely.
ALOGW("Dropping frame that's going backward in time");
- return -1;
+ return false;
}
if (mMaxTimestampGapUs > 0ll) {
@@ -836,7 +573,7 @@
timeUs = (timestampGapUs < mMaxTimestampGapUs ?
timestampGapUs : mMaxTimestampGapUs) + mPrevModifiedTimeUs;
}
- mOriginalTimeUs.add(timeUs, originalTimeUs);
+ *origTimeUs = originalTimeUs;
ALOGV("IN timestamp: %lld -> %lld",
static_cast<long long>(originalTimeUs),
static_cast<long long>(timeUs));
@@ -846,14 +583,15 @@
mPrevModifiedTimeUs = timeUs;
}
- return timeUs;
+ *codecTimeUs = timeUs;
+ return true;
}
status_t GraphicBufferSource::submitBuffer_l(const BufferItem &item, int cbi) {
ALOGV("submitBuffer_l: slot=%d, cbi=%d", item.mSlot, cbi);
- int64_t timeUs = getTimestamp(item);
- if (timeUs < 0ll) {
+ int64_t origTimeUs, codecTimeUs;
+ if (!getTimestamp(item, &origTimeUs, &codecTimeUs)) {
return UNKNOWN_ERROR;
}
@@ -862,19 +600,22 @@
codecBuffer.mSlot = item.mSlot;
codecBuffer.mFrameNumber = item.mFrameNumber;
- OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
- sp<GraphicBuffer> buffer = codecBuffer.mGraphicBuffer;
- status_t err = mNodeInstance->emptyGraphicBuffer(
- header, buffer, OMX_BUFFERFLAG_ENDOFFRAME, timeUs,
- item.mFence->isValid() ? item.mFence->dup() : -1);
+ IOMX::buffer_id bufferID = codecBuffer.mBufferID;
+ const sp<GraphicBuffer> &buffer = codecBuffer.mGraphicBuffer;
+ int fenceID = item.mFence->isValid() ? item.mFence->dup() : -1;
+
+ status_t err = mOMXNode->emptyGraphicBuffer(
+ bufferID, buffer, OMX_BUFFERFLAG_ENDOFFRAME,
+ codecTimeUs, origTimeUs, fenceID);
+
if (err != OK) {
- ALOGW("WARNING: emptyNativeWindowBuffer failed: 0x%x", err);
+ ALOGW("WARNING: emptyGraphicBuffer failed: 0x%x", err);
codecBuffer.mGraphicBuffer = NULL;
return err;
}
- ALOGV("emptyNativeWindowBuffer succeeded, h=%p p=%p buf=%p bufhandle=%p",
- header, header->pBuffer, buffer->getNativeBuffer(), buffer->handle);
+ ALOGV("emptyGraphicBuffer succeeded, bufferID=%u buf=%p bufhandle=%p",
+ bufferID, buffer->getNativeBuffer(), buffer->handle);
return OK;
}
@@ -895,16 +636,17 @@
// to stick a placeholder into codecBuffer.mGraphicBuffer to mark it as
// in-use.
CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
+ IOMX::buffer_id bufferID = codecBuffer.mBufferID;
- OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
- status_t err = mNodeInstance->emptyGraphicBuffer(
- header, NULL /* buffer */, OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS,
- 0 /* timestamp */, -1 /* fenceFd */);
+ status_t err = mOMXNode->emptyGraphicBuffer(
+ bufferID, NULL /* buffer */,
+ OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS,
+ 0 /* timestamp */, -1ll /* origTimestamp */, -1 /* fenceFd */);
if (err != OK) {
ALOGW("emptyDirectBuffer EOS failed: 0x%x", err);
} else {
- ALOGV("submitEndOfInputStream_l: buffer submitted, header=%p cbi=%d",
- header, cbi);
+ ALOGV("submitEndOfInputStream_l: buffer submitted, bufferID=%u cbi=%d",
+ bufferID, cbi);
mEndOfStreamSent = true;
}
}
@@ -920,44 +662,48 @@
return -1;
}
-int GraphicBufferSource::findMatchingCodecBuffer_l(
- const OMX_BUFFERHEADERTYPE* header) {
+int GraphicBufferSource::findMatchingCodecBuffer_l(IOMX::buffer_id bufferID) {
for (int i = (int)mCodecBuffers.size() - 1; i>= 0; --i) {
- if (mCodecBuffers[i].mHeader == header) {
+ if (mCodecBuffers[i].mBufferID == bufferID) {
return i;
}
}
return -1;
}
+status_t GraphicBufferSource::acquireBuffer(BufferItem *bi) {
+ status_t err = mConsumer->acquireBuffer(bi, 0);
+ if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
+ // shouldn't happen
+ ALOGW("acquireBuffer: frame was not available");
+ return err;
+ } else if (err != OK) {
+ ALOGW("acquireBuffer: failed with err=%d", err);
+ return err;
+ }
+ // If this is the first time we're seeing this buffer, add it to our
+ // slot table.
+ if (bi->mGraphicBuffer != NULL) {
+ ALOGV("acquireBuffer: setting mBufferSlot %d", bi->mSlot);
+ mBufferSlot[bi->mSlot] = bi->mGraphicBuffer;
+ mBufferUseCount[bi->mSlot] = 0;
+ }
+ mNumBufferAcquired++;
+ return OK;
+}
+
/*
- * Releases an acquired buffer back to the consumer for either persistent
- * or non-persistent surfaces.
+ * Releases an acquired buffer back to the consumer.
*
- * id: buffer slot to release (in persistent case the id might be changed)
+ * id: buffer slot to release
* frameNum: frame number of the frame being released
- * buffer: GraphicBuffer pointer to release (note this must not be & as we
- * will clear the original mBufferSlot in persistent case)
- * Use NOLINT to supress warning on the copy of 'buffer'.
* fence: fence of the frame being released
*/
void GraphicBufferSource::releaseBuffer(
- int &id, uint64_t frameNum,
- const sp<GraphicBuffer> buffer, const sp<Fence> &fence) { // NOLINT
+ int id, uint64_t frameNum, const sp<Fence> &fence) {
ALOGV("releaseBuffer: slot=%d", id);
- if (mIsPersistent) {
- mConsumer->detachBuffer(id);
- mBufferSlot[id] = NULL;
-
- if (mConsumer->attachBuffer(&id, buffer) == OK) {
- mConsumer->releaseBuffer(
- id, 0, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
- }
- } else {
- mConsumer->releaseBuffer(
- id, frameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
- }
- id = -1; // invalidate id
+ mConsumer->releaseBuffer(
+ id, frameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
mNumBufferAcquired--;
}
@@ -968,7 +714,7 @@
ALOGV("onFrameAvailable exec=%d avail=%zu",
mExecuting, mNumFramesAvailable);
- if (mEndOfStream || mSuspended) {
+ if (mOMXNode == NULL || mEndOfStream || mSuspended) {
if (mEndOfStream) {
// This should only be possible if a new buffer was queued after
// EOS was signaled, i.e. the app is misbehaving.
@@ -979,20 +725,11 @@
}
BufferItem item;
- status_t err = mConsumer->acquireBuffer(&item, 0);
+ status_t err = acquireBuffer(&item);
if (err == OK) {
- mNumBufferAcquired++;
-
- // If this is the first time we're seeing this buffer, add it to our
- // slot table.
- if (item.mGraphicBuffer != NULL) {
- ALOGV("onFrameAvailable: setting mBufferSlot %d", item.mSlot);
- mBufferSlot[item.mSlot] = item.mGraphicBuffer;
- mBufferUseCount[item.mSlot] = 0;
- }
-
- releaseBuffer(item.mSlot, item.mFrameNumber,
- item.mGraphicBuffer, item.mFence);
+ releaseBuffer(item.mSlot, item.mFrameNumber, item.mFence);
+ } else {
+ ALOGE("onFrameAvailable: acquireBuffer returned err=%d", err);
}
return;
}
@@ -1021,6 +758,18 @@
for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
if ((slotMask & 0x01) != 0) {
+ // Last buffer (if set) is always acquired even if its use count
+ // is 0, because we could have skipped that frame but kept it for
+ // repeating. Otherwise a buffer is only acquired if use count>0.
+ if (mBufferSlot[i] != NULL &&
+ (mBufferUseCount[i] > 0 || mLatestBufferId == i)) {
+ ALOGV("releasing acquired buffer: slot=%d, useCount=%d, latest=%d",
+ i, mBufferUseCount[i], mLatestBufferId);
+ mNumBufferAcquired--;
+ }
+ if (mLatestBufferId == i) {
+ mLatestBufferId = -1;
+ }
mBufferSlot[i] = NULL;
mBufferUseCount[i] = 0;
}
@@ -1033,95 +782,261 @@
ALOG_ASSERT(false, "GraphicBufferSource can't consume sideband streams");
}
-void GraphicBufferSource::setDefaultDataSpace(android_dataspace dataSpace) {
- // no need for mutex as we are not yet running
- ALOGD("setting dataspace: %#x", dataSpace);
- mConsumer->setDefaultBufferDataSpace(dataSpace);
- mLastDataSpace = dataSpace;
+Status GraphicBufferSource::configure(
+ const sp<IOMXNode>& omxNode, int32_t dataSpace) {
+ if (omxNode == NULL) {
+ return Status::fromServiceSpecificError(BAD_VALUE);
+ }
+
+ // Do setInputSurface() first, the node will try to enable metadata
+ // mode on input, and does necessary error checking. If this fails,
+ // we can't use this input surface on the node.
+ status_t err = omxNode->setInputSurface(this);
+ if (err != NO_ERROR) {
+ ALOGE("Unable to set input surface: %d", err);
+ return Status::fromServiceSpecificError(err);
+ }
+
+ // use consumer usage bits queried from encoder, but always add
+ // HW_VIDEO_ENCODER for backward compatibility.
+ uint32_t consumerUsage;
+ if (omxNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
+ &consumerUsage, sizeof(consumerUsage)) != OK) {
+ consumerUsage = 0;
+ }
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = kPortIndexInput;
+
+ err = omxNode->getParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
+ if (err != NO_ERROR) {
+ ALOGE("Failed to get port definition: %d", err);
+ return Status::fromServiceSpecificError(UNKNOWN_ERROR);
+ }
+
+ // Call setMaxAcquiredBufferCount without lock.
+ // setMaxAcquiredBufferCount could call back to onBuffersReleased
+ // if the buffer count change results in releasing of existing buffers,
+ // which would lead to deadlock.
+ err = mConsumer->setMaxAcquiredBufferCount(def.nBufferCountActual);
+ if (err != NO_ERROR) {
+ ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
+ def.nBufferCountActual, err);
+ return Status::fromServiceSpecificError(err);
+ }
+
+ {
+ Mutex::Autolock autoLock(mMutex);
+ mOMXNode = omxNode;
+
+ err = mConsumer->setDefaultBufferSize(
+ def.format.video.nFrameWidth,
+ def.format.video.nFrameHeight);
+ if (err != NO_ERROR) {
+ ALOGE("Unable to set BQ default buffer size to %ux%u: %d",
+ def.format.video.nFrameWidth,
+ def.format.video.nFrameHeight,
+ err);
+ return Status::fromServiceSpecificError(err);
+ }
+
+ consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
+ mConsumer->setConsumerUsageBits(consumerUsage);
+
+ // Sets the default buffer data space
+ ALOGD("setting dataspace: %#x, acquired=%d", dataSpace, mNumBufferAcquired);
+ mConsumer->setDefaultBufferDataSpace((android_dataspace)dataSpace);
+ mLastDataSpace = (android_dataspace)dataSpace;
+
+ mExecuting = false;
+ mSuspended = false;
+ mEndOfStream = false;
+ mEndOfStreamSent = false;
+ mMaxTimestampGapUs = -1ll;
+ mPrevOriginalTimeUs = -1ll;
+ mPrevModifiedTimeUs = -1ll;
+ mSkipFramesBeforeNs = -1ll;
+ mRepeatAfterUs = -1ll;
+ mRepeatLastFrameGeneration = 0;
+ mRepeatLastFrameTimestamp = -1ll;
+ mRepeatLastFrameCount = 0;
+ mLatestBufferId = -1;
+ mLatestBufferFrameNum = 0;
+ mLatestBufferFence = Fence::NO_FENCE;
+ mRepeatBufferDeferred = false;
+ mTimePerCaptureUs = -1ll;
+ mTimePerFrameUs = -1ll;
+ mPrevCaptureUs = -1ll;
+ mPrevFrameUs = -1ll;
+ mInputBufferTimeOffsetUs = 0;
+ }
+
+ return Status::ok();
}
-status_t GraphicBufferSource::setRepeatPreviousFrameDelayUs(
- int64_t repeatAfterUs) {
+Status GraphicBufferSource::setSuspend(bool suspend) {
+ ALOGV("setSuspend=%d", suspend);
+
+ Mutex::Autolock autoLock(mMutex);
+
+ if (suspend) {
+ mSuspended = true;
+
+ while (mNumFramesAvailable > 0) {
+ BufferItem item;
+ status_t err = acquireBuffer(&item);
+
+ if (err != OK) {
+ ALOGE("setSuspend: acquireBuffer returned err=%d", err);
+ break;
+ }
+
+ --mNumFramesAvailable;
+
+ releaseBuffer(item.mSlot, item.mFrameNumber, item.mFence);
+ }
+ return Status::ok();
+ }
+
+ mSuspended = false;
+
+ if (mExecuting && mNumFramesAvailable == 0 && mRepeatBufferDeferred) {
+ if (repeatLatestBuffer_l()) {
+ ALOGV("suspend/deferred repeatLatestBuffer_l SUCCESS");
+
+ mRepeatBufferDeferred = false;
+ } else {
+ ALOGV("suspend/deferred repeatLatestBuffer_l FAILURE");
+ }
+ }
+ return Status::ok();
+}
+
+Status GraphicBufferSource::setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) {
+ ALOGV("setRepeatPreviousFrameDelayUs: delayUs=%lld", (long long)repeatAfterUs);
+
Mutex::Autolock autoLock(mMutex);
if (mExecuting || repeatAfterUs <= 0ll) {
- return INVALID_OPERATION;
+ return Status::fromServiceSpecificError(INVALID_OPERATION);
}
mRepeatAfterUs = repeatAfterUs;
-
- return OK;
+ return Status::ok();
}
-status_t GraphicBufferSource::setMaxTimestampGapUs(int64_t maxGapUs) {
+Status GraphicBufferSource::setMaxTimestampGapUs(int64_t maxGapUs) {
+ ALOGV("setMaxTimestampGapUs: maxGapUs=%lld", (long long)maxGapUs);
+
Mutex::Autolock autoLock(mMutex);
if (mExecuting || maxGapUs <= 0ll) {
- return INVALID_OPERATION;
+ return Status::fromServiceSpecificError(INVALID_OPERATION);
}
mMaxTimestampGapUs = maxGapUs;
- return OK;
+ return Status::ok();
}
-status_t GraphicBufferSource::setInputBufferTimeOffset(int64_t timeOffsetUs) {
+Status GraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
Mutex::Autolock autoLock(mMutex);
// timeOffsetUs must be negative for adjustment.
if (timeOffsetUs >= 0ll) {
- return INVALID_OPERATION;
+ return Status::fromServiceSpecificError(INVALID_OPERATION);
}
mInputBufferTimeOffsetUs = timeOffsetUs;
- return OK;
+ return Status::ok();
}
-status_t GraphicBufferSource::setMaxFps(float maxFps) {
+Status GraphicBufferSource::setMaxFps(float maxFps) {
+ ALOGV("setMaxFps: maxFps=%lld", (long long)maxFps);
+
Mutex::Autolock autoLock(mMutex);
if (mExecuting) {
- return INVALID_OPERATION;
+ return Status::fromServiceSpecificError(INVALID_OPERATION);
}
mFrameDropper = new FrameDropper();
status_t err = mFrameDropper->setMaxFrameRate(maxFps);
if (err != OK) {
mFrameDropper.clear();
- return err;
+ return Status::fromServiceSpecificError(err);
}
- return OK;
+ return Status::ok();
}
-void GraphicBufferSource::setSkipFramesBeforeUs(int64_t skipFramesBeforeUs) {
+Status GraphicBufferSource::setStartTimeUs(int64_t skipFramesBeforeUs) {
+ ALOGV("setStartTimeUs: skipFramesBeforeUs=%lld", (long long)skipFramesBeforeUs);
+
Mutex::Autolock autoLock(mMutex);
mSkipFramesBeforeNs =
(skipFramesBeforeUs > 0) ? (skipFramesBeforeUs * 1000) : -1ll;
+
+ return Status::ok();
}
-status_t GraphicBufferSource::setTimeLapseConfig(const TimeLapseConfig &config) {
+Status GraphicBufferSource::setTimeLapseConfig(int64_t timePerFrameUs, int64_t timePerCaptureUs) {
+ ALOGV("setTimeLapseConfig: timePerFrameUs=%lld, timePerCaptureUs=%lld",
+ (long long)timePerFrameUs, (long long)timePerCaptureUs);
+
Mutex::Autolock autoLock(mMutex);
- if (mExecuting || config.mTimePerFrameUs <= 0ll || config.mTimePerCaptureUs <= 0ll) {
- return INVALID_OPERATION;
+ if (mExecuting || timePerFrameUs <= 0ll || timePerCaptureUs <= 0ll) {
+ return Status::fromServiceSpecificError(INVALID_OPERATION);
}
- mTimePerFrameUs = config.mTimePerFrameUs;
- mTimePerCaptureUs = config.mTimePerCaptureUs;
+ mTimePerFrameUs = timePerFrameUs;
+ mTimePerCaptureUs = timePerCaptureUs;
- return OK;
+ return Status::ok();
}
-void GraphicBufferSource::setColorAspects(const ColorAspects &aspects) {
+Status GraphicBufferSource::setColorAspects(int32_t aspectsPacked) {
Mutex::Autolock autoLock(mMutex);
- mColorAspects = aspects;
+ mColorAspects = ColorUtils::unpackToColorAspects(aspectsPacked);
ALOGD("requesting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s))",
- aspects.mRange, asString(aspects.mRange),
- aspects.mPrimaries, asString(aspects.mPrimaries),
- aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs),
- aspects.mTransfer, asString(aspects.mTransfer));
+ mColorAspects.mRange, asString(mColorAspects.mRange),
+ mColorAspects.mPrimaries, asString(mColorAspects.mPrimaries),
+ mColorAspects.mMatrixCoeffs, asString(mColorAspects.mMatrixCoeffs),
+ mColorAspects.mTransfer, asString(mColorAspects.mTransfer));
+
+ return Status::ok();
+}
+
+Status GraphicBufferSource::signalEndOfInputStream() {
+ Mutex::Autolock autoLock(mMutex);
+ ALOGV("signalEndOfInputStream: exec=%d avail=%zu eos=%d",
+ mExecuting, mNumFramesAvailable, mEndOfStream);
+
+ if (mEndOfStream) {
+ ALOGE("EOS was already signaled");
+ return Status::fromStatusT(INVALID_OPERATION);
+ }
+
+ // Set the end-of-stream flag. If no frames are pending from the
+ // BufferQueue, and a codec buffer is available, and we're executing,
+ // we initiate the EOS from here. Otherwise, we'll let
+ // codecBufferEmptied() (or omxExecuting) do it.
+ //
+ // Note: if there are no pending frames and all codec buffers are
+ // available, we *must* submit the EOS from here or we'll just
+ // stall since no future events are expected.
+ mEndOfStream = true;
+
+ if (mExecuting && mNumFramesAvailable == 0) {
+ submitEndOfInputStream_l();
+ }
+
+ return Status::ok();
}
void GraphicBufferSource::onMessageReceived(const sp<AMessage> &msg) {
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h
index aa4ceb3..045a86a 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/GraphicBufferSource.h
@@ -22,15 +22,20 @@
#include <gui/BufferQueue.h>
#include <utils/RefBase.h>
-#include <OMX_Core.h>
#include <VideoAPI.h>
-#include "../include/OMXNodeInstance.h"
+#include <media/IOMX.h>
+#include <media/OMXFenceParcelable.h>
#include <media/stagefright/foundation/ABase.h>
#include <media/stagefright/foundation/AHandlerReflector.h>
#include <media/stagefright/foundation/ALooper.h>
+#include <android/BnGraphicBufferSource.h>
+#include <android/BnOMXBufferSource.h>
+
namespace android {
+using ::android::binder::Status;
+
struct FrameDropper;
/*
@@ -49,16 +54,11 @@
* before the codec is in the "executing" state, so we need to queue
* things up until we're ready to go.
*/
-class GraphicBufferSource : public BufferQueue::ConsumerListener {
+class GraphicBufferSource : public BnGraphicBufferSource,
+ public BnOMXBufferSource,
+ public BufferQueue::ConsumerListener {
public:
- GraphicBufferSource(
- OMXNodeInstance* nodeInstance,
- uint32_t bufferWidth,
- uint32_t bufferHeight,
- uint32_t bufferCount,
- uint32_t consumerUsage,
- const sp<IGraphicBufferConsumer> &consumer = NULL
- );
+ GraphicBufferSource();
virtual ~GraphicBufferSource();
@@ -74,44 +74,42 @@
return mProducer;
}
- // Sets the default buffer data space
- void setDefaultDataSpace(android_dataspace dataSpace);
-
// This is called when OMX transitions to OMX_StateExecuting, which means
// we can start handing it buffers. If we already have buffers of data
// sitting in the BufferQueue, this will send them to the codec.
- void omxExecuting();
+ Status onOmxExecuting() override;
// This is called when OMX transitions to OMX_StateIdle, indicating that
// the codec is meant to return all buffers back to the client for them
// to be freed. Do NOT submit any more buffers to the component.
- void omxIdle();
+ Status onOmxIdle() override;
// This is called when OMX transitions to OMX_StateLoaded, indicating that
// we are shutting down.
- void omxLoaded();
+ Status onOmxLoaded() override;
// A "codec buffer", i.e. a buffer that can be used to pass data into
// the encoder, has been allocated. (This call does not call back into
// OMXNodeInstance.)
- void addCodecBuffer(OMX_BUFFERHEADERTYPE* header);
+ Status onInputBufferAdded(int32_t bufferID) override;
// Called from OnEmptyBufferDone. If we have a BQ buffer available,
// fill it with a new frame of data; otherwise, just mark it as available.
- void codecBufferEmptied(OMX_BUFFERHEADERTYPE* header, int fenceFd);
+ Status onInputBufferEmptied(
+ int32_t bufferID, const OMXFenceParcelable& fenceParcel) override;
- // Called when omx_message::FILL_BUFFER_DONE is received. (Currently the
- // buffer source will fix timestamp in the header if needed.)
- void codecBufferFilled(OMX_BUFFERHEADERTYPE* header);
+ // Configure the buffer source to be used with an OMX node with the default
+ // data space.
+ Status configure(const sp<IOMXNode>& omxNode, int32_t dataSpace) override;
// This is called after the last input frame has been submitted. We
// need to submit an empty buffer with the EOS flag set. If we don't
// have a codec buffer ready, we just set the mEndOfStream flag.
- status_t signalEndOfInputStream();
+ Status signalEndOfInputStream() override;
// If suspend is true, all incoming buffers (including those currently
// in the BufferQueue) will be discarded until the suspension is lifted.
- void suspend(bool suspend);
+ Status setSuspend(bool suspend) override;
// Specifies the interval after which we requeue the buffer previously
// queued to the encoder. This is useful in the case of surface flinger
@@ -120,7 +118,7 @@
// the decoder on the remote end would be unable to decode the latest frame.
// This API must be called before transitioning the encoder to "executing"
// state and once this behaviour is specified it cannot be reset.
- status_t setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs);
+ Status setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) override;
// When set, the timestamp fed to the encoder will be modified such that
// the gap between two adjacent frames is capped at maxGapUs. Timestamp
@@ -129,31 +127,26 @@
// This is to solve a problem in certain real-time streaming case, where
// encoder's rate control logic produces huge frames after a long period
// of suspension on input.
- status_t setMaxTimestampGapUs(int64_t maxGapUs);
+ Status setMaxTimestampGapUs(int64_t maxGapUs) override;
// Sets the input buffer timestamp offset.
// When set, the sample's timestamp will be adjusted with the timeOffsetUs.
- status_t setInputBufferTimeOffset(int64_t timeOffsetUs);
+ Status setTimeOffsetUs(int64_t timeOffsetUs) override;
// When set, the max frame rate fed to the encoder will be capped at maxFps.
- status_t setMaxFps(float maxFps);
-
- struct TimeLapseConfig {
- int64_t mTimePerFrameUs; // the time (us) between two frames for playback
- int64_t mTimePerCaptureUs; // the time (us) between two frames for capture
- };
+ Status setMaxFps(float maxFps) override;
// Sets the time lapse (or slow motion) parameters.
// When set, the sample's timestamp will be modified to playback framerate,
// and capture timestamp will be modified to capture rate.
- status_t setTimeLapseConfig(const TimeLapseConfig &config);
+ Status setTimeLapseConfig(int64_t timePerFrameUs, int64_t timePerCaptureUs) override;
// Sets the start time us (in system time), samples before which should
// be dropped and not submitted to encoder
- void setSkipFramesBeforeUs(int64_t startTimeUs);
+ Status setStartTimeUs(int64_t startTimeUs) override;
// Sets the desired color aspects, e.g. to be used when producer does not specify a dataspace.
- void setColorAspects(const ColorAspects &aspects);
+ Status setColorAspects(int32_t aspectsPacked) override;
protected:
// BufferQueue::ConsumerListener interface, called when a new frame of
@@ -162,48 +155,24 @@
// into the codec buffer, and call Empty[This]Buffer. If we're not yet
// executing or there's no codec buffer available, we just increment
// mNumFramesAvailable and return.
- virtual void onFrameAvailable(const BufferItem& item);
+ void onFrameAvailable(const BufferItem& item) override;
// BufferQueue::ConsumerListener interface, called when the client has
// released one or more GraphicBuffers. We clear out the appropriate
// set of mBufferSlot entries.
- virtual void onBuffersReleased();
+ void onBuffersReleased() override;
// BufferQueue::ConsumerListener interface, called when the client has
// changed the sideband stream. GraphicBufferSource doesn't handle sideband
// streams so this is a no-op (and should never be called).
- virtual void onSidebandStreamChanged();
+ void onSidebandStreamChanged() override;
private:
- // PersistentProxyListener is similar to BufferQueue::ProxyConsumerListener
- // except that it returns (acquire/detach/re-attache/release) buffers
- // in onFrameAvailable() if the actual consumer object is no longer valid.
- //
- // This class is used in persistent input surface case to prevent buffer
- // loss when onFrameAvailable() is received while we don't have a valid
- // consumer around.
- class PersistentProxyListener : public BnConsumerListener {
- public:
- PersistentProxyListener(
- const wp<IGraphicBufferConsumer> &consumer,
- const wp<ConsumerListener>& consumerListener);
- virtual ~PersistentProxyListener();
- virtual void onFrameAvailable(const BufferItem& item) override;
- virtual void onFrameReplaced(const BufferItem& item) override;
- virtual void onBuffersReleased() override;
- virtual void onSidebandStreamChanged() override;
- private:
- // mConsumerListener is a weak reference to the IConsumerListener.
- wp<ConsumerListener> mConsumerListener;
- // mConsumer is a weak reference to the IGraphicBufferConsumer, use
- // a weak ref to avoid circular ref between mConsumer and this class
- wp<IGraphicBufferConsumer> mConsumer;
- };
// Keep track of codec input buffers. They may either be available
// (mGraphicBuffer == NULL) or in use by the codec.
struct CodecBuffer {
- OMX_BUFFERHEADERTYPE* mHeader;
+ IOMX::buffer_id mBufferID;
// buffer producer's frame-number for buffer
uint64_t mFrameNumber;
@@ -224,7 +193,7 @@
}
// Finds the mCodecBuffers entry that matches. Returns -1 if not found.
- int findMatchingCodecBuffer_l(const OMX_BUFFERHEADERTYPE* header);
+ int findMatchingCodecBuffer_l(IOMX::buffer_id bufferID);
// Fills a codec buffer with a frame from the BufferQueue. This must
// only be called when we know that a frame of data is ready (i.e. we're
@@ -243,14 +212,15 @@
// doing anything if we don't have a codec buffer available.
void submitEndOfInputStream_l();
- // Release buffer to the consumer
- void releaseBuffer(
- int &id, uint64_t frameNum,
- const sp<GraphicBuffer> buffer, const sp<Fence> &fence);
+ // Acquire buffer from the consumer
+ status_t acquireBuffer(BufferItem *bi);
- void setLatestBuffer_l(const BufferItem &item, bool dropped);
+ // Release buffer to the consumer
+ void releaseBuffer(int id, uint64_t frameNum, const sp<Fence> &fence);
+
+ void setLatestBuffer_l(const BufferItem &item);
bool repeatLatestBuffer_l();
- int64_t getTimestamp(const BufferItem &item);
+ bool getTimestamp(const BufferItem &item, int64_t *timeUs, int64_t *codecTimeUs);
// called when the data space of the input buffer changes
void onDataSpaceChanged_l(android_dataspace dataSpace, android_pixel_format pixelFormat);
@@ -261,8 +231,8 @@
// Used to report constructor failure.
status_t mInitCheck;
- // Pointer back to the object that contains us. We send buffers here.
- OMXNodeInstance* mNodeInstance;
+ // Pointer back to the IOMXNode that created us. We send buffers here.
+ sp<IOMXNode> mOMXNode;
// Set by omxExecuting() / omxIdling().
bool mExecuting;
@@ -275,7 +245,6 @@
// Our BufferQueue interfaces. mProducer is passed to the producer through
// getIGraphicBufferProducer, and mConsumer is used internally to retrieve
// the buffers queued by the producer.
- bool mIsPersistent;
sp<IGraphicBufferProducer> mProducer;
sp<IGraphicBufferConsumer> mConsumer;
@@ -310,7 +279,6 @@
kRepeatLastFrameCount = 10,
};
- KeyedVector<int64_t, int64_t> mOriginalTimeUs;
int64_t mMaxTimestampGapUs;
int64_t mPrevOriginalTimeUs;
int64_t mPrevModifiedTimeUs;
@@ -342,7 +310,6 @@
int64_t mInputBufferTimeOffsetUs;
- MetadataBufferType mMetadataBufferType;
ColorAspects mColorAspects;
void onMessageReceived(const sp<AMessage> &msg);
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index f7058d7..7907c62 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -26,149 +26,19 @@
#include "../include/OMXNodeInstance.h"
-#include <binder/IMemory.h>
#include <media/stagefright/foundation/ADebug.h>
-#include <utils/threads.h>
+#include "GraphicBufferSource.h"
#include "OMXMaster.h"
#include "OMXUtils.h"
-#include <OMX_AsString.h>
-#include <OMX_Component.h>
-#include <OMX_VideoExt.h>
-
namespace android {
// node ids are created by concatenating the pid with a 16-bit counter
static size_t kMaxNodeInstances = (1 << 16);
-////////////////////////////////////////////////////////////////////////////////
-
-// This provides the underlying Thread used by CallbackDispatcher.
-// Note that deriving CallbackDispatcher from Thread does not work.
-
-struct OMX::CallbackDispatcherThread : public Thread {
- explicit CallbackDispatcherThread(CallbackDispatcher *dispatcher)
- : mDispatcher(dispatcher) {
- }
-
-private:
- CallbackDispatcher *mDispatcher;
-
- bool threadLoop();
-
- CallbackDispatcherThread(const CallbackDispatcherThread &);
- CallbackDispatcherThread &operator=(const CallbackDispatcherThread &);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-struct OMX::CallbackDispatcher : public RefBase {
- explicit CallbackDispatcher(OMXNodeInstance *owner);
-
- // Posts |msg| to the listener's queue. If |realTime| is true, the listener thread is notified
- // that a new message is available on the queue. Otherwise, the message stays on the queue, but
- // the listener is not notified of it. It will process this message when a subsequent message
- // is posted with |realTime| set to true.
- void post(const omx_message &msg, bool realTime = true);
-
- bool loop();
-
-protected:
- virtual ~CallbackDispatcher();
-
-private:
- Mutex mLock;
-
- OMXNodeInstance *mOwner;
- bool mDone;
- Condition mQueueChanged;
- std::list<omx_message> mQueue;
-
- sp<CallbackDispatcherThread> mThread;
-
- void dispatch(std::list<omx_message> &messages);
-
- CallbackDispatcher(const CallbackDispatcher &);
- CallbackDispatcher &operator=(const CallbackDispatcher &);
-};
-
-OMX::CallbackDispatcher::CallbackDispatcher(OMXNodeInstance *owner)
- : mOwner(owner),
- mDone(false) {
- mThread = new CallbackDispatcherThread(this);
- mThread->run("OMXCallbackDisp", ANDROID_PRIORITY_FOREGROUND);
-}
-
-OMX::CallbackDispatcher::~CallbackDispatcher() {
- {
- Mutex::Autolock autoLock(mLock);
-
- mDone = true;
- mQueueChanged.signal();
- }
-
- // A join on self can happen if the last ref to CallbackDispatcher
- // is released within the CallbackDispatcherThread loop
- status_t status = mThread->join();
- if (status != WOULD_BLOCK) {
- // Other than join to self, the only other error return codes are
- // whatever readyToRun() returns, and we don't override that
- CHECK_EQ(status, (status_t)NO_ERROR);
- }
-}
-
-void OMX::CallbackDispatcher::post(const omx_message &msg, bool realTime) {
- Mutex::Autolock autoLock(mLock);
-
- mQueue.push_back(msg);
- if (realTime) {
- mQueueChanged.signal();
- }
-}
-
-void OMX::CallbackDispatcher::dispatch(std::list<omx_message> &messages) {
- if (mOwner == NULL) {
- ALOGV("Would have dispatched a message to a node that's already gone.");
- return;
- }
- mOwner->onMessages(messages);
-}
-
-bool OMX::CallbackDispatcher::loop() {
- for (;;) {
- std::list<omx_message> messages;
-
- {
- Mutex::Autolock autoLock(mLock);
- while (!mDone && mQueue.empty()) {
- mQueueChanged.wait(mLock);
- }
-
- if (mDone) {
- break;
- }
-
- messages.swap(mQueue);
- }
-
- dispatch(messages);
- }
-
- return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-bool OMX::CallbackDispatcherThread::threadLoop() {
- return mDispatcher->loop();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
OMX::OMX()
- : mMaster(new OMXMaster),
- mNodeCounter(0) {
+ : mMaster(new OMXMaster) {
}
OMX::~OMX() {
@@ -177,7 +47,7 @@
}
void OMX::binderDied(const wp<IBinder> &the_late_who) {
- OMXNodeInstance *instance;
+ sp<OMXNodeInstance> instance;
{
Mutex::Autolock autoLock(mLock);
@@ -192,24 +62,9 @@
instance = mLiveNodes.editValueAt(index);
mLiveNodes.removeItemsAt(index);
-
- index = mDispatchers.indexOfKey(instance->nodeID());
- CHECK(index >= 0);
- mDispatchers.removeItemsAt(index);
-
- invalidateNodeID_l(instance->nodeID());
}
- instance->onObserverDied(mMaster);
-}
-
-bool OMX::isSecure(node_id node) {
- OMXNodeInstance *instance = findInstance(node);
- return (instance == NULL ? false : instance->isSecure());
-}
-
-bool OMX::livesLocally(node_id /* node */, pid_t pid) {
- return pid == getpid();
+ instance->onObserverDied();
}
status_t OMX::listNodes(List<ComponentInfo> *list) {
@@ -242,48 +97,38 @@
status_t OMX::allocateNode(
const char *name, const sp<IOMXObserver> &observer,
- sp<IBinder> *nodeBinder, node_id *node) {
+ sp<IOMXNode> *omxNode) {
Mutex::Autolock autoLock(mLock);
- *node = 0;
- if (nodeBinder != NULL) {
- *nodeBinder = NULL;
- }
+ omxNode->clear();
- if (mNodeIDToInstance.size() == kMaxNodeInstances) {
- // all possible node IDs are in use
+ if (mLiveNodes.size() == kMaxNodeInstances) {
return NO_MEMORY;
}
- OMXNodeInstance *instance = new OMXNodeInstance(this, observer, name);
+ sp<OMXNodeInstance> instance = new OMXNodeInstance(this, observer, name);
OMX_COMPONENTTYPE *handle;
OMX_ERRORTYPE err = mMaster->makeComponentInstance(
name, &OMXNodeInstance::kCallbacks,
- instance, &handle);
+ instance.get(), &handle);
if (err != OMX_ErrorNone) {
ALOGE("FAILED to allocate omx component '%s' err=%s(%#x)", name, asString(err), err);
- instance->onGetHandleFailed();
-
return StatusFromOMXError(err);
}
-
- *node = makeNodeID_l(instance);
- mDispatchers.add(*node, new CallbackDispatcher(instance));
-
- instance->setHandle(*node, handle);
+ instance->setHandle(handle);
mLiveNodes.add(IInterface::asBinder(observer), instance);
IInterface::asBinder(observer)->linkToDeath(this);
+ *omxNode = instance;
+
return OK;
}
-status_t OMX::freeNode(node_id node) {
- OMXNodeInstance *instance = findInstance(node);
-
+status_t OMX::freeNode(const sp<OMXNodeInstance> &instance) {
if (instance == NULL) {
return OK;
}
@@ -301,466 +146,35 @@
IInterface::asBinder(instance->observer())->unlinkToDeath(this);
- status_t err = instance->freeNode(mMaster);
-
- {
- Mutex::Autolock autoLock(mLock);
- ssize_t index = mDispatchers.indexOfKey(node);
- CHECK(index >= 0);
- mDispatchers.removeItemsAt(index);
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+ if (instance->handle() != NULL) {
+ err = mMaster->destroyComponentInstance(
+ static_cast<OMX_COMPONENTTYPE *>(instance->handle()));
}
- return err;
-}
-
-status_t OMX::sendCommand(
- node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->sendCommand(cmd, param);
-}
-
-status_t OMX::getParameter(
- node_id node, OMX_INDEXTYPE index,
- void *params, size_t size) {
- ALOGV("getParameter(%u %#x %p %zd)", node, index, params, size);
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->getParameter(
- index, params, size);
-}
-
-status_t OMX::setParameter(
- node_id node, OMX_INDEXTYPE index,
- const void *params, size_t size) {
- ALOGV("setParameter(%u %#x %p %zd)", node, index, params, size);
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->setParameter(
- index, params, size);
-}
-
-status_t OMX::getConfig(
- node_id node, OMX_INDEXTYPE index,
- void *params, size_t size) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->getConfig(
- index, params, size);
-}
-
-status_t OMX::setConfig(
- node_id node, OMX_INDEXTYPE index,
- const void *params, size_t size) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->setConfig(
- index, params, size);
-}
-
-status_t OMX::getState(
- node_id node, OMX_STATETYPE* state) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->getState(
- state);
-}
-
-status_t OMX::enableNativeBuffers(
- node_id node, OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->enableNativeBuffers(port_index, graphic, enable);
-}
-
-status_t OMX::getGraphicBufferUsage(
- node_id node, OMX_U32 port_index, OMX_U32* usage) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->getGraphicBufferUsage(port_index, usage);
-}
-
-status_t OMX::storeMetaDataInBuffers(
- node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->storeMetaDataInBuffers(port_index, enable, type);
-}
-
-status_t OMX::prepareForAdaptivePlayback(
- node_id node, OMX_U32 portIndex, OMX_BOOL enable,
- OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->prepareForAdaptivePlayback(
- portIndex, enable, maxFrameWidth, maxFrameHeight);
-}
-
-status_t OMX::configureVideoTunnelMode(
- node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
- OMX_U32 audioHwSync, native_handle_t **sidebandHandle) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->configureVideoTunnelMode(
- portIndex, tunneled, audioHwSync, sidebandHandle);
-}
-
-status_t OMX::useBuffer(
- node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
- buffer_id *buffer, OMX_U32 allottedSize) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->useBuffer(
- port_index, params, buffer, allottedSize);
-}
-
-status_t OMX::useGraphicBuffer(
- node_id node, OMX_U32 port_index,
- const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->useGraphicBuffer(
- port_index, graphicBuffer, buffer);
-}
-
-status_t OMX::updateGraphicBufferInMeta(
- node_id node, OMX_U32 port_index,
- const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->updateGraphicBufferInMeta(
- port_index, graphicBuffer, buffer);
-}
-
-status_t OMX::updateNativeHandleInMeta(
- node_id node, OMX_U32 port_index,
- const sp<NativeHandle> &nativeHandle, buffer_id buffer) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->updateNativeHandleInMeta(
- port_index, nativeHandle, buffer);
+ return StatusFromOMXError(err);
}
status_t OMX::createInputSurface(
- node_id node, OMX_U32 port_index, android_dataspace dataSpace,
- sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->createInputSurface(
- port_index, dataSpace, bufferProducer, type);
-}
-
-status_t OMX::createPersistentInputSurface(
sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferConsumer> *bufferConsumer) {
- return OMXNodeInstance::createPersistentInputSurface(
- bufferProducer, bufferConsumer);
-}
-
-status_t OMX::setInputSurface(
- node_id node, OMX_U32 port_index,
- const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
+ sp<IGraphicBufferSource> *bufferSource) {
+ if (bufferProducer == NULL || bufferSource == NULL) {
+ ALOGE("b/25884056");
+ return BAD_VALUE;
}
- return instance->setInputSurface(port_index, bufferConsumer, type);
-}
-
-
-status_t OMX::signalEndOfInputStream(node_id node) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
+ sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource();
+ status_t err = graphicBufferSource->initCheck();
+ if (err != OK) {
+ ALOGE("Failed to create persistent input surface: %s (%d)",
+ strerror(-err), err);
+ return err;
}
- return instance->signalEndOfInputStream();
-}
+ *bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
+ *bufferSource = graphicBufferSource;
-status_t OMX::allocateSecureBuffer(
- node_id node, OMX_U32 port_index, size_t size,
- buffer_id *buffer, void **buffer_data, sp<NativeHandle> *native_handle) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->allocateSecureBuffer(
- port_index, size, buffer, buffer_data, native_handle);
-}
-
-status_t OMX::allocateBufferWithBackup(
- node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
- buffer_id *buffer, OMX_U32 allottedSize) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->allocateBufferWithBackup(
- port_index, params, buffer, allottedSize);
-}
-
-status_t OMX::freeBuffer(node_id node, OMX_U32 port_index, buffer_id buffer) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->freeBuffer(
- port_index, buffer);
-}
-
-status_t OMX::fillBuffer(node_id node, buffer_id buffer, int fenceFd) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->fillBuffer(buffer, fenceFd);
-}
-
-status_t OMX::emptyBuffer(
- node_id node,
- buffer_id buffer,
- OMX_U32 range_offset, OMX_U32 range_length,
- OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->emptyBuffer(
- buffer, range_offset, range_length, flags, timestamp, fenceFd);
-}
-
-status_t OMX::getExtensionIndex(
- node_id node,
- const char *parameter_name,
- OMX_INDEXTYPE *index) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->getExtensionIndex(
- parameter_name, index);
-}
-
-status_t OMX::setInternalOption(
- node_id node,
- OMX_U32 port_index,
- InternalOptionType type,
- const void *data,
- size_t size) {
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return NAME_NOT_FOUND;
- }
-
- return instance->setInternalOption(port_index, type, data, size);
-}
-
-OMX_ERRORTYPE OMX::OnEvent(
- node_id node,
- OMX_IN OMX_EVENTTYPE eEvent,
- OMX_IN OMX_U32 nData1,
- OMX_IN OMX_U32 nData2,
- OMX_IN OMX_PTR pEventData) {
- ALOGV("OnEvent(%d, %" PRIu32", %" PRIu32 ")", eEvent, nData1, nData2);
- OMXNodeInstance *instance = findInstance(node);
-
- if (instance == NULL) {
- return OMX_ErrorComponentNotFound;
- }
-
- // Forward to OMXNodeInstance.
- instance->onEvent(eEvent, nData1, nData2);
-
- sp<OMX::CallbackDispatcher> dispatcher = findDispatcher(node);
-
- // output rendered events are not processed as regular events until they hit the observer
- if (eEvent == OMX_EventOutputRendered) {
- if (pEventData == NULL) {
- return OMX_ErrorBadParameter;
- }
-
- // process data from array
- OMX_VIDEO_RENDEREVENTTYPE *renderData = (OMX_VIDEO_RENDEREVENTTYPE *)pEventData;
- for (size_t i = 0; i < nData1; ++i) {
- omx_message msg;
- msg.type = omx_message::FRAME_RENDERED;
- msg.node = node;
- msg.fenceFd = -1;
- msg.u.render_data.timestamp = renderData[i].nMediaTimeUs;
- msg.u.render_data.nanoTime = renderData[i].nSystemTimeNs;
-
- dispatcher->post(msg, false /* realTime */);
- }
- return OMX_ErrorNone;
- }
-
- omx_message msg;
- msg.type = omx_message::EVENT;
- msg.node = node;
- msg.fenceFd = -1;
- msg.u.event_data.event = eEvent;
- msg.u.event_data.data1 = nData1;
- msg.u.event_data.data2 = nData2;
-
- dispatcher->post(msg, true /* realTime */);
-
- return OMX_ErrorNone;
-}
-
-OMX_ERRORTYPE OMX::OnEmptyBufferDone(
- node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer, int fenceFd) {
- ALOGV("OnEmptyBufferDone buffer=%p", pBuffer);
-
- omx_message msg;
- msg.type = omx_message::EMPTY_BUFFER_DONE;
- msg.node = node;
- msg.fenceFd = fenceFd;
- msg.u.buffer_data.buffer = buffer;
-
- findDispatcher(node)->post(msg);
-
- return OMX_ErrorNone;
-}
-
-OMX_ERRORTYPE OMX::OnFillBufferDone(
- node_id node, buffer_id buffer, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer, int fenceFd) {
- ALOGV("OnFillBufferDone buffer=%p", pBuffer);
-
- omx_message msg;
- msg.type = omx_message::FILL_BUFFER_DONE;
- msg.node = node;
- msg.fenceFd = fenceFd;
- msg.u.extended_buffer_data.buffer = buffer;
- msg.u.extended_buffer_data.range_offset = pBuffer->nOffset;
- msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen;
- msg.u.extended_buffer_data.flags = pBuffer->nFlags;
- msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp;
-
- findDispatcher(node)->post(msg);
-
- return OMX_ErrorNone;
-}
-
-OMX::node_id OMX::makeNodeID_l(OMXNodeInstance *instance) {
- // mLock is already held.
-
- node_id prefix = node_id(getpid() << 16);
- node_id node = 0;
- do {
- if (++mNodeCounter >= kMaxNodeInstances) {
- mNodeCounter = 0; // OK to use because we're combining with the pid
- }
- node = node_id(prefix | mNodeCounter);
- } while (mNodeIDToInstance.indexOfKey(node) >= 0);
- mNodeIDToInstance.add(node, instance);
-
- return node;
-}
-
-OMXNodeInstance *OMX::findInstance(node_id node) {
- Mutex::Autolock autoLock(mLock);
-
- ssize_t index = mNodeIDToInstance.indexOfKey(node);
-
- return index < 0 ? NULL : mNodeIDToInstance.valueAt(index);
-}
-
-sp<OMX::CallbackDispatcher> OMX::findDispatcher(node_id node) {
- Mutex::Autolock autoLock(mLock);
-
- ssize_t index = mDispatchers.indexOfKey(node);
-
- return index < 0 ? NULL : mDispatchers.valueAt(index);
-}
-
-void OMX::invalidateNodeID(node_id node) {
- Mutex::Autolock autoLock(mLock);
- invalidateNodeID_l(node);
-}
-
-void OMX::invalidateNodeID_l(node_id node) {
- // mLock is held.
- mNodeIDToInstance.removeItem(node);
+ return OK;
}
} // namespace android
diff --git a/media/libstagefright/omx/OMXMaster.cpp b/media/libstagefright/omx/OMXMaster.cpp
index 6132a2c..ac9b0c3 100644
--- a/media/libstagefright/omx/OMXMaster.cpp
+++ b/media/libstagefright/omx/OMXMaster.cpp
@@ -32,26 +32,23 @@
OMXMaster::OMXMaster()
: mVendorLibHandle(NULL) {
- mProcessName[0] = 0;
- if (mProcessName[0] == 0) {
- pid_t pid = getpid();
- char filename[20];
- snprintf(filename, sizeof(filename), "/proc/%d/comm", pid);
- int fd = open(filename, O_RDONLY);
- if (fd < 0) {
- ALOGW("couldn't determine process name");
- sprintf(mProcessName, "<unknown>");
- } else {
- ssize_t len = read(fd, mProcessName, sizeof(mProcessName));
- if (len < 2) {
- ALOGW("couldn't determine process name");
- sprintf(mProcessName, "<unknown>");
- } else {
- // the name is newline terminated, so erase the newline
- mProcessName[len - 1] = 0;
- }
- close(fd);
- }
+ pid_t pid = getpid();
+ char filename[20];
+ snprintf(filename, sizeof(filename), "/proc/%d/comm", pid);
+ int fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ ALOGW("couldn't determine process name");
+ strlcpy(mProcessName, "<unknown>", sizeof(mProcessName));
+ } else {
+ ssize_t len = read(fd, mProcessName, sizeof(mProcessName));
+ if (len < 2) {
+ ALOGW("couldn't determine process name");
+ strlcpy(mProcessName, "<unknown>", sizeof(mProcessName));
+ } else {
+ // the name is newline terminated, so erase the newline
+ mProcessName[len - 1] = 0;
+ }
+ close(fd);
}
addVendorPlugin();
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 8c10310..ef18958 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -23,10 +23,11 @@
#include "../include/OMXNodeInstance.h"
#include "OMXMaster.h"
#include "OMXUtils.h"
-#include "GraphicBufferSource.h"
+#include <android/IOMXBufferSource.h>
#include <OMX_Component.h>
#include <OMX_IndexExt.h>
+#include <OMX_VideoExt.h>
#include <OMX_AsString.h>
#include <binder/IMemory.h>
@@ -35,6 +36,7 @@
#include <HardwareAPI.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/MediaErrors.h>
#include <utils/misc.h>
#include <utils/NativeHandle.h>
@@ -42,19 +44,28 @@
static const OMX_U32 kPortIndexInput = 0;
static const OMX_U32 kPortIndexOutput = 1;
-#define CLOGW(fmt, ...) ALOGW("[%x:%s] " fmt, mNodeID, mName, ##__VA_ARGS__)
+// Quirk still supported, even though deprecated
+enum Quirks {
+ kRequiresAllocateBufferOnInputPorts = 1,
+ kRequiresAllocateBufferOnOutputPorts = 2,
+
+ kQuirksMask = kRequiresAllocateBufferOnInputPorts
+ | kRequiresAllocateBufferOnOutputPorts,
+};
+
+#define CLOGW(fmt, ...) ALOGW("[%p:%s] " fmt, mHandle, mName, ##__VA_ARGS__)
#define CLOG_ERROR_IF(cond, fn, err, fmt, ...) \
- ALOGE_IF(cond, #fn "(%x:%s, " fmt ") ERROR: %s(%#x)", \
- mNodeID, mName, ##__VA_ARGS__, asString(err), err)
+ ALOGE_IF(cond, #fn "(%p:%s, " fmt ") ERROR: %s(%#x)", \
+ mHandle, mName, ##__VA_ARGS__, asString(err), err)
#define CLOG_ERROR(fn, err, fmt, ...) CLOG_ERROR_IF(true, fn, err, fmt, ##__VA_ARGS__)
#define CLOG_IF_ERROR(fn, err, fmt, ...) \
CLOG_ERROR_IF((err) != OMX_ErrorNone, fn, err, fmt, ##__VA_ARGS__)
#define CLOGI_(level, fn, fmt, ...) \
- ALOGI_IF(DEBUG >= (level), #fn "(%x:%s, " fmt ")", mNodeID, mName, ##__VA_ARGS__)
+ ALOGI_IF(DEBUG >= (level), #fn "(%p:%s, " fmt ")", mHandle, mName, ##__VA_ARGS__)
#define CLOGD_(level, fn, fmt, ...) \
- ALOGD_IF(DEBUG >= (level), #fn "(%x:%s, " fmt ")", mNodeID, mName, ##__VA_ARGS__)
+ ALOGD_IF(DEBUG >= (level), #fn "(%p:%s, " fmt ")", mHandle, mName, ##__VA_ARGS__)
#define CLOG_LIFE(fn, fmt, ...) CLOGI_(ADebug::kDebugLifeCycle, fn, fmt, ##__VA_ARGS__)
#define CLOG_STATE(fn, fmt, ...) CLOGI_(ADebug::kDebugState, fn, fmt, ##__VA_ARGS__)
@@ -62,7 +73,7 @@
#define CLOG_INTERNAL(fn, fmt, ...) CLOGD_(ADebug::kDebugInternalState, fn, fmt, ##__VA_ARGS__)
#define CLOG_DEBUG_IF(cond, fn, fmt, ...) \
- ALOGD_IF(cond, #fn "(%x, " fmt ")", mNodeID, ##__VA_ARGS__)
+ ALOGD_IF(cond, #fn "(%p, " fmt ")", mHandle, ##__VA_ARGS__)
#define CLOG_BUFFER(fn, fmt, ...) \
CLOG_DEBUG_IF(DEBUG >= ADebug::kDebugAll, fn, fmt, ##__VA_ARGS__)
@@ -94,18 +105,16 @@
struct BufferMeta {
explicit BufferMeta(
- const sp<IMemory> &mem, OMX_U32 portIndex, bool copyToOmx,
- bool copyFromOmx, OMX_U8 *backup)
+ const sp<IMemory> &mem, OMX_U32 portIndex, bool copy, OMX_U8 *backup)
: mMem(mem),
- mCopyFromOmx(copyFromOmx),
- mCopyToOmx(copyToOmx),
+ mCopyFromOmx(portIndex == kPortIndexOutput && copy),
+ mCopyToOmx(portIndex == kPortIndexInput && copy),
mPortIndex(portIndex),
mBackup(backup) {
}
- explicit BufferMeta(size_t size, OMX_U32 portIndex)
- : mSize(size),
- mCopyFromOmx(false),
+ explicit BufferMeta(OMX_U32 portIndex)
+ : mCopyFromOmx(false),
mCopyToOmx(false),
mPortIndex(portIndex),
mBackup(NULL) {
@@ -125,7 +134,7 @@
}
// check component returns proper range
- sp<ABuffer> codec = getBuffer(header, false /* backup */, true /* limit */);
+ sp<ABuffer> codec = getBuffer(header, true /* limit */);
memcpy((OMX_U8 *)mMem->pointer() + header->nOffset, codec->data(), codec->size());
}
@@ -140,14 +149,9 @@
header->nFilledLen);
}
- // return either the codec or the backup buffer
- sp<ABuffer> getBuffer(const OMX_BUFFERHEADERTYPE *header, bool backup, bool limit) {
- sp<ABuffer> buf;
- if (backup && mMem != NULL) {
- buf = new ABuffer(mMem->pointer(), mMem->size());
- } else {
- buf = new ABuffer(header->pBuffer, header->nAllocLen);
- }
+ // return the codec buffer
+ sp<ABuffer> getBuffer(const OMX_BUFFERHEADERTYPE *header, bool limit) {
+ sp<ABuffer> buf = new ABuffer(header->pBuffer, header->nAllocLen);
if (limit) {
if (header->nOffset + header->nFilledLen > header->nOffset
&& header->nOffset + header->nFilledLen <= header->nAllocLen) {
@@ -179,7 +183,6 @@
sp<GraphicBuffer> mGraphicBuffer;
sp<NativeHandle> mNativeHandle;
sp<IMemory> mMem;
- size_t mSize;
bool mCopyFromOmx;
bool mCopyToOmx;
OMX_U32 mPortIndex;
@@ -203,16 +206,142 @@
}
}
+////////////////////////////////////////////////////////////////////////////////
+
+// This provides the underlying Thread used by CallbackDispatcher.
+// Note that deriving CallbackDispatcher from Thread does not work.
+
+struct OMXNodeInstance::CallbackDispatcherThread : public Thread {
+ explicit CallbackDispatcherThread(CallbackDispatcher *dispatcher)
+ : mDispatcher(dispatcher) {
+ }
+
+private:
+ CallbackDispatcher *mDispatcher;
+
+ bool threadLoop();
+
+ CallbackDispatcherThread(const CallbackDispatcherThread &);
+ CallbackDispatcherThread &operator=(const CallbackDispatcherThread &);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct OMXNodeInstance::CallbackDispatcher : public RefBase {
+ explicit CallbackDispatcher(const sp<OMXNodeInstance> &owner);
+
+ // Posts |msg| to the listener's queue. If |realTime| is true, the listener thread is notified
+ // that a new message is available on the queue. Otherwise, the message stays on the queue, but
+ // the listener is not notified of it. It will process this message when a subsequent message
+ // is posted with |realTime| set to true.
+ void post(const omx_message &msg, bool realTime = true);
+
+ bool loop();
+
+protected:
+ virtual ~CallbackDispatcher();
+
+private:
+ Mutex mLock;
+
+ sp<OMXNodeInstance> const mOwner;
+ bool mDone;
+ Condition mQueueChanged;
+ std::list<omx_message> mQueue;
+
+ sp<CallbackDispatcherThread> mThread;
+
+ void dispatch(std::list<omx_message> &messages);
+
+ CallbackDispatcher(const CallbackDispatcher &);
+ CallbackDispatcher &operator=(const CallbackDispatcher &);
+};
+
+OMXNodeInstance::CallbackDispatcher::CallbackDispatcher(const sp<OMXNodeInstance> &owner)
+ : mOwner(owner),
+ mDone(false) {
+ mThread = new CallbackDispatcherThread(this);
+ mThread->run("OMXCallbackDisp", ANDROID_PRIORITY_FOREGROUND);
+}
+
+OMXNodeInstance::CallbackDispatcher::~CallbackDispatcher() {
+ {
+ Mutex::Autolock autoLock(mLock);
+
+ mDone = true;
+ mQueueChanged.signal();
+ }
+
+ // A join on self can happen if the last ref to CallbackDispatcher
+ // is released within the CallbackDispatcherThread loop
+ status_t status = mThread->join();
+ if (status != WOULD_BLOCK) {
+ // Other than join to self, the only other error return codes are
+ // whatever readyToRun() returns, and we don't override that
+ CHECK_EQ(status, (status_t)NO_ERROR);
+ }
+}
+
+void OMXNodeInstance::CallbackDispatcher::post(const omx_message &msg, bool realTime) {
+ Mutex::Autolock autoLock(mLock);
+
+ mQueue.push_back(msg);
+ if (realTime) {
+ mQueueChanged.signal();
+ }
+}
+
+void OMXNodeInstance::CallbackDispatcher::dispatch(std::list<omx_message> &messages) {
+ if (mOwner == NULL) {
+ ALOGV("Would have dispatched a message to a node that's already gone.");
+ return;
+ }
+ mOwner->onMessages(messages);
+}
+
+bool OMXNodeInstance::CallbackDispatcher::loop() {
+ for (;;) {
+ std::list<omx_message> messages;
+
+ {
+ Mutex::Autolock autoLock(mLock);
+ while (!mDone && mQueue.empty()) {
+ mQueueChanged.wait(mLock);
+ }
+
+ if (mDone) {
+ break;
+ }
+
+ messages.swap(mQueue);
+ }
+
+ dispatch(messages);
+ }
+
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool OMXNodeInstance::CallbackDispatcherThread::threadLoop() {
+ return mDispatcher->loop();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
OMXNodeInstance::OMXNodeInstance(
OMX *owner, const sp<IOMXObserver> &observer, const char *name)
: mOwner(owner),
- mNodeID(0),
mHandle(NULL),
mObserver(observer),
mDying(false),
mSailed(false),
mQueriedProhibitedExtensions(false),
- mBufferIDCount(0)
+ mQuirks(0),
+ mBufferIDCount(0),
+ mShouldRestorePts(false),
+ mRestorePtsFailed(false)
{
mName = ADebug::GetDebugName(name);
DEBUG = ADebug::GetDebugLevelFromProperty(name, "debug.stagefright.omx-debug");
@@ -234,44 +363,42 @@
CHECK(mHandle == NULL);
}
-void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) {
- mNodeID = node_id;
+void OMXNodeInstance::setHandle(OMX_HANDLETYPE handle) {
CLOG_LIFE(allocateNode, "handle=%p", handle);
CHECK(mHandle == NULL);
mHandle = handle;
+ if (handle != NULL) {
+ mDispatcher = new CallbackDispatcher(this);
+ }
}
-sp<GraphicBufferSource> OMXNodeInstance::getGraphicBufferSource() {
- Mutex::Autolock autoLock(mGraphicBufferSourceLock);
- return mGraphicBufferSource;
+sp<IOMXBufferSource> OMXNodeInstance::getBufferSource() {
+ Mutex::Autolock autoLock(mOMXBufferSourceLock);
+ return mOMXBufferSource;
}
-void OMXNodeInstance::setGraphicBufferSource(
- const sp<GraphicBufferSource>& bufferSource) {
- Mutex::Autolock autoLock(mGraphicBufferSourceLock);
- CLOG_INTERNAL(setGraphicBufferSource, "%p", bufferSource.get());
- mGraphicBufferSource = bufferSource;
+void OMXNodeInstance::setBufferSource(const sp<IOMXBufferSource>& bufferSource) {
+ Mutex::Autolock autoLock(mOMXBufferSourceLock);
+ CLOG_INTERNAL(setBufferSource, "%p", bufferSource.get());
+ mOMXBufferSource = bufferSource;
}
-OMX *OMXNodeInstance::owner() {
- return mOwner;
+OMX_HANDLETYPE OMXNodeInstance::handle() {
+ return mHandle;
}
sp<IOMXObserver> OMXNodeInstance::observer() {
return mObserver;
}
-OMX::node_id OMXNodeInstance::nodeID() {
- return mNodeID;
-}
+status_t OMXNodeInstance::freeNode() {
-status_t OMXNodeInstance::freeNode(OMXMaster *master) {
CLOG_LIFE(freeNode, "handle=%p", mHandle);
static int32_t kMaxNumIterations = 10;
// exit if we have already freed the node
if (mHandle == NULL) {
- return OK;
+ return mOwner->freeNode(this);
}
// Transition the node from its current state all the way down
@@ -350,43 +477,35 @@
LOG_ALWAYS_FATAL("unknown state %s(%#x).", asString(state), state);
break;
}
+ status_t err = mOwner->freeNode(this);
- ALOGV("[%x:%s] calling destroyComponentInstance", mNodeID, mName);
- OMX_ERRORTYPE err = master->destroyComponentInstance(
- static_cast<OMX_COMPONENTTYPE *>(mHandle));
+ mDispatcher.clear();
+ mOMXBufferSource.clear();
mHandle = NULL;
CLOG_IF_ERROR(freeNode, err, "");
free(mName);
mName = NULL;
- mOwner->invalidateNodeID(mNodeID);
- mNodeID = 0;
-
ALOGV("OMXNodeInstance going away.");
- delete this;
- return StatusFromOMXError(err);
+ return err;
}
status_t OMXNodeInstance::sendCommand(
OMX_COMMANDTYPE cmd, OMX_S32 param) {
- if (cmd == OMX_CommandStateSet) {
- // There are no configurations past first StateSet command.
- mSailed = true;
- }
- const sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
+ const sp<IOMXBufferSource> bufferSource(getBufferSource());
if (bufferSource != NULL && cmd == OMX_CommandStateSet) {
if (param == OMX_StateIdle) {
// Initiating transition from Executing -> Idle
// ACodec is waiting for all buffers to be returned, do NOT
// submit any more buffers to the codec.
- bufferSource->omxIdle();
+ bufferSource->onOmxIdle();
} else if (param == OMX_StateLoaded) {
// Initiating transition from Idle/Executing -> Loaded
// Buffers are about to be freed.
- bufferSource->omxLoaded();
- setGraphicBufferSource(NULL);
+ bufferSource->onOmxLoaded();
+ setBufferSource(NULL);
}
// fall through
@@ -394,6 +513,11 @@
Mutex::Autolock autoLock(mLock);
+ if (cmd == OMX_CommandStateSet) {
+ // There are no configurations past first StateSet command.
+ mSailed = true;
+ }
+
// bump internal-state debug level for 2 input and output frames past a command
{
Mutex::Autolock _l(mDebugLock);
@@ -520,14 +644,6 @@
return StatusFromOMXError(err);
}
-status_t OMXNodeInstance::getState(OMX_STATETYPE* state) {
- Mutex::Autolock autoLock(mLock);
-
- OMX_ERRORTYPE err = OMX_GetState(mHandle, state);
- CLOG_IF_ERROR(getState, err, "");
- return StatusFromOMXError(err);
-}
-
status_t OMXNodeInstance::enableNativeBuffers(
OMX_U32 portIndex, OMX_BOOL graphic, OMX_BOOL enable) {
if (portIndex >= NELEM(mSecureBufferType)) {
@@ -792,43 +908,64 @@
return BAD_VALUE;
}
- // metadata buffers are not connected cross process
- // use a backup buffer instead of the actual buffer
BufferMeta *buffer_meta;
- bool useBackup = mMetadataType[portIndex] != kMetadataBufferTypeInvalid;
- OMX_U8 *data = static_cast<OMX_U8 *>(params->pointer());
- // allocate backup buffer
- if (useBackup) {
- data = new (std::nothrow) OMX_U8[allottedSize];
- if (data == NULL) {
- return NO_MEMORY;
- }
- memset(data, 0, allottedSize);
+ OMX_BUFFERHEADERTYPE *header;
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+ bool isMetadata = mMetadataType[portIndex] != kMetadataBufferTypeInvalid;
- // if we are not connecting the buffers, the sizes must match
- if (allottedSize != params->size()) {
- CLOG_ERROR(useBuffer, BAD_VALUE, SIMPLE_BUFFER(portIndex, (size_t)allottedSize, data));
- delete[] data;
- return BAD_VALUE;
- }
+ uint32_t requiresAllocateBufferBit =
+ (portIndex == kPortIndexInput)
+ ? kRequiresAllocateBufferOnInputPorts
+ : kRequiresAllocateBufferOnOutputPorts;
+ if (mQuirks & requiresAllocateBufferBit) {
+ // metadata buffers are not connected cross process; only copy if not meta.
buffer_meta = new BufferMeta(
- params, portIndex, false /* copyToOmx */, false /* copyFromOmx */, data);
+ params, portIndex, !isMetadata /* copy */, NULL /* data */);
+
+ err = OMX_AllocateBuffer(
+ mHandle, &header, portIndex, buffer_meta, allottedSize);
+
+ if (err != OMX_ErrorNone) {
+ CLOG_ERROR(allocateBuffer, err,
+ SIMPLE_BUFFER(portIndex, (size_t)allottedSize, params->pointer()));
+ }
} else {
- buffer_meta = new BufferMeta(
- params, portIndex, false /* copyToOmx */, false /* copyFromOmx */, NULL);
+ OMX_U8 *data = static_cast<OMX_U8 *>(params->pointer());
+
+ // metadata buffers are not connected cross process
+ // use a backup buffer instead of the actual buffer
+ if (isMetadata) {
+ // if we are not connecting the buffers, the sizes must match
+ if (allottedSize != params->size()) {
+ CLOG_ERROR(useBuffer, BAD_VALUE, SIMPLE_BUFFER(portIndex, (size_t)allottedSize, data));
+ return BAD_VALUE;
+ }
+
+ data = new (std::nothrow) OMX_U8[allottedSize];
+ if (data == NULL) {
+ return NO_MEMORY;
+ }
+ memset(data, 0, allottedSize);
+
+ buffer_meta = new BufferMeta(
+ params, portIndex, false /* copy */, data);
+ } else {
+ buffer_meta = new BufferMeta(
+ params, portIndex, false /* copy */, NULL);
+ }
+
+ err = OMX_UseBuffer(
+ mHandle, &header, portIndex, buffer_meta,
+ allottedSize, data);
+
+ if (err != OMX_ErrorNone) {
+ CLOG_ERROR(useBuffer, err, SIMPLE_BUFFER(
+ portIndex, (size_t)allottedSize, data));
+ }
}
- OMX_BUFFERHEADERTYPE *header;
-
- OMX_ERRORTYPE err = OMX_UseBuffer(
- mHandle, &header, portIndex, buffer_meta,
- allottedSize, data);
-
if (err != OMX_ErrorNone) {
- CLOG_ERROR(useBuffer, err, SIMPLE_BUFFER(
- portIndex, (size_t)allottedSize, data));
-
delete buffer_meta;
buffer_meta = NULL;
@@ -843,9 +980,9 @@
addActiveBuffer(portIndex, *buffer);
- sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
+ sp<IOMXBufferSource> bufferSource(getBufferSource());
if (bufferSource != NULL && portIndex == kPortIndexInput) {
- bufferSource->addCodecBuffer(header);
+ bufferSource->onInputBufferAdded(*buffer);
}
CLOG_BUFFER(useBuffer, NEW_BUFFER_FMT(
@@ -975,7 +1112,7 @@
status_t OMXNodeInstance::updateGraphicBufferInMeta_l(
OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
- OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header, bool updateCodecBuffer) {
+ OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header) {
// No need to check |graphicBuffer| since NULL is valid for it as below.
if (header == NULL) {
ALOGE("b/25884056");
@@ -987,14 +1124,9 @@
}
BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate);
- sp<ABuffer> data = bufferMeta->getBuffer(
- header, !updateCodecBuffer /* backup */, false /* limit */);
+ sp<ABuffer> data = bufferMeta->getBuffer(header, false /* limit */);
bufferMeta->setGraphicBuffer(graphicBuffer);
MetadataBufferType metaType = mMetadataType[portIndex];
- // we use gralloc source only in the codec buffers
- if (metaType == kMetadataBufferTypeGrallocSource && !updateCodecBuffer) {
- metaType = kMetadataBufferTypeANWBuffer;
- }
if (metaType == kMetadataBufferTypeGrallocSource
&& data->capacity() >= sizeof(VideoGrallocMetadata)) {
VideoGrallocMetadata &metadata = *(VideoGrallocMetadata *)(data->data());
@@ -1023,10 +1155,9 @@
OMX::buffer_id buffer) {
Mutex::Autolock autoLock(mLock);
OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, portIndex);
- // update backup buffer for input, codec buffer for output
+
return updateGraphicBufferInMeta_l(
- portIndex, graphicBuffer, buffer, header,
- true /* updateCodecBuffer */);
+ portIndex, graphicBuffer, buffer, header);
}
status_t OMXNodeInstance::updateNativeHandleInMeta(
@@ -1044,9 +1175,7 @@
}
BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate);
- // update backup buffer
- sp<ABuffer> data = bufferMeta->getBuffer(
- header, false /* backup */, false /* limit */);
+ sp<ABuffer> data = bufferMeta->getBuffer(header, false /* limit */);
bufferMeta->setNativeHandle(nativeHandle);
if (mMetadataType[portIndex] == kMetadataBufferTypeNativeHandleSource
&& data->capacity() >= sizeof(VideoNativeHandleMetadata)) {
@@ -1066,32 +1195,23 @@
return OK;
}
-status_t OMXNodeInstance::createGraphicBufferSource(
- OMX_U32 portIndex, const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type) {
+status_t OMXNodeInstance::setInputSurface(
+ const sp<IOMXBufferSource> &bufferSource) {
+ Mutex::Autolock autolock(mLock);
+
status_t err;
// only allow graphic source on input port, when there are no allocated buffers yet
- if (portIndex != kPortIndexInput) {
- android_errorWriteLog(0x534e4554, "29422020");
- return BAD_VALUE;
- } else if (mNumPortBuffers[portIndex] > 0) {
+ if (mNumPortBuffers[kPortIndexInput] > 0) {
android_errorWriteLog(0x534e4554, "29422020");
return INVALID_OPERATION;
}
- const sp<GraphicBufferSource> surfaceCheck = getGraphicBufferSource();
- if (surfaceCheck != NULL) {
- if (portIndex < NELEM(mMetadataType) && type != NULL) {
- *type = mMetadataType[portIndex];
- }
+ if (getBufferSource() != NULL) {
return ALREADY_EXISTS;
}
- // Input buffers will hold meta-data (ANativeWindowBuffer references).
- if (type != NULL) {
- *type = kMetadataBufferTypeANWBuffer;
- }
- err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE, type);
+ err = storeMetaDataInBuffers_l(kPortIndexInput, OMX_TRUE, NULL);
if (err != OK) {
return err;
}
@@ -1100,13 +1220,13 @@
// codec was configured.
OMX_PARAM_PORTDEFINITIONTYPE def;
InitOMXParams(&def);
- def.nPortIndex = portIndex;
+ def.nPortIndex = kPortIndexInput;
OMX_ERRORTYPE oerr = OMX_GetParameter(
mHandle, OMX_IndexParamPortDefinition, &def);
if (oerr != OMX_ErrorNone) {
OMX_INDEXTYPE index = OMX_IndexParamPortDefinition;
- CLOG_ERROR(getParameter, oerr, "%s(%#x): %s:%u",
- asString(index), index, portString(portIndex), portIndex);
+ CLOG_ERROR(getParameter, oerr, "%s(%#x): %s:%u", asString(index),
+ index, portString(kPortIndexInput), kPortIndexInput);
return UNKNOWN_ERROR;
}
@@ -1117,103 +1237,18 @@
return INVALID_OPERATION;
}
- uint32_t usageBits;
- oerr = OMX_GetParameter(
- mHandle, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, &usageBits);
- if (oerr != OMX_ErrorNone) {
- usageBits = 0;
- }
-
- sp<GraphicBufferSource> bufferSource = new GraphicBufferSource(this,
- def.format.video.nFrameWidth,
- def.format.video.nFrameHeight,
- def.nBufferCountActual,
- usageBits,
- bufferConsumer);
-
- if ((err = bufferSource->initCheck()) != OK) {
- return err;
- }
- setGraphicBufferSource(bufferSource);
-
- return OK;
-}
-
-status_t OMXNodeInstance::createInputSurface(
- OMX_U32 portIndex, android_dataspace dataSpace,
- sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
- if (bufferProducer == NULL) {
- ALOGE("b/25884056");
+ if (def.format.video.nFrameWidth == 0
+ || def.format.video.nFrameHeight == 0) {
+ ALOGE("Invalid video dimension %ux%u",
+ def.format.video.nFrameWidth,
+ def.format.video.nFrameHeight);
return BAD_VALUE;
}
- Mutex::Autolock autolock(mLock);
- status_t err = createGraphicBufferSource(portIndex, NULL /* bufferConsumer */, type);
-
- if (err != OK) {
- return err;
- }
-
- mGraphicBufferSource->setDefaultDataSpace(dataSpace);
-
- *bufferProducer = mGraphicBufferSource->getIGraphicBufferProducer();
+ setBufferSource(bufferSource);
return OK;
}
-//static
-status_t OMXNodeInstance::createPersistentInputSurface(
- sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferConsumer> *bufferConsumer) {
- if (bufferProducer == NULL || bufferConsumer == NULL) {
- ALOGE("b/25884056");
- return BAD_VALUE;
- }
- String8 name("GraphicBufferSource");
-
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->setConsumerName(name);
- consumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER);
-
- sp<BufferQueue::ProxyConsumerListener> proxy =
- new BufferQueue::ProxyConsumerListener(NULL);
- status_t err = consumer->consumerConnect(proxy, false);
- if (err != NO_ERROR) {
- ALOGE("Error connecting to BufferQueue: %s (%d)",
- strerror(-err), err);
- return err;
- }
-
- *bufferProducer = producer;
- *bufferConsumer = consumer;
-
- return OK;
-}
-
-status_t OMXNodeInstance::setInputSurface(
- OMX_U32 portIndex, const sp<IGraphicBufferConsumer> &bufferConsumer,
- MetadataBufferType *type) {
- Mutex::Autolock autolock(mLock);
- return createGraphicBufferSource(portIndex, bufferConsumer, type);
-}
-
-void OMXNodeInstance::signalEvent(OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) {
- mOwner->OnEvent(mNodeID, event, arg1, arg2, NULL);
-}
-
-status_t OMXNodeInstance::signalEndOfInputStream() {
- // For non-Surface input, the MediaCodec should convert the call to a
- // pair of requests (dequeue input buffer, queue input buffer with EOS
- // flag set). Seems easier than doing the equivalent from here.
- sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
- if (bufferSource == NULL) {
- CLOGW("signalEndOfInputStream can only be used with Surface input");
- return INVALID_OPERATION;
- }
- return bufferSource->signalEndOfInputStream();
-}
-
status_t OMXNodeInstance::allocateSecureBuffer(
OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
void **buffer_data, sp<NativeHandle> *native_handle) {
@@ -1230,7 +1265,7 @@
Mutex::Autolock autoLock(mLock);
- BufferMeta *buffer_meta = new BufferMeta(size, portIndex);
+ BufferMeta *buffer_meta = new BufferMeta(portIndex);
OMX_BUFFERHEADERTYPE *header;
@@ -1261,9 +1296,9 @@
addActiveBuffer(portIndex, *buffer);
- sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
+ sp<IOMXBufferSource> bufferSource(getBufferSource());
if (bufferSource != NULL && portIndex == kPortIndexInput) {
- bufferSource->addCodecBuffer(header);
+ bufferSource->onInputBufferAdded(*buffer);
}
CLOG_BUFFER(allocateSecureBuffer, NEW_BUFFER_FMT(
*buffer, portIndex, "%zu@%p:%p", size, *buffer_data,
@@ -1272,60 +1307,6 @@
return OK;
}
-status_t OMXNodeInstance::allocateBufferWithBackup(
- OMX_U32 portIndex, const sp<IMemory> ¶ms,
- OMX::buffer_id *buffer, OMX_U32 allottedSize) {
- if (params == NULL || buffer == NULL) {
- ALOGE("b/25884056");
- return BAD_VALUE;
- }
-
- Mutex::Autolock autoLock(mLock);
- if (allottedSize > params->size() || portIndex >= NELEM(mNumPortBuffers)) {
- return BAD_VALUE;
- }
-
- // metadata buffers are not connected cross process; only copy if not meta
- bool copy = mMetadataType[portIndex] == kMetadataBufferTypeInvalid;
-
- BufferMeta *buffer_meta = new BufferMeta(
- params, portIndex,
- (portIndex == kPortIndexInput) && copy /* copyToOmx */,
- (portIndex == kPortIndexOutput) && copy /* copyFromOmx */,
- NULL /* data */);
-
- OMX_BUFFERHEADERTYPE *header;
-
- OMX_ERRORTYPE err = OMX_AllocateBuffer(
- mHandle, &header, portIndex, buffer_meta, allottedSize);
- if (err != OMX_ErrorNone) {
- CLOG_ERROR(allocateBufferWithBackup, err,
- SIMPLE_BUFFER(portIndex, (size_t)allottedSize, params->pointer()));
- delete buffer_meta;
- buffer_meta = NULL;
-
- *buffer = 0;
-
- return StatusFromOMXError(err);
- }
-
- CHECK_EQ(header->pAppPrivate, buffer_meta);
-
- *buffer = makeBufferID(header);
-
- addActiveBuffer(portIndex, *buffer);
-
- sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
- if (bufferSource != NULL && portIndex == kPortIndexInput) {
- bufferSource->addCodecBuffer(header);
- }
-
- CLOG_BUFFER(allocateBufferWithBackup, NEW_BUFFER_FMT(*buffer, portIndex, "%zu@%p :> %u@%p",
- params->size(), params->pointer(), allottedSize, header->pBuffer));
-
- return OK;
-}
-
status_t OMXNodeInstance::freeBuffer(
OMX_U32 portIndex, OMX::buffer_id buffer) {
Mutex::Autolock autoLock(mLock);
@@ -1391,7 +1372,7 @@
Mutex::Autolock autoLock(mLock);
// no emptybuffer if using input surface
- if (getGraphicBufferSource() != NULL) {
+ if (getBufferSource() != NULL) {
android_errorWriteLog(0x534e4554, "29422020");
return INVALID_OPERATION;
}
@@ -1538,24 +1519,32 @@
// like emptyBuffer, but the data is already in header->pBuffer
status_t OMXNodeInstance::emptyGraphicBuffer(
- OMX_BUFFERHEADERTYPE *header, const sp<GraphicBuffer> &graphicBuffer,
- OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
+ OMX::buffer_id buffer, const sp<GraphicBuffer> &graphicBuffer,
+ OMX_U32 flags, OMX_TICKS timestamp, OMX_TICKS origTimestamp, int fenceFd) {
+ Mutex::Autolock autoLock(mLock);
+
+ OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexInput);
if (header == NULL) {
ALOGE("b/25884056");
return BAD_VALUE;
}
- Mutex::Autolock autoLock(mLock);
- OMX::buffer_id buffer = findBufferID(header);
status_t err = updateGraphicBufferInMeta_l(
- kPortIndexInput, graphicBuffer, buffer, header,
- true /* updateCodecBuffer */);
+ kPortIndexInput, graphicBuffer, buffer, header);
if (err != OK) {
CLOG_ERROR(emptyGraphicBuffer, err, FULL_BUFFER(
(intptr_t)header->pBuffer, header, fenceFd));
return err;
}
+ // If we're required to restore original timestamp, origTimestamp will
+ // be set to non-negative number for all frames. If it's not required
+ // client will set it to -1ll for all frames.
+ if (origTimestamp >= 0ll && !mRestorePtsFailed) {
+ mShouldRestorePts = true;
+ mOriginalTimeUs.add(timestamp, origTimestamp);
+ }
+
header->nOffset = 0;
if (graphicBuffer == NULL) {
header->nFilledLen = 0;
@@ -1567,6 +1556,38 @@
return emptyBuffer_l(header, flags, timestamp, (intptr_t)header->pBuffer, fenceFd);
}
+void OMXNodeInstance::codecBufferFilled(omx_message &msg) {
+ Mutex::Autolock autoLock(mBufferIDLock);
+
+ if (!mShouldRestorePts || mRestorePtsFailed) {
+ return;
+ }
+
+ OMX_U32 &flags = msg.u.extended_buffer_data.flags;
+ OMX_TICKS ×tamp = msg.u.extended_buffer_data.timestamp;
+
+ if (!(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
+ ssize_t index = mOriginalTimeUs.indexOfKey(timestamp);
+ if (index >= 0) {
+ ALOGV("OUT timestamp: %lld -> %lld",
+ static_cast<long long>(timestamp),
+ static_cast<long long>(mOriginalTimeUs[index]));
+ timestamp = mOriginalTimeUs[index];
+ mOriginalTimeUs.removeItemsAt(index);
+ } else {
+ // giving up the effort as encoder doesn't appear to preserve pts
+ ALOGW("giving up limiting timestamp gap (pts = %lld)", timestamp);
+ mRestorePtsFailed = true;
+ }
+ if (mOriginalTimeUs.size() > BufferQueue::NUM_BUFFER_SLOTS) {
+ // something terribly wrong must have happened, giving up...
+ ALOGE("mOriginalTimeUs has too many entries (%zu)",
+ mOriginalTimeUs.size());
+ mRestorePtsFailed = true;
+ }
+ }
+}
+
status_t OMXNodeInstance::getExtensionIndex(
const char *parameterName, OMX_INDEXTYPE *index) {
Mutex::Autolock autoLock(mLock);
@@ -1577,133 +1598,22 @@
return StatusFromOMXError(err);
}
-inline static const char *asString(IOMX::InternalOptionType i, const char *def = "??") {
- switch (i) {
- case IOMX::INTERNAL_OPTION_SUSPEND: return "SUSPEND";
- case IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY:
- return "REPEAT_PREVIOUS_FRAME_DELAY";
- case IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP: return "MAX_TIMESTAMP_GAP";
- case IOMX::INTERNAL_OPTION_MAX_FPS: return "MAX_FPS";
- case IOMX::INTERNAL_OPTION_START_TIME: return "START_TIME";
- case IOMX::INTERNAL_OPTION_TIME_LAPSE: return "TIME_LAPSE";
- case IOMX::INTERNAL_OPTION_TIME_OFFSET: return "TIME_OFFSET";
- default: return def;
- }
+status_t OMXNodeInstance::dispatchMessage(const omx_message &msg) {
+ mDispatcher->post(msg, true /*realTime*/);
+ return OK;
}
-template<typename T>
-static bool getInternalOption(
- const void *data, size_t size, T *out) {
- if (size != sizeof(T)) {
- return false;
+status_t OMXNodeInstance::setQuirks(OMX_U32 quirks) {
+ if (quirks & ~kQuirksMask) {
+ return BAD_VALUE;
}
- *out = *(T*)data;
- return true;
-}
-status_t OMXNodeInstance::setInternalOption(
- OMX_U32 portIndex,
- IOMX::InternalOptionType type,
- const void *data,
- size_t size) {
- CLOG_CONFIG(setInternalOption, "%s(%d): %s:%u %zu@%p",
- asString(type), type, portString(portIndex), portIndex, size, data);
- switch (type) {
- case IOMX::INTERNAL_OPTION_SUSPEND:
- case IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY:
- case IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP:
- case IOMX::INTERNAL_OPTION_MAX_FPS:
- case IOMX::INTERNAL_OPTION_START_TIME:
- case IOMX::INTERNAL_OPTION_TIME_LAPSE:
- case IOMX::INTERNAL_OPTION_TIME_OFFSET:
- case IOMX::INTERNAL_OPTION_COLOR_ASPECTS:
- {
- const sp<GraphicBufferSource> &bufferSource =
- getGraphicBufferSource();
+ mQuirks = quirks;
- if (bufferSource == NULL || portIndex != kPortIndexInput) {
- CLOGW("setInternalOption is only for Surface input");
- return ERROR_UNSUPPORTED;
- }
-
- if (type == IOMX::INTERNAL_OPTION_SUSPEND) {
- bool suspend;
- if (!getInternalOption(data, size, &suspend)) {
- return INVALID_OPERATION;
- }
-
- CLOG_CONFIG(setInternalOption, "suspend=%d", suspend);
- bufferSource->suspend(suspend);
- } else if (type == IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY) {
- int64_t delayUs;
- if (!getInternalOption(data, size, &delayUs)) {
- return INVALID_OPERATION;
- }
-
- CLOG_CONFIG(setInternalOption, "delayUs=%lld", (long long)delayUs);
- return bufferSource->setRepeatPreviousFrameDelayUs(delayUs);
- } else if (type == IOMX::INTERNAL_OPTION_TIME_OFFSET) {
- int64_t timeOffsetUs;
- if (!getInternalOption(data, size, &timeOffsetUs)) {
- return INVALID_OPERATION;
- }
- CLOG_CONFIG(setInternalOption, "bufferOffsetUs=%lld", (long long)timeOffsetUs);
- return bufferSource->setInputBufferTimeOffset(timeOffsetUs);
- } else if (type == IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP) {
- int64_t maxGapUs;
- if (!getInternalOption(data, size, &maxGapUs)) {
- return INVALID_OPERATION;
- }
-
- CLOG_CONFIG(setInternalOption, "gapUs=%lld", (long long)maxGapUs);
- return bufferSource->setMaxTimestampGapUs(maxGapUs);
- } else if (type == IOMX::INTERNAL_OPTION_MAX_FPS) {
- float maxFps;
- if (!getInternalOption(data, size, &maxFps)) {
- return INVALID_OPERATION;
- }
-
- CLOG_CONFIG(setInternalOption, "maxFps=%f", maxFps);
- return bufferSource->setMaxFps(maxFps);
- } else if (type == IOMX::INTERNAL_OPTION_START_TIME) {
- int64_t skipFramesBeforeUs;
- if (!getInternalOption(data, size, &skipFramesBeforeUs)) {
- return INVALID_OPERATION;
- }
-
- CLOG_CONFIG(setInternalOption, "beforeUs=%lld", (long long)skipFramesBeforeUs);
- bufferSource->setSkipFramesBeforeUs(skipFramesBeforeUs);
- } else if (type == IOMX::INTERNAL_OPTION_TIME_LAPSE) {
- GraphicBufferSource::TimeLapseConfig config;
- if (!getInternalOption(data, size, &config)) {
- return INVALID_OPERATION;
- }
-
- CLOG_CONFIG(setInternalOption, "perFrameUs=%lld perCaptureUs=%lld",
- (long long)config.mTimePerFrameUs, (long long)config.mTimePerCaptureUs);
-
- return bufferSource->setTimeLapseConfig(config);
- } else if (type == IOMX::INTERNAL_OPTION_COLOR_ASPECTS) {
- ColorAspects aspects;
- if (!getInternalOption(data, size, &aspects)) {
- return INVALID_OPERATION;
- }
-
- CLOG_CONFIG(setInternalOption, "setting color aspects");
- bufferSource->setColorAspects(aspects);
- }
-
- return OK;
- }
-
- default:
- return ERROR_UNSUPPORTED;
- }
+ return OK;
}
bool OMXNodeInstance::handleMessage(omx_message &msg) {
- const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
-
if (msg.type == omx_message::FILL_BUFFER_DONE) {
OMX_BUFFERHEADERTYPE *buffer =
findBufferHeader(msg.u.extended_buffer_data.buffer, kPortIndexOutput);
@@ -1733,12 +1643,8 @@
}
buffer_meta->CopyFromOMX(buffer);
- if (bufferSource != NULL) {
- // fix up the buffer info (especially timestamp) if needed
- bufferSource->codecBufferFilled(buffer);
-
- msg.u.extended_buffer_data.timestamp = buffer->nTimeStamp;
- }
+ // fix up the buffer info (especially timestamp) if needed
+ codecBufferFilled(msg);
} else if (msg.type == omx_message::EMPTY_BUFFER_DONE) {
OMX_BUFFERHEADERTYPE *buffer =
findBufferHeader(msg.u.buffer_data.buffer, kPortIndexInput);
@@ -1754,20 +1660,100 @@
EBD, WITH_STATS(EMPTY_BUFFER(msg.u.buffer_data.buffer, buffer, msg.fenceFd)));
}
+ const sp<IOMXBufferSource> bufferSource(getBufferSource());
+
if (bufferSource != NULL) {
- // This is one of the buffers used exclusively by
- // GraphicBufferSource.
+ // This is one of the buffers used exclusively by IOMXBufferSource.
// Don't dispatch a message back to ACodec, since it doesn't
// know that anyone asked to have the buffer emptied and will
// be very confused.
- bufferSource->codecBufferEmptied(buffer, msg.fenceFd);
+ bufferSource->onInputBufferEmptied(
+ msg.u.buffer_data.buffer, OMXFenceParcelable(msg.fenceFd));
return true;
}
+ } else if (msg.type == omx_message::EVENT &&
+ msg.u.event_data.event == OMX_EventDataSpaceChanged) {
+ handleDataSpaceChanged(msg);
}
return false;
}
+bool OMXNodeInstance::handleDataSpaceChanged(omx_message &msg) {
+ android_dataspace dataSpace = (android_dataspace) msg.u.event_data.data1;
+ android_dataspace origDataSpace = dataSpace;
+
+ if (!ColorUtils::convertDataSpaceToV0(dataSpace)) {
+ // Do not process the data space change, don't notify client either
+ return true;
+ }
+
+ android_pixel_format pixelFormat = (android_pixel_format)msg.u.event_data.data3;
+
+ ColorAspects requestedAspects = ColorUtils::unpackToColorAspects(msg.u.event_data.data2);
+ ColorAspects aspects = requestedAspects; // initially requested aspects
+
+ // request color aspects to encode
+ OMX_INDEXTYPE index;
+ status_t err = getExtensionIndex(
+ "OMX.google.android.index.describeColorAspects", &index);
+ if (err == OK) {
+ // V0 dataspace
+ DescribeColorAspectsParams params;
+ InitOMXParams(¶ms);
+ params.nPortIndex = kPortIndexInput;
+ params.nDataSpace = origDataSpace;
+ params.nPixelFormat = pixelFormat;
+ params.bDataSpaceChanged = OMX_TRUE;
+ params.sAspects = requestedAspects;
+
+ err = getConfig(index, ¶ms, sizeof(params));
+ if (err == OK) {
+ aspects = params.sAspects;
+ ALOGD("Codec resolved it to (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
+ params.sAspects.mRange, asString(params.sAspects.mRange),
+ params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
+ params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
+ params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
+ err, asString(err));
+ } else {
+ params.sAspects = aspects;
+ err = OK;
+ }
+ params.bDataSpaceChanged = OMX_FALSE;
+ for (int triesLeft = 2; --triesLeft >= 0; ) {
+ status_t err = setConfig(index, ¶ms, sizeof(params));
+ if (err == OK) {
+ err = getConfig(index, ¶ms, sizeof(params));
+ }
+ if (err != OK || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(
+ params.sAspects, aspects)) {
+ // if we can't set or get color aspects, still communicate dataspace to client
+ break;
+ }
+
+ ALOGW_IF(triesLeft == 0, "Codec repeatedly changed requested ColorAspects.");
+ }
+ }
+
+ ALOGV("Set color aspects to (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
+ aspects.mRange, asString(aspects.mRange),
+ aspects.mPrimaries, asString(aspects.mPrimaries),
+ aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs),
+ aspects.mTransfer, asString(aspects.mTransfer),
+ err, asString(err));
+
+ // signal client that the dataspace has changed; this will update the output format
+ // TODO: we should tie this to an output buffer somehow, and signal the change
+ // just before the output buffer is returned to the client, but there are many
+ // ways this could fail (e.g. flushing), and we are not yet supporting this scenario.
+
+ msg.u.event_data.data1 = (OMX_U32) dataSpace;
+ msg.u.event_data.data2 = (OMX_U32) ColorUtils::packToU32(aspects);
+
+ return false;
+}
+
void OMXNodeInstance::onMessages(std::list<omx_message> &messages) {
for (std::list<omx_message>::iterator it = messages.begin(); it != messages.end(); ) {
if (handleMessage(*it)) {
@@ -1782,15 +1768,11 @@
}
}
-void OMXNodeInstance::onObserverDied(OMXMaster *master) {
+void OMXNodeInstance::onObserverDied() {
ALOGE("!!! Observer died. Quickly, do something, ... anything...");
// Try to force shutdown of the node and hope for the best.
- freeNode(master);
-}
-
-void OMXNodeInstance::onGetHandleFailed() {
- delete this;
+ freeNode();
}
// OMXNodeInstance::OnEvent calls OMX::OnEvent, which then calls here.
@@ -1834,13 +1816,13 @@
CLOGI_(level, onEvent, "%s(%x), %s(%x), %s(%x)",
asString(event), event, arg1String, arg1, arg2String, arg2);
- const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
+ const sp<IOMXBufferSource> bufferSource(getBufferSource());
if (bufferSource != NULL
&& event == OMX_EventCmdComplete
&& arg1 == OMX_CommandStateSet
&& arg2 == OMX_StateExecuting) {
- bufferSource->omxExecuting();
+ bufferSource->onOmxExecuting();
}
// allow configuration if we return to the loaded state
@@ -1867,8 +1849,39 @@
if (instance->mDying) {
return OMX_ErrorNone;
}
- return instance->owner()->OnEvent(
- instance->nodeID(), eEvent, nData1, nData2, pEventData);
+
+ instance->onEvent(eEvent, nData1, nData2);
+
+ // output rendered events are not processed as regular events until they hit the observer
+ if (eEvent == OMX_EventOutputRendered) {
+ if (pEventData == NULL) {
+ return OMX_ErrorBadParameter;
+ }
+
+ // process data from array
+ OMX_VIDEO_RENDEREVENTTYPE *renderData = (OMX_VIDEO_RENDEREVENTTYPE *)pEventData;
+ for (size_t i = 0; i < nData1; ++i) {
+ omx_message msg;
+ msg.type = omx_message::FRAME_RENDERED;
+ msg.fenceFd = -1;
+ msg.u.render_data.timestamp = renderData[i].nMediaTimeUs;
+ msg.u.render_data.nanoTime = renderData[i].nSystemTimeNs;
+
+ instance->mDispatcher->post(msg, false /* realTime */);
+ }
+ return OMX_ErrorNone;
+ }
+
+ omx_message msg;
+ msg.type = omx_message::EVENT;
+ msg.fenceFd = -1;
+ msg.u.event_data.event = eEvent;
+ msg.u.event_data.data1 = nData1;
+ msg.u.event_data.data2 = nData2;
+
+ instance->mDispatcher->post(msg, true /* realTime */);
+
+ return OMX_ErrorNone;
}
// static
@@ -1885,8 +1898,14 @@
return OMX_ErrorNone;
}
int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput);
- return instance->owner()->OnEmptyBufferDone(instance->nodeID(),
- instance->findBufferID(pBuffer), pBuffer, fenceFd);
+
+ omx_message msg;
+ msg.type = omx_message::EMPTY_BUFFER_DONE;
+ msg.fenceFd = fenceFd;
+ msg.u.buffer_data.buffer = instance->findBufferID(pBuffer);
+ instance->mDispatcher->post(msg);
+
+ return OMX_ErrorNone;
}
// static
@@ -1903,8 +1922,18 @@
return OMX_ErrorNone;
}
int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput);
- return instance->owner()->OnFillBufferDone(instance->nodeID(),
- instance->findBufferID(pBuffer), pBuffer, fenceFd);
+
+ omx_message msg;
+ msg.type = omx_message::FILL_BUFFER_DONE;
+ msg.fenceFd = fenceFd;
+ msg.u.extended_buffer_data.buffer = instance->findBufferID(pBuffer);
+ msg.u.extended_buffer_data.range_offset = pBuffer->nOffset;
+ msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen;
+ msg.u.extended_buffer_data.flags = pBuffer->nFlags;
+ msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp;
+ instance->mDispatcher->post(msg);
+
+ return OMX_ErrorNone;
}
void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) {
diff --git a/media/libstagefright/omx/OMXUtils.cpp b/media/libstagefright/omx/OMXUtils.cpp
index 799696c..38aad39 100644
--- a/media/libstagefright/omx/OMXUtils.cpp
+++ b/media/libstagefright/omx/OMXUtils.cpp
@@ -20,7 +20,10 @@
#include <string.h>
#include <media/hardware/HardwareAPI.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/MediaErrors.h>
+#include <media/MediaDefs.h>
#include "OMXUtils.h"
namespace android {
@@ -101,5 +104,273 @@
/**************************************************************************************************/
+const char *GetComponentRole(bool isEncoder, const char *mime) {
+ struct MimeToRole {
+ const char *mime;
+ const char *decoderRole;
+ const char *encoderRole;
+ };
+
+ static const MimeToRole kMimeToRole[] = {
+ { MEDIA_MIMETYPE_AUDIO_MPEG,
+ "audio_decoder.mp3", "audio_encoder.mp3" },
+ { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
+ "audio_decoder.mp1", "audio_encoder.mp1" },
+ { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
+ "audio_decoder.mp2", "audio_encoder.mp2" },
+ { MEDIA_MIMETYPE_AUDIO_AMR_NB,
+ "audio_decoder.amrnb", "audio_encoder.amrnb" },
+ { MEDIA_MIMETYPE_AUDIO_AMR_WB,
+ "audio_decoder.amrwb", "audio_encoder.amrwb" },
+ { MEDIA_MIMETYPE_AUDIO_AAC,
+ "audio_decoder.aac", "audio_encoder.aac" },
+ { MEDIA_MIMETYPE_AUDIO_VORBIS,
+ "audio_decoder.vorbis", "audio_encoder.vorbis" },
+ { MEDIA_MIMETYPE_AUDIO_OPUS,
+ "audio_decoder.opus", "audio_encoder.opus" },
+ { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
+ "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
+ { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
+ "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
+ { MEDIA_MIMETYPE_VIDEO_AVC,
+ "video_decoder.avc", "video_encoder.avc" },
+ { MEDIA_MIMETYPE_VIDEO_HEVC,
+ "video_decoder.hevc", "video_encoder.hevc" },
+ { MEDIA_MIMETYPE_VIDEO_MPEG4,
+ "video_decoder.mpeg4", "video_encoder.mpeg4" },
+ { MEDIA_MIMETYPE_VIDEO_H263,
+ "video_decoder.h263", "video_encoder.h263" },
+ { MEDIA_MIMETYPE_VIDEO_VP8,
+ "video_decoder.vp8", "video_encoder.vp8" },
+ { MEDIA_MIMETYPE_VIDEO_VP9,
+ "video_decoder.vp9", "video_encoder.vp9" },
+ { MEDIA_MIMETYPE_AUDIO_RAW,
+ "audio_decoder.raw", "audio_encoder.raw" },
+ { MEDIA_MIMETYPE_VIDEO_DOLBY_VISION,
+ "video_decoder.dolby-vision", "video_encoder.dolby-vision" },
+ { MEDIA_MIMETYPE_AUDIO_FLAC,
+ "audio_decoder.flac", "audio_encoder.flac" },
+ { MEDIA_MIMETYPE_AUDIO_MSGSM,
+ "audio_decoder.gsm", "audio_encoder.gsm" },
+ { MEDIA_MIMETYPE_VIDEO_MPEG2,
+ "video_decoder.mpeg2", "video_encoder.mpeg2" },
+ { MEDIA_MIMETYPE_AUDIO_AC3,
+ "audio_decoder.ac3", "audio_encoder.ac3" },
+ { MEDIA_MIMETYPE_AUDIO_EAC3,
+ "audio_decoder.eac3", "audio_encoder.eac3" },
+ };
+
+ static const size_t kNumMimeToRole =
+ sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
+
+ size_t i;
+ for (i = 0; i < kNumMimeToRole; ++i) {
+ if (!strcasecmp(mime, kMimeToRole[i].mime)) {
+ break;
+ }
+ }
+
+ if (i == kNumMimeToRole) {
+ return NULL;
+ }
+
+ return isEncoder ? kMimeToRole[i].encoderRole
+ : kMimeToRole[i].decoderRole;
+}
+
+status_t SetComponentRole(const sp<IOMXNode> &omxNode, const char *role) {
+ OMX_PARAM_COMPONENTROLETYPE roleParams;
+ InitOMXParams(&roleParams);
+
+ strncpy((char *)roleParams.cRole,
+ role, OMX_MAX_STRINGNAME_SIZE - 1);
+
+ roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
+
+ return omxNode->setParameter(
+ OMX_IndexParamStandardComponentRole,
+ &roleParams, sizeof(roleParams));
+}
+
+bool DescribeDefaultColorFormat(DescribeColorFormat2Params ¶ms) {
+ MediaImage2 &image = params.sMediaImage;
+ memset(&image, 0, sizeof(image));
+
+ image.mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
+ image.mNumPlanes = 0;
+
+ const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat;
+ image.mWidth = params.nFrameWidth;
+ image.mHeight = params.nFrameHeight;
+
+ // only supporting YUV420
+ if (fmt != OMX_COLOR_FormatYUV420Planar &&
+ fmt != OMX_COLOR_FormatYUV420PackedPlanar &&
+ fmt != OMX_COLOR_FormatYUV420SemiPlanar &&
+ fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar &&
+ fmt != (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_YV12) {
+ ALOGW("do not know color format 0x%x = %d", fmt, fmt);
+ return false;
+ }
+
+ // TEMPORARY FIX for some vendors that advertise sliceHeight as 0
+ if (params.nStride != 0 && params.nSliceHeight == 0) {
+ ALOGW("using sliceHeight=%u instead of what codec advertised (=0)",
+ params.nFrameHeight);
+ params.nSliceHeight = params.nFrameHeight;
+ }
+
+ // we need stride and slice-height to be non-zero and sensible. These values were chosen to
+ // prevent integer overflows further down the line, and do not indicate support for
+ // 32kx32k video.
+ if (params.nStride == 0 || params.nSliceHeight == 0
+ || params.nStride > 32768 || params.nSliceHeight > 32768) {
+ ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u",
+ fmt, fmt, params.nStride, params.nSliceHeight);
+ return false;
+ }
+
+ // set-up YUV format
+ image.mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV;
+ image.mNumPlanes = 3;
+ image.mBitDepth = 8;
+ image.mBitDepthAllocated = 8;
+ image.mPlane[image.Y].mOffset = 0;
+ image.mPlane[image.Y].mColInc = 1;
+ image.mPlane[image.Y].mRowInc = params.nStride;
+ image.mPlane[image.Y].mHorizSubsampling = 1;
+ image.mPlane[image.Y].mVertSubsampling = 1;
+
+ switch ((int)fmt) {
+ case HAL_PIXEL_FORMAT_YV12:
+ if (params.bUsingNativeBuffers) {
+ size_t ystride = align(params.nStride, 16);
+ size_t cstride = align(params.nStride / 2, 16);
+ image.mPlane[image.Y].mRowInc = ystride;
+
+ image.mPlane[image.V].mOffset = ystride * params.nSliceHeight;
+ image.mPlane[image.V].mColInc = 1;
+ image.mPlane[image.V].mRowInc = cstride;
+ image.mPlane[image.V].mHorizSubsampling = 2;
+ image.mPlane[image.V].mVertSubsampling = 2;
+
+ image.mPlane[image.U].mOffset = image.mPlane[image.V].mOffset
+ + (cstride * params.nSliceHeight / 2);
+ image.mPlane[image.U].mColInc = 1;
+ image.mPlane[image.U].mRowInc = cstride;
+ image.mPlane[image.U].mHorizSubsampling = 2;
+ image.mPlane[image.U].mVertSubsampling = 2;
+ break;
+ } else {
+ // fall through as YV12 is used for YUV420Planar by some codecs
+ }
+
+ case OMX_COLOR_FormatYUV420Planar:
+ case OMX_COLOR_FormatYUV420PackedPlanar:
+ image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
+ image.mPlane[image.U].mColInc = 1;
+ image.mPlane[image.U].mRowInc = params.nStride / 2;
+ image.mPlane[image.U].mHorizSubsampling = 2;
+ image.mPlane[image.U].mVertSubsampling = 2;
+
+ image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset
+ + (params.nStride * params.nSliceHeight / 4);
+ image.mPlane[image.V].mColInc = 1;
+ image.mPlane[image.V].mRowInc = params.nStride / 2;
+ image.mPlane[image.V].mHorizSubsampling = 2;
+ image.mPlane[image.V].mVertSubsampling = 2;
+ break;
+
+ case OMX_COLOR_FormatYUV420SemiPlanar:
+ // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder
+ case OMX_COLOR_FormatYUV420PackedSemiPlanar:
+ // NV12
+ image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
+ image.mPlane[image.U].mColInc = 2;
+ image.mPlane[image.U].mRowInc = params.nStride;
+ image.mPlane[image.U].mHorizSubsampling = 2;
+ image.mPlane[image.U].mVertSubsampling = 2;
+
+ image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1;
+ image.mPlane[image.V].mColInc = 2;
+ image.mPlane[image.V].mRowInc = params.nStride;
+ image.mPlane[image.V].mHorizSubsampling = 2;
+ image.mPlane[image.V].mVertSubsampling = 2;
+ break;
+
+ default:
+ TRESPASS();
+ }
+ return true;
+}
+
+bool DescribeColorFormat(
+ const sp<IOMXNode> &omxNode,
+ DescribeColorFormat2Params &describeParams)
+{
+ OMX_INDEXTYPE describeColorFormatIndex;
+ if (omxNode->getExtensionIndex(
+ "OMX.google.android.index.describeColorFormat",
+ &describeColorFormatIndex) == OK) {
+ DescribeColorFormatParams describeParamsV1(describeParams);
+ if (omxNode->getParameter(
+ describeColorFormatIndex,
+ &describeParamsV1, sizeof(describeParamsV1)) == OK) {
+ describeParams.initFromV1(describeParamsV1);
+ return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
+ }
+ } else if (omxNode->getExtensionIndex(
+ "OMX.google.android.index.describeColorFormat2", &describeColorFormatIndex) == OK
+ && omxNode->getParameter(
+ describeColorFormatIndex, &describeParams, sizeof(describeParams)) == OK) {
+ return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
+ }
+
+ return DescribeDefaultColorFormat(describeParams);
+}
+
+// static
+bool IsFlexibleColorFormat(
+ const sp<IOMXNode> &omxNode,
+ uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) {
+ DescribeColorFormat2Params describeParams;
+ InitOMXParams(&describeParams);
+ describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
+ // reasonable dummy values
+ describeParams.nFrameWidth = 128;
+ describeParams.nFrameHeight = 128;
+ describeParams.nStride = 128;
+ describeParams.nSliceHeight = 128;
+ describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers;
+
+ CHECK(flexibleEquivalent != NULL);
+
+ if (!DescribeColorFormat(omxNode, describeParams)) {
+ return false;
+ }
+
+ const MediaImage2 &img = describeParams.sMediaImage;
+ if (img.mType == MediaImage2::MEDIA_IMAGE_TYPE_YUV) {
+ if (img.mNumPlanes != 3
+ || img.mPlane[img.Y].mHorizSubsampling != 1
+ || img.mPlane[img.Y].mVertSubsampling != 1) {
+ return false;
+ }
+
+ // YUV 420
+ if (img.mPlane[img.U].mHorizSubsampling == 2
+ && img.mPlane[img.U].mVertSubsampling == 2
+ && img.mPlane[img.V].mHorizSubsampling == 2
+ && img.mPlane[img.V].mVertSubsampling == 2) {
+ // possible flexible YUV420 format
+ if (img.mBitDepth <= 8) {
+ *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
} // namespace android
diff --git a/media/libstagefright/omx/OMXUtils.h b/media/libstagefright/omx/OMXUtils.h
index 0c5e537..3f533ff 100644
--- a/media/libstagefright/omx/OMXUtils.h
+++ b/media/libstagefright/omx/OMXUtils.h
@@ -17,6 +17,8 @@
#ifndef OMX_UTILS_H_
#define OMX_UTILS_H_
+#include <media/IOMX.h>
+
/***** DO NOT USE THIS INCLUDE!!! INTERAL ONLY!!! UNLESS YOU RESIDE IN media/libstagefright *****/
// OMXUtils contains omx-specific utility functions for stagefright/omx library
@@ -36,6 +38,19 @@
status_t StatusFromOMXError(OMX_ERRORTYPE err);
+const char *GetComponentRole(bool isEncoder, const char *mime);
+status_t SetComponentRole(const sp<IOMXNode> &omxNode, const char *role);
+
+struct DescribeColorFormat2Params;
+
+bool IsFlexibleColorFormat(
+ const sp<IOMXNode> &omxNode, uint32_t colorFormat,
+ bool usingNativeBuffers, OMX_U32 *flexibleEquivalent);
+bool DescribeDefaultColorFormat(DescribeColorFormat2Params &describeParams);
+bool DescribeColorFormat(
+ const sp<IOMXNode> &omxNode,
+ DescribeColorFormat2Params &describeParams);
+
} // namespace android
#endif
diff --git a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
index 7c975f7..761b425 100644
--- a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
+++ b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
@@ -77,19 +77,34 @@
switch (index) {
case OMX_IndexParamPortDefinition:
{
- portIndex = ((OMX_PARAM_PORTDEFINITIONTYPE *)params)->nPortIndex;
+ const OMX_PARAM_PORTDEFINITIONTYPE *portDefs =
+ (const OMX_PARAM_PORTDEFINITIONTYPE *) params;
+ if (!isValidOMXParam(portDefs)) {
+ return false;
+ }
+ portIndex = portDefs->nPortIndex;
break;
}
case OMX_IndexParamAudioPcm:
{
- portIndex = ((OMX_AUDIO_PARAM_PCMMODETYPE *)params)->nPortIndex;
+ const OMX_AUDIO_PARAM_PCMMODETYPE *pcmMode =
+ (const OMX_AUDIO_PARAM_PCMMODETYPE *) params;
+ if (!isValidOMXParam(pcmMode)) {
+ return false;
+ }
+ portIndex = pcmMode->nPortIndex;
break;
}
case OMX_IndexParamAudioAac:
{
- portIndex = ((OMX_AUDIO_PARAM_AACPROFILETYPE *)params)->nPortIndex;
+ const OMX_AUDIO_PARAM_AACPROFILETYPE *aacMode =
+ (const OMX_AUDIO_PARAM_AACPROFILETYPE *) params;
+ if (!isValidOMXParam(aacMode)) {
+ return false;
+ }
+ portIndex = aacMode->nPortIndex;
break;
}
diff --git a/media/libstagefright/omx/SoftOMXPlugin.cpp b/media/libstagefright/omx/SoftOMXPlugin.cpp
index 0f9c00c..a773ca2 100755
--- a/media/libstagefright/omx/SoftOMXPlugin.cpp
+++ b/media/libstagefright/omx/SoftOMXPlugin.cpp
@@ -56,6 +56,7 @@
{ "OMX.google.vp8.decoder", "vpxdec", "video_decoder.vp8" },
{ "OMX.google.vp9.decoder", "vpxdec", "video_decoder.vp9" },
{ "OMX.google.vp8.encoder", "vpxenc", "video_encoder.vp8" },
+ { "OMX.google.vp9.encoder", "vpxenc", "video_encoder.vp9" },
{ "OMX.google.raw.decoder", "rawdec", "audio_decoder.raw" },
{ "OMX.google.flac.encoder", "flacenc", "audio_encoder.flac" },
{ "OMX.google.gsm.decoder", "gsmdec", "audio_decoder.gsm" },
diff --git a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
index 0f9c118..adf846a 100644
--- a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
@@ -480,18 +480,25 @@
unsigned green = src[greenOffset];
unsigned blue = src[blueOffset];
- // using ITU-R BT.601 conversion matrix
+ // Using ITU-R BT.601-7 (03/2011)
+ // 2.5.1: Ey' = ( 0.299*R + 0.587*G + 0.114*B)
+ // 2.5.2: ECr' = ( 0.701*R - 0.587*G - 0.114*B) / 1.402
+ // ECb' = (-0.299*R - 0.587*G + 0.886*B) / 1.772
+ // 2.5.3: Y = 219 * Ey' + 16
+ // Cr = 224 * ECr' + 128
+ // Cb = 224 * ECb' + 128
+
unsigned luma =
- ((red * 66 + green * 129 + blue * 25) >> 8) + 16;
+ ((red * 65 + green * 129 + blue * 25 + 128) >> 8) + 16;
dstY[x] = luma;
if ((x & 1) == 0 && (y & 1) == 0) {
unsigned U =
- ((-red * 38 - green * 74 + blue * 112) >> 8) + 128;
+ ((-red * 38 - green * 74 + blue * 112 + 128) >> 8) + 128;
unsigned V =
- ((red * 112 - green * 94 - blue * 18) >> 8) + 128;
+ ((red * 112 - green * 94 - blue * 18 + 128) >> 8) + 128;
dstU[x >> 1] = U;
dstV[x >> 1] = V;
diff --git a/media/libstagefright/omx/tests/Android.mk b/media/libstagefright/omx/tests/Android.mk
index 02e97f1..ec14eb7 100644
--- a/media/libstagefright/omx/tests/Android.mk
+++ b/media/libstagefright/omx/tests/Android.mk
@@ -12,7 +12,6 @@
$(TOP)/frameworks/native/include/media/openmax
LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
LOCAL_MODULE := omx_tests
@@ -39,6 +38,5 @@
frameworks/av/media/libstagefright/omx \
LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
include $(BUILD_NATIVE_TEST)
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 50bb0de..ea99e53 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -43,6 +43,25 @@
namespace android {
+/////////////////////////////////////////////////////////////////////
+
+struct Harness::CodecObserver : public BnOMXObserver {
+ CodecObserver(const sp<Harness> &harness, int32_t gen)
+ : mHarness(harness), mGeneration(gen) {}
+
+ void onMessages(const std::list<omx_message> &messages) override;
+
+private:
+ sp<Harness> mHarness;
+ int32_t mGeneration;
+};
+
+void Harness::CodecObserver::onMessages(const std::list<omx_message> &messages) {
+ mHarness->handleMessages(mGeneration, messages);
+}
+
+/////////////////////////////////////////////////////////////////////
+
Harness::Harness()
: mInitCheck(NO_INIT) {
mInitCheck = initOMX();
@@ -64,18 +83,17 @@
return mOMX != 0 ? OK : NO_INIT;
}
-void Harness::onMessages(const std::list<omx_message> &messages) {
+void Harness::handleMessages(int32_t gen, const std::list<omx_message> &messages) {
Mutex::Autolock autoLock(mLock);
for (std::list<omx_message>::const_iterator it = messages.cbegin(); it != messages.cend(); ) {
mMessageQueue.push_back(*it++);
+ mLastMsgGeneration = gen;
}
mMessageAddedCondition.signal();
}
-status_t Harness::dequeueMessageForNode(
- IOMX::node_id node, omx_message *msg, int64_t timeoutUs) {
- return dequeueMessageForNodeIgnoringBuffers(
- node, NULL, NULL, msg, timeoutUs);
+status_t Harness::dequeueMessageForNode(omx_message *msg, int64_t timeoutUs) {
+ return dequeueMessageForNodeIgnoringBuffers(NULL, NULL, msg, timeoutUs);
}
// static
@@ -120,7 +138,6 @@
}
status_t Harness::dequeueMessageForNodeIgnoringBuffers(
- IOMX::node_id node,
Vector<Buffer> *inputBuffers,
Vector<Buffer> *outputBuffers,
omx_message *msg, int64_t timeoutUs) {
@@ -128,21 +145,22 @@
for (;;) {
Mutex::Autolock autoLock(mLock);
+ // Messages are queued in batches, if the last batch queued is
+ // from a node that already expired, discard those messages.
+ if (mLastMsgGeneration < mCurGeneration) {
+ mMessageQueue.clear();
+ }
List<omx_message>::iterator it = mMessageQueue.begin();
while (it != mMessageQueue.end()) {
- if ((*it).node == node) {
- if (handleBufferMessage(*it, inputBuffers, outputBuffers)) {
- it = mMessageQueue.erase(it);
- continue;
- }
-
- *msg = *it;
- mMessageQueue.erase(it);
-
- return OK;
+ if (handleBufferMessage(*it, inputBuffers, outputBuffers)) {
+ it = mMessageQueue.erase(it);
+ continue;
}
- ++it;
+ *msg = *it;
+ mMessageQueue.erase(it);
+
+ return OK;
}
status_t err = (timeoutUs < 0)
@@ -158,16 +176,15 @@
}
status_t Harness::getPortDefinition(
- IOMX::node_id node, OMX_U32 portIndex,
- OMX_PARAM_PORTDEFINITIONTYPE *def) {
+ OMX_U32 portIndex, OMX_PARAM_PORTDEFINITIONTYPE *def) {
def->nSize = sizeof(*def);
def->nVersion.s.nVersionMajor = 1;
def->nVersion.s.nVersionMinor = 0;
def->nVersion.s.nRevision = 0;
def->nVersion.s.nStep = 0;
def->nPortIndex = portIndex;
- return mOMX->getParameter(
- node, OMX_IndexParamPortDefinition, def, sizeof(*def));
+ return mOMXNode->getParameter(
+ OMX_IndexParamPortDefinition, def, sizeof(*def));
}
#define EXPECT(condition, info) \
@@ -180,12 +197,11 @@
status_t Harness::allocatePortBuffers(
const sp<MemoryDealer> &dealer,
- IOMX::node_id node, OMX_U32 portIndex,
- Vector<Buffer> *buffers) {
+ OMX_U32 portIndex, Vector<Buffer> *buffers) {
buffers->clear();
OMX_PARAM_PORTDEFINITIONTYPE def;
- status_t err = getPortDefinition(node, portIndex, &def);
+ status_t err = getPortDefinition(portIndex, &def);
EXPECT_SUCCESS(err, "getPortDefinition");
for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
@@ -194,9 +210,9 @@
buffer.mFlags = 0;
CHECK(buffer.mMemory != NULL);
- err = mOMX->allocateBufferWithBackup(
- node, portIndex, buffer.mMemory, &buffer.mID, buffer.mMemory->size());
- EXPECT_SUCCESS(err, "allocateBuffer");
+ err = mOMXNode->useBuffer(
+ portIndex, buffer.mMemory, &buffer.mID, buffer.mMemory->size());
+ EXPECT_SUCCESS(err, "useBuffer");
buffers->push(buffer);
}
@@ -204,7 +220,7 @@
return OK;
}
-status_t Harness::setRole(IOMX::node_id node, const char *role) {
+status_t Harness::setRole(const char *role) {
OMX_PARAM_COMPONENTROLETYPE params;
params.nSize = sizeof(params);
params.nVersion.s.nVersionMajor = 1;
@@ -214,31 +230,31 @@
strncpy((char *)params.cRole, role, OMX_MAX_STRINGNAME_SIZE - 1);
params.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
- return mOMX->setParameter(
- node, OMX_IndexParamStandardComponentRole,
+ return mOMXNode->setParameter(
+ OMX_IndexParamStandardComponentRole,
¶ms, sizeof(params));
}
struct NodeReaper {
- NodeReaper(const sp<Harness> &harness, IOMX::node_id node)
+ NodeReaper(const sp<Harness> &harness, const sp<IOMXNode> &omxNode)
: mHarness(harness),
- mNode(node) {
+ mOMXNode(omxNode) {
}
~NodeReaper() {
- if (mNode != 0) {
- mHarness->mOMX->freeNode(mNode);
- mNode = 0;
+ if (mOMXNode != 0) {
+ mOMXNode->freeNode();
+ mOMXNode = NULL;
}
}
void disarm() {
- mNode = 0;
+ mOMXNode = NULL;
}
private:
sp<Harness> mHarness;
- IOMX::node_id mNode;
+ sp<IOMXNode> mOMXNode;
NodeReaper(const NodeReaper &);
NodeReaper &operator=(const NodeReaper &);
@@ -264,23 +280,23 @@
}
sp<MemoryDealer> dealer = new MemoryDealer(16 * 1024 * 1024, "OMXHarness");
- IOMX::node_id node;
- status_t err =
- mOMX->allocateNode(componentName, this, NULL, &node);
+ sp<CodecObserver> observer = new CodecObserver(this, ++mCurGeneration);
+
+ status_t err = mOMX->allocateNode(componentName, observer, &mOMXNode);
EXPECT_SUCCESS(err, "allocateNode");
- NodeReaper reaper(this, node);
+ NodeReaper reaper(this, mOMXNode);
- err = setRole(node, componentRole);
+ err = setRole(componentRole);
EXPECT_SUCCESS(err, "setRole");
// Initiate transition Loaded->Idle
- err = mOMX->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle);
+ err = mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle);
EXPECT_SUCCESS(err, "sendCommand(go-to-Idle)");
omx_message msg;
- err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+ err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
// Make sure node doesn't just transition to idle before we are done
// allocating all input and output buffers.
EXPECT(err == TIMED_OUT,
@@ -289,17 +305,17 @@
// Now allocate buffers.
Vector<Buffer> inputBuffers;
- err = allocatePortBuffers(dealer, node, 0, &inputBuffers);
+ err = allocatePortBuffers(dealer, 0, &inputBuffers);
EXPECT_SUCCESS(err, "allocatePortBuffers(input)");
- err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+ err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
CHECK_EQ(err, (status_t)TIMED_OUT);
Vector<Buffer> outputBuffers;
- err = allocatePortBuffers(dealer, node, 1, &outputBuffers);
+ err = allocatePortBuffers(dealer, 1, &outputBuffers);
EXPECT_SUCCESS(err, "allocatePortBuffers(output)");
- err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+ err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
EXPECT(err == OK
&& msg.type == omx_message::EVENT
&& msg.u.event_data.event == OMX_EventCmdComplete
@@ -309,10 +325,10 @@
"after all input and output buffers were allocated.");
// Initiate transition Idle->Executing
- err = mOMX->sendCommand(node, OMX_CommandStateSet, OMX_StateExecuting);
+ err = mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateExecuting);
EXPECT_SUCCESS(err, "sendCommand(go-to-Executing)");
- err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+ err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
EXPECT(err == OK
&& msg.type == omx_message::EVENT
&& msg.u.event_data.event == OMX_EventCmdComplete
@@ -322,17 +338,17 @@
"executing state.");
for (size_t i = 0; i < outputBuffers.size(); ++i) {
- err = mOMX->fillBuffer(node, outputBuffers[i].mID);
+ err = mOMXNode->fillBuffer(outputBuffers[i].mID);
EXPECT_SUCCESS(err, "fillBuffer");
outputBuffers.editItemAt(i).mFlags |= kBufferBusy;
}
- err = mOMX->sendCommand(node, OMX_CommandFlush, 1);
+ err = mOMXNode->sendCommand(OMX_CommandFlush, 1);
EXPECT_SUCCESS(err, "sendCommand(flush-output-port)");
err = dequeueMessageForNodeIgnoringBuffers(
- node, &inputBuffers, &outputBuffers, &msg, DEFAULT_TIMEOUT);
+ &inputBuffers, &outputBuffers, &msg, DEFAULT_TIMEOUT);
EXPECT(err == OK
&& msg.type == omx_message::EVENT
&& msg.u.event_data.event == OMX_EventCmdComplete
@@ -347,18 +363,18 @@
}
for (size_t i = 0; i < outputBuffers.size(); ++i) {
- err = mOMX->fillBuffer(node, outputBuffers[i].mID);
+ err = mOMXNode->fillBuffer(outputBuffers[i].mID);
EXPECT_SUCCESS(err, "fillBuffer");
outputBuffers.editItemAt(i).mFlags |= kBufferBusy;
}
// Initiate transition Executing->Idle
- err = mOMX->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle);
+ err = mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle);
EXPECT_SUCCESS(err, "sendCommand(go-to-Idle)");
err = dequeueMessageForNodeIgnoringBuffers(
- node, &inputBuffers, &outputBuffers, &msg, DEFAULT_TIMEOUT);
+ &inputBuffers, &outputBuffers, &msg, DEFAULT_TIMEOUT);
EXPECT(err == OK
&& msg.type == omx_message::EVENT
&& msg.u.event_data.event == OMX_EventCmdComplete
@@ -382,28 +398,28 @@
}
// Initiate transition Idle->Loaded
- err = mOMX->sendCommand(node, OMX_CommandStateSet, OMX_StateLoaded);
+ err = mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateLoaded);
EXPECT_SUCCESS(err, "sendCommand(go-to-Loaded)");
// Make sure node doesn't just transition to loaded before we are done
// freeing all input and output buffers.
- err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+ err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
CHECK_EQ(err, (status_t)TIMED_OUT);
for (size_t i = 0; i < inputBuffers.size(); ++i) {
- err = mOMX->freeBuffer(node, 0, inputBuffers[i].mID);
+ err = mOMXNode->freeBuffer(0, inputBuffers[i].mID);
EXPECT_SUCCESS(err, "freeBuffer");
}
- err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+ err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
CHECK_EQ(err, (status_t)TIMED_OUT);
for (size_t i = 0; i < outputBuffers.size(); ++i) {
- err = mOMX->freeBuffer(node, 1, outputBuffers[i].mID);
+ err = mOMXNode->freeBuffer(1, outputBuffers[i].mID);
EXPECT_SUCCESS(err, "freeBuffer");
}
- err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+ err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
EXPECT(err == OK
&& msg.type == omx_message::EVENT
&& msg.u.event_data.event == OMX_EventCmdComplete
@@ -412,12 +428,12 @@
"Component did not properly transition to from idle to "
"loaded state after freeing all input and output buffers.");
- err = mOMX->freeNode(node);
+ err = mOMXNode->freeNode();
EXPECT_SUCCESS(err, "freeNode");
reaper.disarm();
- node = 0;
+ mOMXNode = NULL;
return OK;
}
diff --git a/media/libstagefright/omx/tests/OMXHarness.h b/media/libstagefright/omx/tests/OMXHarness.h
index 1ebf3aa..0fe00a6 100644
--- a/media/libstagefright/omx/tests/OMXHarness.h
+++ b/media/libstagefright/omx/tests/OMXHarness.h
@@ -29,7 +29,7 @@
class MemoryDealer;
-struct Harness : public BnOMXObserver {
+struct Harness : public RefBase {
enum BufferFlags {
kBufferBusy = 1
};
@@ -43,25 +43,21 @@
status_t initCheck() const;
- status_t dequeueMessageForNode(
- IOMX::node_id node, omx_message *msg, int64_t timeoutUs = -1);
+ status_t dequeueMessageForNode(omx_message *msg, int64_t timeoutUs = -1);
status_t dequeueMessageForNodeIgnoringBuffers(
- IOMX::node_id node,
Vector<Buffer> *inputBuffers,
Vector<Buffer> *outputBuffers,
omx_message *msg, int64_t timeoutUs = -1);
status_t getPortDefinition(
- IOMX::node_id node, OMX_U32 portIndex,
- OMX_PARAM_PORTDEFINITIONTYPE *def);
+ OMX_U32 portIndex, OMX_PARAM_PORTDEFINITIONTYPE *def);
status_t allocatePortBuffers(
const sp<MemoryDealer> &dealer,
- IOMX::node_id node, OMX_U32 portIndex,
- Vector<Buffer> *buffers);
+ OMX_U32 portIndex, Vector<Buffer> *buffers);
- status_t setRole(IOMX::node_id node, const char *role);
+ status_t setRole(const char *role);
status_t testStateTransitions(
const char *componentName, const char *componentRole);
@@ -74,20 +70,22 @@
status_t testAll();
- virtual void onMessages(const std::list<omx_message> &messages);
-
protected:
virtual ~Harness();
private:
friend struct NodeReaper;
+ struct CodecObserver;
Mutex mLock;
status_t mInitCheck;
sp<IOMX> mOMX;
+ sp<IOMXNode> mOMXNode;
List<omx_message> mMessageQueue;
Condition mMessageAddedCondition;
+ int32_t mLastMsgGeneration;
+ int32_t mCurGeneration;
status_t initOMX();
@@ -96,6 +94,8 @@
Vector<Buffer> *inputBuffers,
Vector<Buffer> *outputBuffers);
+ void handleMessages(int32_t gen, const std::list<omx_message> &messages);
+
Harness(const Harness &);
Harness &operator=(const Harness &);
};
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index 8b0331a..325084c 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -17,7 +17,6 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "ASessionDescription"
#include <utils/Log.h>
-#include <cutils/log.h>
#include "ASessionDescription.h"
@@ -212,7 +211,7 @@
*PT = x;
- char key[32];
+ char key[20];
snprintf(key, sizeof(key), "a=rtpmap:%lu", x);
if (findAttribute(index, key, desc)) {
snprintf(key, sizeof(key), "a=fmtp:%lu", x);
@@ -231,11 +230,8 @@
*width = 0;
*height = 0;
- char key[33];
+ char key[20];
snprintf(key, sizeof(key), "a=framesize:%lu", PT);
- if (PT > 9999999) {
- android_errorWriteLog(0x534e4554, "25747670");
- }
AString value;
if (!findAttribute(index, key, &value)) {
return false;
diff --git a/media/libstagefright/rtsp/Android.mk b/media/libstagefright/rtsp/Android.mk
index 35301ce..3472e49 100644
--- a/media/libstagefright/rtsp/Android.mk
+++ b/media/libstagefright/rtsp/Android.mk
@@ -32,7 +32,6 @@
endif
LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
@@ -58,7 +57,6 @@
$(TOP)/frameworks/native/include/media/openmax
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
LOCAL_MODULE_TAGS := optional
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 76e2e6e..5505aa4 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -25,6 +25,7 @@
#endif
#include <utils/Log.h>
+#include <cutils/properties.h> // for property_get
#include "APacketSource.h"
#include "ARTPConnection.h"
@@ -807,11 +808,7 @@
result = UNKNOWN_ERROR;
} else {
parsePlayResponse(response);
-
- sp<AMessage> timeout = new AMessage('tiou', this);
- mCheckTimeoutGeneration++;
- timeout->setInt32("tioucheck", mCheckTimeoutGeneration);
- timeout->post(kStartupTimeoutUs);
+ postTimeout();
}
}
@@ -1153,10 +1150,7 @@
// Post new timeout in order to make sure to use
// fake timestamps if no new Sender Reports arrive
- sp<AMessage> timeout = new AMessage('tiou', this);
- mCheckTimeoutGeneration++;
- timeout->setInt32("tioucheck", mCheckTimeoutGeneration);
- timeout->post(kStartupTimeoutUs);
+ postTimeout();
}
}
@@ -1248,10 +1242,7 @@
// Start new timeoutgeneration to avoid getting timeout
// before PLAY response arrive
- sp<AMessage> timeout = new AMessage('tiou', this);
- mCheckTimeoutGeneration++;
- timeout->setInt32("tioucheck", mCheckTimeoutGeneration);
- timeout->post(kStartupTimeoutUs);
+ postTimeout();
int64_t timeUs;
CHECK(msg->findInt64("time", &timeUs));
@@ -1305,10 +1296,7 @@
// Post new timeout in order to make sure to use
// fake timestamps if no new Sender Reports arrive
- sp<AMessage> timeout = new AMessage('tiou', this);
- mCheckTimeoutGeneration++;
- timeout->setInt32("tioucheck", mCheckTimeoutGeneration);
- timeout->post(kStartupTimeoutUs);
+ postTimeout();
ssize_t i = response->mHeaders.indexOfKey("rtp-info");
CHECK_GE(i, 0);
@@ -1964,6 +1952,16 @@
msg->post();
}
+ void postTimeout() {
+ sp<AMessage> timeout = new AMessage('tiou', this);
+ mCheckTimeoutGeneration++;
+ timeout->setInt32("tioucheck", mCheckTimeoutGeneration);
+
+ int64_t startupTimeoutUs;
+ startupTimeoutUs = property_get_int64("media.rtsp.timeout-us", kStartupTimeoutUs);
+ timeout->post(startupTimeoutUs);
+ }
+
DISALLOW_EVIL_CONSTRUCTORS(MyHandler);
};
diff --git a/media/libstagefright/tests/Android.mk b/media/libstagefright/tests/Android.mk
index d1c9d36..a93770a 100644
--- a/media/libstagefright/tests/Android.mk
+++ b/media/libstagefright/tests/Android.mk
@@ -33,7 +33,6 @@
$(TOP)/frameworks/native/include/media/hardware \
LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
LOCAL_32_BIT_ONLY := true
@@ -65,7 +64,6 @@
$(TOP)/frameworks/native/include/media/openmax \
LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
include $(BUILD_NATIVE_TEST)
@@ -95,7 +93,6 @@
LOCAL_32_BIT_ONLY := true
LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
include $(BUILD_NATIVE_TEST)
diff --git a/media/libstagefright/timedtext/Android.mk b/media/libstagefright/timedtext/Android.mk
index 8d128b8..0b0facf 100644
--- a/media/libstagefright/timedtext/Android.mk
+++ b/media/libstagefright/timedtext/Android.mk
@@ -5,7 +5,6 @@
TextDescriptions.cpp \
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
LOCAL_C_INCLUDES:= \
diff --git a/media/libstagefright/webm/Android.mk b/media/libstagefright/webm/Android.mk
index ce580ae..096fd07 100644
--- a/media/libstagefright/webm/Android.mk
+++ b/media/libstagefright/webm/Android.mk
@@ -4,7 +4,6 @@
LOCAL_CPPFLAGS += -D__STDINT_LIMITS
LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow
LOCAL_SRC_FILES:= EbmlUtil.cpp \
diff --git a/media/libstagefright/wifi-display/Android.mk b/media/libstagefright/wifi-display/Android.mk
index ae4ac90..902f66c 100644
--- a/media/libstagefright/wifi-display/Android.mk
+++ b/media/libstagefright/wifi-display/Android.mk
@@ -32,7 +32,6 @@
libutils \
LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
LOCAL_MODULE:= libstagefright_wfd
diff --git a/media/libstagefright/wifi-display/source/Converter.cpp b/media/libstagefright/wifi-display/source/Converter.cpp
index 471152e..273af18 100644
--- a/media/libstagefright/wifi-display/source/Converter.cpp
+++ b/media/libstagefright/wifi-display/source/Converter.cpp
@@ -26,6 +26,7 @@
#include <cutils/properties.h>
#include <gui/Surface.h>
#include <media/ICrypto.h>
+#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -720,7 +721,7 @@
#endif
sp<ABuffer> buffer;
- sp<ABuffer> outbuf = mEncoderOutputBuffers.itemAt(bufferIndex);
+ sp<MediaCodecBuffer> outbuf = mEncoderOutputBuffers.itemAt(bufferIndex);
if (outbuf->meta()->findPointer("handle", (void**)&handle) &&
handle != NULL) {
diff --git a/media/libstagefright/wifi-display/source/Converter.h b/media/libstagefright/wifi-display/source/Converter.h
index b182990..ad95ab5 100644
--- a/media/libstagefright/wifi-display/source/Converter.h
+++ b/media/libstagefright/wifi-display/source/Converter.h
@@ -25,6 +25,7 @@
struct ABuffer;
class IGraphicBufferProducer;
struct MediaCodec;
+class MediaCodecBuffer;
#define ENABLE_SILENCE_DETECTION 0
@@ -106,8 +107,8 @@
sp<IGraphicBufferProducer> mGraphicBufferProducer;
- Vector<sp<ABuffer> > mEncoderInputBuffers;
- Vector<sp<ABuffer> > mEncoderOutputBuffers;
+ Vector<sp<MediaCodecBuffer> > mEncoderInputBuffers;
+ Vector<sp<MediaCodecBuffer> > mEncoderOutputBuffers;
List<size_t> mAvailEncoderInputIndices;
diff --git a/media/libstagefright/yuv/Android.mk b/media/libstagefright/yuv/Android.mk
index f2fd3be..08d202b 100644
--- a/media/libstagefright/yuv/Android.mk
+++ b/media/libstagefright/yuv/Android.mk
@@ -13,7 +13,6 @@
LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
LOCAL_SANITIZE := signed-integer-overflow
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index 0381edf..0e9bc34 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -16,17 +16,38 @@
#define LOG_TAG "MtpDataPacket"
+#include "MtpDataPacket.h"
+
+#include <algorithm>
+#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
-#include <fcntl.h>
-
#include <usbhost/usbhost.h>
-
-#include "MtpDataPacket.h"
#include "MtpStringBuffer.h"
namespace android {
+namespace {
+// Reads the exact |count| bytes from |fd| to |buf|.
+// Returns |count| if it succeed to read the bytes. Otherwise returns -1. If it reaches EOF, the
+// function regards it as an error.
+ssize_t readExactBytes(int fd, void* buf, size_t count) {
+ if (count > SSIZE_MAX) {
+ return -1;
+ }
+ size_t read_count = 0;
+ while (read_count < count) {
+ int result = read(fd, static_cast<int8_t*>(buf) + read_count, count - read_count);
+ // Assume that EOF is error.
+ if (result <= 0) {
+ return -1;
+ }
+ read_count += result;
+ }
+ return read_count == count ? count : -1;
+}
+} // namespace
+
MtpDataPacket::MtpDataPacket()
: MtpPacket(MTP_BUFFER_SIZE), // MAX_USBFS_BUFFER_SIZE
mOffset(MTP_CONTAINER_HEADER_SIZE)
@@ -511,29 +532,104 @@
return length;
}
-int MtpDataPacket::writeDataHeader(struct usb_request *request, uint32_t length) {
- MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length);
- MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
- request->buffer = mBuffer;
- request->buffer_length = MTP_CONTAINER_HEADER_SIZE;
- int ret = transfer(request);
- return (ret < 0 ? ret : 0);
-}
+int MtpDataPacket::write(struct usb_request *request, UrbPacketDivisionMode divisionMode) {
+ if (mPacketSize < MTP_CONTAINER_HEADER_SIZE || mPacketSize > MTP_BUFFER_SIZE) {
+ ALOGE("Illegal packet size.");
+ return -1;
+ }
-int MtpDataPacket::write(struct usb_request *request) {
MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
- request->buffer = mBuffer;
- request->buffer_length = mPacketSize;
- int ret = transfer(request);
- return (ret < 0 ? ret : 0);
+
+ size_t processedBytes = 0;
+ while (processedBytes < mPacketSize) {
+ const size_t write_size =
+ processedBytes == 0 && divisionMode == FIRST_PACKET_ONLY_HEADER ?
+ MTP_CONTAINER_HEADER_SIZE : mPacketSize - processedBytes;
+ request->buffer = mBuffer + processedBytes;
+ request->buffer_length = write_size;
+ const int result = transfer(request);
+ if (result < 0) {
+ ALOGE("Failed to write bytes to the device.");
+ return -1;
+ }
+ processedBytes += result;
+ }
+
+ return processedBytes == mPacketSize ? processedBytes : -1;
}
-int MtpDataPacket::write(struct usb_request *request, void* buffer, uint32_t length) {
- request->buffer = buffer;
- request->buffer_length = length;
- int ret = transfer(request);
- return (ret < 0 ? ret : 0);
+int MtpDataPacket::write(struct usb_request *request,
+ UrbPacketDivisionMode divisionMode,
+ int fd,
+ size_t payloadSize) {
+ // Obtain the greatest multiple of minimum packet size that is not greater than
+ // MTP_BUFFER_SIZE.
+ if (request->max_packet_size <= 0) {
+ ALOGE("Cannot determine bulk transfer size due to illegal max packet size %d.",
+ request->max_packet_size);
+ return -1;
+ }
+ const size_t maxBulkTransferSize =
+ MTP_BUFFER_SIZE - (MTP_BUFFER_SIZE % request->max_packet_size);
+ const size_t containerLength = payloadSize + MTP_CONTAINER_HEADER_SIZE;
+ size_t processedBytes = 0;
+ bool readError = false;
+
+ // Bind the packet with given request.
+ request->buffer = mBuffer;
+ allocate(maxBulkTransferSize);
+
+ while (processedBytes < containerLength) {
+ size_t bulkTransferSize = 0;
+
+ // prepare header.
+ const bool headerSent = processedBytes != 0;
+ if (!headerSent) {
+ MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, containerLength);
+ MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
+ bulkTransferSize += MTP_CONTAINER_HEADER_SIZE;
+ }
+
+ // Prepare payload.
+ if (headerSent || divisionMode == FIRST_PACKET_HAS_PAYLOAD) {
+ const size_t processedPayloadBytes =
+ headerSent ? processedBytes - MTP_CONTAINER_HEADER_SIZE : 0;
+ const size_t maxRead = payloadSize - processedPayloadBytes;
+ const size_t maxWrite = maxBulkTransferSize - bulkTransferSize;
+ const size_t bulkTransferPayloadSize = std::min(maxRead, maxWrite);
+ // prepare payload.
+ if (!readError) {
+ const ssize_t result = readExactBytes(
+ fd,
+ mBuffer + bulkTransferSize,
+ bulkTransferPayloadSize);
+ if (result < 0) {
+ ALOGE("Found an error while reading data from FD. Send 0 data instead.");
+ readError = true;
+ }
+ }
+ if (readError) {
+ memset(mBuffer + bulkTransferSize, 0, bulkTransferPayloadSize);
+ }
+ bulkTransferSize += bulkTransferPayloadSize;
+ }
+
+ // Bulk transfer.
+ mPacketSize = bulkTransferSize;
+ request->buffer_length = bulkTransferSize;
+ const int result = transfer(request);
+ if (result != static_cast<ssize_t>(bulkTransferSize)) {
+ // Cannot recover writing error.
+ ALOGE("Found an error while write data to MtpDevice.");
+ return -1;
+ }
+
+ // Update variables.
+ processedBytes += bulkTransferSize;
+ }
+
+ return readError ? -1 : processedBytes;
}
#endif // MTP_HOST
diff --git a/media/mtp/MtpDataPacket.h b/media/mtp/MtpDataPacket.h
index 6240f28..82e0ee4 100644
--- a/media/mtp/MtpDataPacket.h
+++ b/media/mtp/MtpDataPacket.h
@@ -93,7 +93,6 @@
inline void putEmptyString() { putUInt8(0); }
inline void putEmptyArray() { putUInt32(0); }
-
#ifdef MTP_DEVICE
// fill our buffer with data from the given file descriptor
int read(int fd);
@@ -110,9 +109,15 @@
int readDataWait(struct usb_device *device);
int readDataHeader(struct usb_request *ep);
- int writeDataHeader(struct usb_request *ep, uint32_t length);
- int write(struct usb_request *ep);
- int write(struct usb_request *ep, void* buffer, uint32_t length);
+ // Write a whole data packet with payload to the end point given by a request. |divisionMode|
+ // specifies whether to divide header and payload. See |UrbPacketDivisionMode| for meanings of
+ // each value. Return the number of bytes (including header size) sent to the device on success.
+ // Otherwise -1.
+ int write(struct usb_request *request, UrbPacketDivisionMode divisionMode);
+ // Similar to previous write method but it reads the payload from |fd|. If |size| is larger than
+ // MTP_BUFFER_SIZE, the data will be sent by multiple bulk transfer requests.
+ int write(struct usb_request *request, UrbPacketDivisionMode divisionMode,
+ int fd, size_t size);
#endif
inline bool hasData() const { return mPacketSize > MTP_CONTAINER_HEADER_SIZE; }
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index bd89a51..e3d2ec6 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -220,7 +220,10 @@
mTransactionID(0),
mReceivedResponse(false),
mProcessingEvent(false),
- mCurrentEventHandle(0)
+ mCurrentEventHandle(0),
+ mLastSendObjectInfoTransactionID(0),
+ mLastSendObjectInfoObjectHandle(0),
+ mPacketDivisionMode(FIRST_PACKET_HAS_PAYLOAD)
{
mRequestIn1 = usb_request_new(device, ep_in);
mRequestIn2 = usb_request_new(device, ep_in);
@@ -490,6 +493,8 @@
if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) {
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK) {
+ mLastSendObjectInfoTransactionID = mRequest.getTransactionID();
+ mLastSendObjectInfoObjectHandle = mResponse.getParameter(3);
info->mStorageID = mResponse.getParameter(1);
info->mParent = mResponse.getParameter(2);
info->mHandle = mResponse.getParameter(3);
@@ -502,31 +507,21 @@
bool MtpDevice::sendObject(MtpObjectHandle handle, int size, int srcFD) {
Mutex::Autolock autoLock(mMutex);
- int remaining = size;
- mRequest.reset();
- mRequest.setParameter(1, handle);
- bool error = false;
- if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
- // send data header
- writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining);
-
- // USB writes greater than 16K don't work
- char buffer[MTP_BUFFER_SIZE];
- while (remaining > 0) {
- int count = read(srcFD, buffer, sizeof(buffer));
- if (count > 0) {
- if (mData.write(mRequestOut, buffer, count) < 0) {
- error = true;
- }
- // FIXME check error
- remaining -= count;
- } else {
- break;
- }
- }
+ if (mLastSendObjectInfoTransactionID + 1 != mTransactionID ||
+ mLastSendObjectInfoObjectHandle != handle) {
+ ALOGE("A sendObject request must follow the sendObjectInfo request.");
+ return false;
}
- MtpResponseCode ret = readResponse();
- return (remaining == 0 && ret == MTP_RESPONSE_OK && !error);
+
+ mRequest.reset();
+ if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
+ mData.setOperationCode(mRequest.getOperationCode());
+ mData.setTransactionID(mRequest.getTransactionID());
+ const int writeResult = mData.write(mRequestOut, mPacketDivisionMode, srcFD, size);
+ const MtpResponseCode ret = readResponse();
+ return ret == MTP_RESPONSE_OK && writeResult > 0;
+ }
+ return false;
}
bool MtpDevice::deleteObject(MtpObjectHandle handle) {
@@ -698,8 +693,8 @@
return false;
}
- // If object size 0 byte, the remote device can reply response packet
- // without sending any data packets.
+ // If object size 0 byte, the remote device may reply a response packet without sending any data
+ // packets.
if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) {
mResponse.copyFrom(mData);
return mResponse.getResponseCode() == MTP_RESPONSE_OK;
@@ -722,6 +717,14 @@
{
int initialDataLength = 0;
void* const initialData = mData.getData(&initialDataLength);
+ if (fullLength > MTP_CONTAINER_HEADER_SIZE && initialDataLength == 0) {
+ // According to the MTP spec, the responder (MTP device) can choose two ways of sending
+ // data. a) The first packet contains the head and as much of the payload as possible
+ // b) The first packet contains only the header. The initiator (MTP host) needs
+ // to remember which way the responder used, and send upcoming data in the same way.
+ ALOGD("Found short packet that contains only a header.");
+ mPacketDivisionMode = FIRST_PACKET_ONLY_HEADER;
+ }
if (initialData) {
if (initialDataLength > 0) {
if (!callback(initialData, offset, initialDataLength, clientData)) {
@@ -845,7 +848,7 @@
ALOGV("sendData\n");
mData.setOperationCode(mRequest.getOperationCode());
mData.setTransactionID(mRequest.getTransactionID());
- int ret = mData.write(mRequestOut);
+ int ret = mData.write(mRequestOut, mPacketDivisionMode);
mData.dump();
return (ret >= 0);
}
@@ -872,12 +875,6 @@
}
}
-bool MtpDevice::writeDataHeader(MtpOperationCode operation, int dataLength) {
- mData.setOperationCode(operation);
- mData.setTransactionID(mRequest.getTransactionID());
- return (!mData.writeDataHeader(mRequestOut, dataLength));
-}
-
MtpResponseCode MtpDevice::readResponse() {
ALOGV("readResponse\n");
if (mReceivedResponse) {
diff --git a/media/mtp/MtpDevice.h b/media/mtp/MtpDevice.h
index 4be44cf..a9a3e0e 100644
--- a/media/mtp/MtpDevice.h
+++ b/media/mtp/MtpDevice.h
@@ -62,11 +62,18 @@
bool mProcessingEvent;
int mCurrentEventHandle;
+ // to check if a sendObject request follows the last sendObjectInfo request.
+ MtpTransactionID mLastSendObjectInfoTransactionID;
+ MtpObjectHandle mLastSendObjectInfoObjectHandle;
+
// to ensure only one MTP transaction at a time
Mutex mMutex;
Mutex mEventMutex;
Mutex mEventMutexForInterrupt;
+ // Remember the device's packet division mode.
+ UrbPacketDivisionMode mPacketDivisionMode;
+
public:
typedef bool (*ReadObjectCallback)
(void* data, uint32_t offset, uint32_t length, void* clientData);
@@ -100,7 +107,7 @@
bool sendObject(MtpObjectHandle handle, int size, int srcFD);
bool deleteObject(MtpObjectHandle handle);
MtpObjectHandle getParent(MtpObjectHandle handle);
- MtpObjectHandle getStorageID(MtpObjectHandle handle);
+ MtpStorageID getStorageID(MtpObjectHandle handle);
MtpObjectPropertyList* getObjectPropsSupported(MtpObjectFormat format);
diff --git a/media/mtp/MtpDeviceInfo.cpp b/media/mtp/MtpDeviceInfo.cpp
index 3e1dff7..3d5cb06 100644
--- a/media/mtp/MtpDeviceInfo.cpp
+++ b/media/mtp/MtpDeviceInfo.cpp
@@ -69,6 +69,7 @@
if (!packet.getString(string)) return false;
mVendorExtensionDesc = strdup((const char *)string);
+ if (!mVendorExtensionDesc) return false;
if (!packet.getUInt16(mFunctionalMode)) return false;
mOperations = packet.getAUInt16();
@@ -84,12 +85,16 @@
if (!packet.getString(string)) return false;
mManufacturer = strdup((const char *)string);
+ if (!mManufacturer) return false;
if (!packet.getString(string)) return false;
mModel = strdup((const char *)string);
+ if (!mModel) return false;
if (!packet.getString(string)) return false;
mVersion = strdup((const char *)string);
+ if (!mVersion) return false;
if (!packet.getString(string)) return false;
mSerial = strdup((const char *)string);
+ if (!mSerial) return false;
return true;
}
diff --git a/media/mtp/MtpObjectInfo.cpp b/media/mtp/MtpObjectInfo.cpp
index 0573104..43b745f 100644
--- a/media/mtp/MtpObjectInfo.cpp
+++ b/media/mtp/MtpObjectInfo.cpp
@@ -77,6 +77,7 @@
if (!packet.getString(string)) return false;
mName = strdup((const char *)string);
+ if (!mName) return false;
if (!packet.getString(string)) return false;
if (parseDateTime((const char*)string, time))
@@ -88,6 +89,7 @@
if (!packet.getString(string)) return false;
mKeywords = strdup((const char *)string);
+ if (!mKeywords) return false;
return true;
}
diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp
index 35ecb4f..3dd4248 100644
--- a/media/mtp/MtpPacket.cpp
+++ b/media/mtp/MtpPacket.cpp
@@ -70,8 +70,8 @@
char* bufptr = buffer;
for (size_t i = 0; i < mPacketSize; i++) {
- sprintf(bufptr, "%02X ", mBuffer[i]);
- bufptr += strlen(bufptr);
+ bufptr += snprintf(bufptr, sizeof(buffer) - (bufptr - buffer), "%02X ",
+ mBuffer[i]);
if (i % DUMP_BYTES_PER_ROW == (DUMP_BYTES_PER_ROW - 1)) {
ALOGV("%s", buffer);
bufptr = buffer;
diff --git a/media/mtp/MtpStorageInfo.cpp b/media/mtp/MtpStorageInfo.cpp
index 5d4ebbf..8801a38 100644
--- a/media/mtp/MtpStorageInfo.cpp
+++ b/media/mtp/MtpStorageInfo.cpp
@@ -58,8 +58,10 @@
if (!packet.getString(string)) return false;
mStorageDescription = strdup((const char *)string);
+ if (!mStorageDescription) return false;
if (!packet.getString(string)) return false;
mVolumeIdentifier = strdup((const char *)string);
+ if (!mVolumeIdentifier) return false;
return true;
}
diff --git a/media/mtp/MtpTypes.h b/media/mtp/MtpTypes.h
index 720c854..c749c66 100644
--- a/media/mtp/MtpTypes.h
+++ b/media/mtp/MtpTypes.h
@@ -73,6 +73,13 @@
typedef String8 MtpString;
+enum UrbPacketDivisionMode {
+ // First packet only contains a header.
+ FIRST_PACKET_ONLY_HEADER,
+ // First packet contains payload much as possible.
+ FIRST_PACKET_HAS_PAYLOAD
+};
+
}; // namespace android
#endif // _MTP_TYPES_H
diff --git a/media/ndk/NdkMediaCodec.cpp b/media/ndk/NdkMediaCodec.cpp
index 3d1eca1..22c90e2 100644
--- a/media/ndk/NdkMediaCodec.cpp
+++ b/media/ndk/NdkMediaCodec.cpp
@@ -30,10 +30,10 @@
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/MediaCodec.h>
#include <media/stagefright/MediaErrors.h>
+#include <media/MediaCodecBuffer.h>
using namespace android;
@@ -268,13 +268,17 @@
EXPORT
uint8_t* AMediaCodec_getInputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
- android::Vector<android::sp<android::ABuffer> > abufs;
+ android::Vector<android::sp<android::MediaCodecBuffer> > abufs;
if (mData->mCodec->getInputBuffers(&abufs) == 0) {
size_t n = abufs.size();
if (idx >= n) {
ALOGE("buffer index %zu out of range", idx);
return NULL;
}
+ if (abufs[idx] == NULL) {
+ ALOGE("buffer index %zu is NULL", idx);
+ return NULL;
+ }
if (out_size != NULL) {
*out_size = abufs[idx]->capacity();
}
@@ -286,7 +290,7 @@
EXPORT
uint8_t* AMediaCodec_getOutputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
- android::Vector<android::sp<android::ABuffer> > abufs;
+ android::Vector<android::sp<android::MediaCodecBuffer> > abufs;
if (mData->mCodec->getOutputBuffers(&abufs) == 0) {
size_t n = abufs.size();
if (idx >= n) {
diff --git a/media/ndk/NdkMediaDrm.cpp b/media/ndk/NdkMediaDrm.cpp
index be71f43..8d34ab0 100644
--- a/media/ndk/NdkMediaDrm.cpp
+++ b/media/ndk/NdkMediaDrm.cpp
@@ -99,11 +99,12 @@
break;
default:
ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
- return;
+ goto cleanup;
}
(*mListener)(mObj, &sessionId, ndkEventType, extra, data, dataSize);
+ cleanup:
delete [] sessionId.ptr;
delete [] data;
}
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index e7fc381..0fd8cdd 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -40,6 +40,7 @@
$(call include-path-for, audio-utils)
LOCAL_SHARED_LIBRARIES := \
+ libaudiohal \
libaudioresampler \
libaudiospdif \
libaudioutils \
@@ -50,9 +51,6 @@
libmedia \
libmediautils \
libnbaio \
- libhardware \
- libhardware_legacy \
- libeffects \
libpowermanager \
libserviceutility \
libsonic \
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 60093cc..c85d377 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -31,6 +31,9 @@
#include <utils/Log.h>
#include <utils/Trace.h>
#include <binder/Parcel.h>
+#include <media/audiohal/DeviceHalInterface.h>
+#include <media/audiohal/DevicesFactoryHalInterface.h>
+#include <media/audiohal/EffectsFactoryHalInterface.h>
#include <memunreachable/memunreachable.h>
#include <utils/String16.h>
#include <utils/threads.h>
@@ -40,7 +43,6 @@
#include <cutils/properties.h>
#include <system/audio.h>
-#include <hardware/audio.h>
#include "AudioMixer.h"
#include "AudioFlinger.h"
@@ -48,7 +50,6 @@
#include <media/AudioResamplerPublic.h>
-#include <media/EffectsFactoryApi.h>
#include <audio_effects/effect_visualizer.h>
#include <audio_effects/effect_ns.h>
#include <audio_effects/effect_aec.h>
@@ -85,6 +86,7 @@
static const char kDeadlockedString[] = "AudioFlinger may be deadlocked\n";
static const char kHardwareLockedString[] = "Hardware lock is taken\n";
static const char kClientLockedString[] = "Client lock is taken\n";
+static const char kNoEffectsFactory[] = "Effects Factory is absent\n";
nsecs_t AudioFlinger::mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
@@ -141,35 +143,6 @@
return "unknown";
}
-static int load_audio_interface(const char *if_name, audio_hw_device_t **dev)
-{
- const hw_module_t *mod;
- int rc;
-
- rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
- ALOGE_IF(rc, "%s couldn't load audio hw module %s.%s (%s)", __func__,
- AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
- if (rc) {
- goto out;
- }
- rc = audio_hw_device_open(mod, dev);
- ALOGE_IF(rc, "%s couldn't open audio hw device in %s.%s (%s)", __func__,
- AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
- if (rc) {
- goto out;
- }
- if ((*dev)->common.version < AUDIO_DEVICE_API_VERSION_MIN) {
- ALOGE("%s wrong audio hw device version %04x", __func__, (*dev)->common.version);
- rc = BAD_VALUE;
- goto out;
- }
- return 0;
-
-out:
- *dev = NULL;
- return rc;
-}
-
// ----------------------------------------------------------------------------
AudioFlinger::AudioFlinger()
@@ -205,6 +178,9 @@
// in bad state, reset the state upon service start.
BatteryNotifier::getInstance().noteResetAudio();
+ mDevicesFactoryHal = DevicesFactoryHalInterface::create();
+ mEffectsFactoryHal = EffectsFactoryHalInterface::create();
+
#ifdef TEE_SINK
char value[PROPERTY_VALUE_MAX];
(void) property_get("ro.debuggable", value, "0");
@@ -263,7 +239,6 @@
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
// no mHardwareLock needed, as there are no other references to this
- audio_hw_device_close(mAudioHwDevs.valueAt(i)->hwDevice());
delete mAudioHwDevs.valueAt(i);
}
@@ -302,10 +277,12 @@
// then try to find a module supporting the requested device.
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
AudioHwDevice *audioHwDevice = mAudioHwDevs.valueAt(i);
- audio_hw_device_t *dev = audioHwDevice->hwDevice();
- if ((dev->get_supported_devices != NULL) &&
- (dev->get_supported_devices(dev) & devices) == devices)
+ sp<DeviceHalInterface> dev = audioHwDevice->hwDevice();
+ uint32_t supportedDevices;
+ if (dev->getSupportedDevices(&supportedDevices) == OK &&
+ (supportedDevices & devices) == devices) {
return audioHwDevice;
+ }
}
} else {
// check a match for the requested module handle
@@ -419,7 +396,12 @@
write(fd, result.string(), result.size());
}
- EffectDumpEffects(fd);
+ if (mEffectsFactoryHal != 0) {
+ mEffectsFactoryHal->dumpEffects(fd);
+ } else {
+ String8 result(kNoEffectsFactory);
+ write(fd, result.string(), result.size());
+ }
dumpClients(fd, args);
if (clientLocked) {
@@ -447,8 +429,8 @@
}
// dump all hardware devs
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
- audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
- dev->dump(dev, fd);
+ sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
+ dev->dump(fd);
}
#ifdef TEE_SINK
@@ -810,7 +792,7 @@
mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
if (dev->canSetMasterVolume()) {
- dev->hwDevice()->set_master_volume(dev->hwDevice(), value);
+ dev->hwDevice()->setMasterVolume(value);
}
mHardwareStatus = AUDIO_HW_IDLE;
}
@@ -847,9 +829,9 @@
{ // scope for the lock
AutoMutex lock(mHardwareLock);
- audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice();
+ sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
mHardwareStatus = AUDIO_HW_SET_MODE;
- ret = dev->set_mode(dev, mode);
+ ret = dev->setMode(mode);
mHardwareStatus = AUDIO_HW_IDLE;
}
@@ -878,8 +860,8 @@
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
- audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
- status_t result = dev->set_mic_mute(dev, state);
+ sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
+ status_t result = dev->setMicMute(state);
if (result != NO_ERROR) {
ret = result;
}
@@ -899,8 +881,8 @@
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
- audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
- status_t result = dev->get_mic_mute(dev, &state);
+ sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
+ status_t result = dev->getMicMute(&state);
if (result == NO_ERROR) {
mute = mute && state;
}
@@ -932,7 +914,7 @@
mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
if (dev->canSetMasterMute()) {
- dev->hwDevice()->set_master_mute(dev->hwDevice(), muted);
+ dev->hwDevice()->setMasterMute(muted);
}
mHardwareStatus = AUDIO_HW_IDLE;
}
@@ -1110,8 +1092,8 @@
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_HW_SET_PARAMETER;
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
- audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
- status_t result = dev->set_parameters(dev, keyValuePairs.string());
+ sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
+ status_t result = dev->setParameters(keyValuePairs);
// return success if at least one audio device accepts the parameters as not all
// HALs are requested to support all parameters. If no audio device supports the
// requested parameters, the last error is reported.
@@ -1192,16 +1174,16 @@
String8 out_s8;
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
- char *s;
+ String8 s;
+ status_t result;
{
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_HW_GET_PARAMETER;
- audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
- s = dev->get_parameters(dev, keys.string());
+ sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
+ result = dev->getParameters(keys, &s);
mHardwareStatus = AUDIO_HW_IDLE;
}
- out_s8 += String8(s ? s : "");
- free(s);
+ if (result == OK) out_s8 += s;
}
return out_s8;
}
@@ -1238,14 +1220,14 @@
proposed.channel_mask = channelMask;
proposed.format = format;
- audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice();
+ sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
size_t frames;
for (;;) {
// Note: config is currently a const parameter for get_input_buffer_size()
// but we use a copy from proposed in case config changes from the call.
config = proposed;
- frames = dev->get_input_buffer_size(dev, &config);
- if (frames != 0) {
+ status_t result = dev->getInputBufferSize(&config, &frames);
+ if (result == OK && frames != 0) {
break; // hal success, config is the result
}
// change one parameter of the configuration each iteration to a more "common" value
@@ -1292,9 +1274,9 @@
}
AutoMutex lock(mHardwareLock);
- audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice();
+ sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
mHardwareStatus = AUDIO_HW_SET_VOICE_VOLUME;
- ret = dev->set_voice_volume(dev, value);
+ ret = dev->setVoiceVolume(value);
mHardwareStatus = AUDIO_HW_IDLE;
return ret;
@@ -1632,16 +1614,16 @@
}
}
- audio_hw_device_t *dev;
+ sp<DeviceHalInterface> dev;
- int rc = load_audio_interface(name, &dev);
+ int rc = mDevicesFactoryHal->openDevice(name, &dev);
if (rc) {
ALOGE("loadHwModule() error %d loading module %s", rc, name);
return AUDIO_MODULE_HANDLE_NONE;
}
mHardwareStatus = AUDIO_HW_INIT;
- rc = dev->init_check(dev);
+ rc = dev->initCheck();
mHardwareStatus = AUDIO_HW_IDLE;
if (rc) {
ALOGE("loadHwModule() init check error %d for module %s", rc, name);
@@ -1659,32 +1641,26 @@
if (0 == mAudioHwDevs.size()) {
mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
- if (NULL != dev->get_master_volume) {
- float mv;
- if (OK == dev->get_master_volume(dev, &mv)) {
- mMasterVolume = mv;
- }
+ float mv;
+ if (OK == dev->getMasterVolume(&mv)) {
+ mMasterVolume = mv;
}
mHardwareStatus = AUDIO_HW_GET_MASTER_MUTE;
- if (NULL != dev->get_master_mute) {
- bool mm;
- if (OK == dev->get_master_mute(dev, &mm)) {
- mMasterMute = mm;
- }
+ bool mm;
+ if (OK == dev->getMasterMute(&mm)) {
+ mMasterMute = mm;
}
}
mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
- if ((NULL != dev->set_master_volume) &&
- (OK == dev->set_master_volume(dev, mMasterVolume))) {
+ if (OK == dev->setMasterVolume(mMasterVolume)) {
flags = static_cast<AudioHwDevice::Flags>(flags |
AudioHwDevice::AHWD_CAN_SET_MASTER_VOLUME);
}
mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
- if ((NULL != dev->set_master_mute) &&
- (OK == dev->set_master_mute(dev, mMasterMute))) {
+ if (OK == dev->setMasterMute(mMasterMute)) {
flags = static_cast<AudioHwDevice::Flags>(flags |
AudioHwDevice::AHWD_CAN_SET_MASTER_MUTE);
}
@@ -1695,8 +1671,7 @@
audio_module_handle_t handle = (audio_module_handle_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_MODULE);
mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags));
- ALOGI("loadHwModule() Loaded %s audio interface from %s (%s) handle %d",
- name, dev->common.module->name, dev->common.module->id, handle);
+ ALOGI("loadHwModule() Loaded %s audio interface, handle %d", name, handle);
return handle;
@@ -1746,13 +1721,15 @@
return mHwAvSyncIds.valueAt(index);
}
- audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice();
+ sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
if (dev == NULL) {
return AUDIO_HW_SYNC_INVALID;
}
- char *reply = dev->get_parameters(dev, AUDIO_PARAMETER_HW_AV_SYNC);
- AudioParameter param = AudioParameter(String8(reply));
- free(reply);
+ String8 reply;
+ AudioParameter param;
+ if (dev->getParameters(String8(AUDIO_PARAMETER_HW_AV_SYNC), &reply) == OK) {
+ param = AudioParameter(reply);
+ }
int value;
if (param.getInt(String8(AUDIO_PARAMETER_HW_AV_SYNC), value) != NO_ERROR) {
@@ -1937,7 +1914,7 @@
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_HW_SET_MODE;
- mPrimaryHardwareDev->hwDevice()->set_mode(mPrimaryHardwareDev->hwDevice(), mMode);
+ mPrimaryHardwareDev->hwDevice()->setMode(mMode);
mHardwareStatus = AUDIO_HW_IDLE;
}
return NO_ERROR;
@@ -2033,7 +2010,6 @@
AudioStreamOut *out = thread->clearOutput();
ALOG_ASSERT(out != NULL, "out shouldn't be NULL");
// from now on thread->mOutput is NULL
- out->hwDev()->close_output_stream(out->hwDev(), out->stream);
delete out;
}
@@ -2128,13 +2104,13 @@
}
audio_config_t halconfig = *config;
- audio_hw_device_t *inHwHal = inHwDev->hwDevice();
- audio_stream_in_t *inStream = NULL;
- status_t status = inHwHal->open_input_stream(inHwHal, *input, devices, &halconfig,
- &inStream, flags, address.string(), source);
+ sp<DeviceHalInterface> inHwHal = inHwDev->hwDevice();
+ sp<StreamInHalInterface> inStream;
+ status_t status = inHwHal->openInputStream(
+ *input, devices, &halconfig, flags, address.string(), source, &inStream);
ALOGV("openInput_l() openInputStream returned input %p, SamplingRate %d"
", Format %#x, Channels %x, flags %#x, status %d addr %s",
- inStream,
+ inStream.get(),
halconfig.sample_rate,
halconfig.format,
halconfig.channel_mask,
@@ -2151,13 +2127,13 @@
(audio_channel_count_from_in_mask(config->channel_mask) <= FCC_8)) {
// FIXME describe the change proposed by HAL (save old values so we can log them here)
ALOGV("openInput_l() reopening with proposed sampling rate and channel mask");
- inStream = NULL;
- status = inHwHal->open_input_stream(inHwHal, *input, devices, &halconfig,
- &inStream, flags, address.string(), source);
+ inStream.clear();
+ status = inHwHal->openInputStream(
+ *input, devices, &halconfig, flags, address.string(), source, &inStream);
// FIXME log this new status; HAL should not propose any further changes
}
- if (status == NO_ERROR && inStream != NULL) {
+ if (status == NO_ERROR && inStream != 0) {
#ifdef TEE_SINK
// Try to re-use most recently used Pipe to archive a copy of input for dumpsys,
@@ -2304,7 +2280,6 @@
AudioStreamIn *in = thread->clearInput();
ALOG_ASSERT(in != NULL, "in shouldn't be NULL");
// from now on thread->mInput is NULL
- in->hwDev()->close_input_stream(in->hwDev(), in->stream);
delete in;
}
@@ -2596,24 +2571,39 @@
// Effect management
// ----------------------------------------------------------------------------
+sp<EffectsFactoryHalInterface> AudioFlinger::getEffectsFactory() {
+ return mEffectsFactoryHal;
+}
status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects) const
{
Mutex::Autolock _l(mLock);
- return EffectQueryNumberEffects(numEffects);
+ if (mEffectsFactoryHal.get()) {
+ return mEffectsFactoryHal->queryNumberEffects(numEffects);
+ } else {
+ return -ENODEV;
+ }
}
status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor) const
{
Mutex::Autolock _l(mLock);
- return EffectQueryEffect(index, descriptor);
+ if (mEffectsFactoryHal.get()) {
+ return mEffectsFactoryHal->getDescriptor(index, descriptor);
+ } else {
+ return -ENODEV;
+ }
}
status_t AudioFlinger::getEffectDescriptor(const effect_uuid_t *pUuid,
effect_descriptor_t *descriptor) const
{
Mutex::Autolock _l(mLock);
- return EffectGetDescriptor(pUuid, descriptor);
+ if (mEffectsFactoryHal.get()) {
+ return mEffectsFactoryHal->getDescriptor(pUuid, descriptor);
+ } else {
+ return -ENODEV;
+ }
}
@@ -2633,8 +2623,8 @@
effect_descriptor_t desc;
pid_t pid = IPCThreadState::self()->getCallingPid();
- ALOGV("createEffect pid %d, effectClient %p, priority %d, sessionId %d, io %d",
- pid, effectClient.get(), priority, sessionId, io);
+ ALOGV("createEffect pid %d, effectClient %p, priority %d, sessionId %d, io %d, factory %p",
+ pid, effectClient.get(), priority, sessionId, io, mEffectsFactoryHal.get());
if (pDesc == NULL) {
lStatus = BAD_VALUE;
@@ -2654,10 +2644,15 @@
goto Exit;
}
+ if (mEffectsFactoryHal == 0) {
+ lStatus = NO_INIT;
+ goto Exit;
+ }
+
{
- if (!EffectIsNullUuid(&pDesc->uuid)) {
+ if (!EffectsFactoryHalInterface::isNullUuid(&pDesc->uuid)) {
// if uuid is specified, request effect descriptor
- lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);
+ lStatus = mEffectsFactoryHal->getDescriptor(&pDesc->uuid, &desc);
if (lStatus < 0) {
ALOGW("createEffect() error %d from EffectGetDescriptor", lStatus);
goto Exit;
@@ -2665,7 +2660,7 @@
} else {
// if uuid is not specified, look for an available implementation
// of the required type in effect factory
- if (EffectIsNullUuid(&pDesc->type)) {
+ if (EffectsFactoryHalInterface::isNullUuid(&pDesc->type)) {
ALOGW("createEffect() no effect type");
lStatus = BAD_VALUE;
goto Exit;
@@ -2675,13 +2670,13 @@
d.flags = 0; // prevent compiler warning
bool found = false;
- lStatus = EffectQueryNumberEffects(&numEffects);
+ lStatus = mEffectsFactoryHal->queryNumberEffects(&numEffects);
if (lStatus < 0) {
ALOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
goto Exit;
}
for (uint32_t i = 0; i < numEffects; i++) {
- lStatus = EffectQueryEffect(i, &desc);
+ lStatus = mEffectsFactoryHal->getDescriptor(i, &desc);
if (lStatus < 0) {
ALOGW("createEffect() error %d from EffectQueryEffect", lStatus);
continue;
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index c4b89f8..890aa89 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -43,9 +43,9 @@
#include <binder/MemoryDealer.h>
#include <system/audio.h>
-#include <hardware/audio.h>
#include <hardware/audio_policy.h>
+#include <media/audiohal/StreamHalInterface.h>
#include <media/AudioBufferProvider.h>
#include <media/ExtendedAudioBufferProvider.h>
@@ -71,6 +71,9 @@
class AudioMixer;
class AudioBuffer;
class AudioResampler;
+class DeviceHalInterface;
+class DevicesFactoryHalInterface;
+class EffectsFactoryHalInterface;
class FastMixer;
class PassthruBufferProvider;
class ServerProxy;
@@ -271,6 +274,7 @@
sp<NBLog::Writer> newWriter_l(size_t size, const char *name);
void unregisterWriter(const sp<NBLog::Writer>& writer);
+ sp<EffectsFactoryHalInterface> getEffectsFactory();
private:
static const size_t kLogMemorySize = 40 * 1024;
sp<MemoryDealer> mLogMemoryDealer; // == 0 when NBLog is disabled
@@ -611,12 +615,12 @@
struct AudioStreamIn {
AudioHwDevice* const audioHwDev;
- audio_stream_in_t* const stream;
+ sp<StreamInHalInterface> stream;
audio_input_flags_t flags;
- audio_hw_device_t* hwDev() const { return audioHwDev->hwDevice(); }
+ sp<DeviceHalInterface> hwDev() const { return audioHwDev->hwDevice(); }
- AudioStreamIn(AudioHwDevice *dev, audio_stream_in_t *in, audio_input_flags_t flags) :
+ AudioStreamIn(AudioHwDevice *dev, sp<StreamInHalInterface> in, audio_input_flags_t flags) :
audioHwDev(dev), stream(in), flags(flags) {}
};
@@ -645,6 +649,8 @@
AudioHwDevice* mPrimaryHardwareDev; // mAudioHwDevs[0] or NULL
DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*> mAudioHwDevs;
+ sp<DevicesFactoryHalInterface> mDevicesFactoryHal;
+
// for dump, indicates which hardware operation is currently in progress (but not stream ops)
enum hardware_call_state {
AUDIO_HW_IDLE = 0, // no operation in progress
@@ -760,6 +766,7 @@
nsecs_t mGlobalEffectEnableTime; // when a global effect was last enabled
sp<PatchPanel> mPatchPanel;
+ sp<EffectsFactoryHalInterface> mEffectsFactoryHal;
bool mSystemReady;
};
diff --git a/services/audioflinger/AudioHwDevice.cpp b/services/audioflinger/AudioHwDevice.cpp
index 7494930..28110a2 100644
--- a/services/audioflinger/AudioHwDevice.cpp
+++ b/services/audioflinger/AudioHwDevice.cpp
@@ -18,7 +18,7 @@
#define LOG_TAG "AudioHwDevice"
//#define LOG_NDEBUG 0
-#include <hardware/audio.h>
+#include <system/audio.h>
#include <utils/Log.h>
#include <audio_utils/spdif/SPDIFEncoder.h>
@@ -93,5 +93,10 @@
return status;
}
+uint32_t AudioHwDevice::version() const
+{
+ uint32_t result;
+ return mHwDevice->getVersion(&result) == OK ? result : 0;
+}
}; // namespace android
diff --git a/services/audioflinger/AudioHwDevice.h b/services/audioflinger/AudioHwDevice.h
index b9f65c1..ebb8911 100644
--- a/services/audioflinger/AudioHwDevice.h
+++ b/services/audioflinger/AudioHwDevice.h
@@ -22,11 +22,10 @@
#include <stdlib.h>
#include <sys/types.h>
-#include <hardware/audio.h>
+#include <media/audiohal/DeviceHalInterface.h>
#include <utils/Errors.h>
#include <system/audio.h>
-
namespace android {
class AudioStreamOut;
@@ -40,7 +39,7 @@
AudioHwDevice(audio_module_handle_t handle,
const char *moduleName,
- audio_hw_device_t *hwDevice,
+ sp<DeviceHalInterface> hwDevice,
Flags flags)
: mHandle(handle)
, mModuleName(strdup(moduleName))
@@ -58,8 +57,8 @@
audio_module_handle_t handle() const { return mHandle; }
const char *moduleName() const { return mModuleName; }
- audio_hw_device_t *hwDevice() const { return mHwDevice; }
- uint32_t version() const { return mHwDevice->common.version; }
+ sp<DeviceHalInterface> hwDevice() const { return mHwDevice; }
+ uint32_t version() const;
/** This method creates and opens the audio hardware output stream.
* The "address" parameter qualifies the "devices" audio device type if needed.
@@ -79,7 +78,7 @@
private:
const audio_module_handle_t mHandle;
const char * const mModuleName;
- audio_hw_device_t * const mHwDevice;
+ sp<DeviceHalInterface> mHwDevice;
const Flags mFlags;
};
diff --git a/services/audioflinger/AudioResamplerDyn.cpp b/services/audioflinger/AudioResamplerDyn.cpp
index b7ca5d9..21914b9 100644
--- a/services/audioflinger/AudioResamplerDyn.cpp
+++ b/services/audioflinger/AudioResamplerDyn.cpp
@@ -149,6 +149,15 @@
}
template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::InBuffer::reset()
+{
+ // clear resampler state
+ if (mState != nullptr) {
+ memset(mState, 0, mStateCount * sizeof(TI));
+ }
+}
+
+template<typename TC, typename TI, typename TO>
void AudioResamplerDyn<TC, TI, TO>::Constants::set(
int L, int halfNumCoefs, int inSampleRate, int outSampleRate)
{
@@ -528,6 +537,9 @@
mBuffer.frameCount = inFrameCount;
provider->getNextBuffer(&mBuffer);
if (mBuffer.raw == NULL) {
+ // We are either at the end of playback or in an underrun situation.
+ // Reset buffer to prevent pop noise at the next buffer.
+ mInBuffer.reset();
goto resample_exit;
}
inFrameCount -= mBuffer.frameCount;
diff --git a/services/audioflinger/AudioResamplerDyn.h b/services/audioflinger/AudioResamplerDyn.h
index 3b1c381..a5ea821 100644
--- a/services/audioflinger/AudioResamplerDyn.h
+++ b/services/audioflinger/AudioResamplerDyn.h
@@ -96,6 +96,8 @@
inline void readAdvance(TI*& impulse, const int halfNumCoefs,
const TI* const in, const size_t inputIndex);
+ void reset();
+
private:
// tuning parameter guidelines: 2 <= multiple <= 8
static const int kStateSizeMultipleOfFilterLength = 4;
diff --git a/services/audioflinger/AudioStreamOut.cpp b/services/audioflinger/AudioStreamOut.cpp
index 6026bbb..1d4b3fe 100644
--- a/services/audioflinger/AudioStreamOut.cpp
+++ b/services/audioflinger/AudioStreamOut.cpp
@@ -18,7 +18,9 @@
#define LOG_TAG "AudioFlinger"
//#define LOG_NDEBUG 0
-#include <hardware/audio.h>
+#include <media/audiohal/DeviceHalInterface.h>
+#include <media/audiohal/StreamHalInterface.h>
+#include <system/audio.h>
#include <utils/Log.h>
#include "AudioHwDevice.h"
@@ -40,19 +42,23 @@
{
}
-audio_hw_device_t *AudioStreamOut::hwDev() const
+AudioStreamOut::~AudioStreamOut()
+{
+}
+
+sp<DeviceHalInterface> AudioStreamOut::hwDev() const
{
return audioHwDev->hwDevice();
}
status_t AudioStreamOut::getRenderPosition(uint64_t *frames)
{
- if (stream == NULL) {
+ if (stream == 0) {
return NO_INIT;
}
uint32_t halPosition = 0;
- status_t status = stream->get_render_position(stream, &halPosition);
+ status_t status = stream->getRenderPosition(&halPosition);
if (status != NO_ERROR) {
return status;
}
@@ -84,12 +90,12 @@
status_t AudioStreamOut::getPresentationPosition(uint64_t *frames, struct timespec *timestamp)
{
- if (stream == NULL) {
+ if (stream == 0) {
return NO_INIT;
}
uint64_t halPosition = 0;
- status_t status = stream->get_presentation_position(stream, &halPosition, timestamp);
+ status_t status = stream->getPresentationPosition(&halPosition, timestamp);
if (status != NO_ERROR) {
return status;
}
@@ -115,24 +121,23 @@
struct audio_config *config,
const char *address)
{
- audio_stream_out_t *outStream;
+ sp<StreamOutHalInterface> outStream;
audio_output_flags_t customFlags = (config->format == AUDIO_FORMAT_IEC61937)
? (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO)
: flags;
- int status = hwDev()->open_output_stream(
- hwDev(),
+ int status = hwDev()->openOutputStream(
handle,
devices,
customFlags,
config,
- &outStream,
- address);
+ address,
+ &outStream);
ALOGV("AudioStreamOut::open(), HAL returned "
" stream %p, sampleRate %d, Format %#x, "
"channelMask %#x, status %d",
- outStream,
+ outStream.get(),
config->sample_rate,
config->format,
config->channel_mask,
@@ -144,21 +149,20 @@
struct audio_config customConfig = *config;
customConfig.format = AUDIO_FORMAT_PCM_16_BIT;
- status = hwDev()->open_output_stream(
- hwDev(),
+ status = hwDev()->openOutputStream(
handle,
devices,
customFlags,
&customConfig,
- &outStream,
- address);
+ address,
+ &outStream);
ALOGV("AudioStreamOut::open(), treat IEC61937 as PCM, status = %d", status);
}
if (status == NO_ERROR) {
stream = outStream;
mHalFormatHasProportionalFrames = audio_has_proportional_frames(config->format);
- mHalFrameSize = audio_stream_out_frame_size(stream);
+ status = stream->getFrameSize(&mHalFrameSize);
}
return status;
@@ -166,47 +170,46 @@
audio_format_t AudioStreamOut::getFormat() const
{
- return stream->common.get_format(&stream->common);
+ audio_format_t result;
+ return stream->getFormat(&result) == OK ? result : AUDIO_FORMAT_INVALID;
}
uint32_t AudioStreamOut::getSampleRate() const
{
- return stream->common.get_sample_rate(&stream->common);
+ uint32_t result;
+ return stream->getSampleRate(&result) == OK ? result : 0;
}
audio_channel_mask_t AudioStreamOut::getChannelMask() const
{
- return stream->common.get_channels(&stream->common);
+ audio_channel_mask_t result;
+ return stream->getChannelMask(&result) == OK ? result : AUDIO_CHANNEL_INVALID;
}
int AudioStreamOut::flush()
{
- ALOG_ASSERT(stream != NULL);
mRenderPosition = 0;
mFramesWritten = 0;
mFramesWrittenAtStandby = 0;
- if (stream->flush != NULL) {
- return stream->flush(stream);
- }
- return NO_ERROR;
+ status_t result = stream->flush();
+ return result != INVALID_OPERATION ? result : NO_ERROR;
}
int AudioStreamOut::standby()
{
- ALOG_ASSERT(stream != NULL);
mRenderPosition = 0;
mFramesWrittenAtStandby = mFramesWritten;
- return stream->common.standby(&stream->common);
+ return stream->standby();
}
ssize_t AudioStreamOut::write(const void *buffer, size_t numBytes)
{
- ALOG_ASSERT(stream != NULL);
- ssize_t bytesWritten = stream->write(stream, buffer, numBytes);
- if (bytesWritten > 0 && mHalFrameSize > 0) {
+ size_t bytesWritten;
+ status_t result = stream->write(buffer, numBytes, &bytesWritten);
+ if (result == OK && bytesWritten > 0 && mHalFrameSize > 0) {
mFramesWritten += bytesWritten / mHalFrameSize;
}
- return bytesWritten;
+ return result == OK ? bytesWritten : result;
}
} // namespace android
diff --git a/services/audioflinger/AudioStreamOut.h b/services/audioflinger/AudioStreamOut.h
index 768f537..b16b1af 100644
--- a/services/audioflinger/AudioStreamOut.h
+++ b/services/audioflinger/AudioStreamOut.h
@@ -23,11 +23,11 @@
#include <system/audio.h>
-#include "AudioStreamOut.h"
-
namespace android {
class AudioHwDevice;
+class DeviceHalInterface;
+class StreamOutHalInterface;
/**
* Managed access to a HAL output stream.
@@ -38,10 +38,10 @@
// For emphasis, we could also make all pointers to them be "const *",
// but that would clutter the code unnecessarily.
AudioHwDevice * const audioHwDev;
- audio_stream_out_t *stream;
+ sp<StreamOutHalInterface> stream;
const audio_output_flags_t flags;
- audio_hw_device_t *hwDev() const;
+ sp<DeviceHalInterface> hwDev() const;
AudioStreamOut(AudioHwDevice *dev, audio_output_flags_t flags);
@@ -51,7 +51,7 @@
struct audio_config *config,
const char *address);
- virtual ~AudioStreamOut() { }
+ virtual ~AudioStreamOut();
// Get the bottom 32-bits of the 64-bit render position.
status_t getRenderPosition(uint32_t *frames);
diff --git a/services/audioflinger/BufferProviders.cpp b/services/audioflinger/BufferProviders.cpp
index 7b6dfcb..f3b817c 100644
--- a/services/audioflinger/BufferProviders.cpp
+++ b/services/audioflinger/BufferProviders.cpp
@@ -20,8 +20,9 @@
#include <audio_effects/effect_downmix.h>
#include <audio_utils/primitives.h>
#include <audio_utils/format.h>
+#include <media/audiohal/EffectHalInterface.h>
+#include <media/audiohal/EffectsFactoryHalInterface.h>
#include <media/AudioResamplerPublic.h>
-#include <media/EffectsFactoryApi.h>
#include <utils/Log.h>
@@ -145,13 +146,22 @@
ALOGV("DownmixerBufferProvider(%p)(%#x, %#x, %#x %u %d)",
this, inputChannelMask, outputChannelMask, format,
sampleRate, sessionId);
- if (!sIsMultichannelCapable
- || EffectCreate(&sDwnmFxDesc.uuid,
- sessionId,
- SESSION_ID_INVALID_AND_IGNORED,
- &mDownmixHandle) != 0) {
+ if (!sIsMultichannelCapable) {
+ ALOGE("DownmixerBufferProvider() error: not multichannel capable");
+ return;
+ }
+ mEffectsFactory = EffectsFactoryHalInterface::create();
+ if (mEffectsFactory == 0) {
+ ALOGE("DownmixerBufferProvider() error: could not obtain the effects factory");
+ return;
+ }
+ if (mEffectsFactory->createEffect(&sDwnmFxDesc.uuid,
+ sessionId,
+ SESSION_ID_INVALID_AND_IGNORED,
+ &mDownmixInterface) != 0) {
ALOGE("DownmixerBufferProvider() error creating downmixer effect");
- mDownmixHandle = NULL;
+ mDownmixInterface.clear();
+ mEffectsFactory.clear();
return;
}
// channel input configuration will be overridden per-track
@@ -173,28 +183,28 @@
uint32_t replySize = sizeof(int);
// Configure downmixer
- status_t status = (*mDownmixHandle)->command(mDownmixHandle,
+ status_t status = mDownmixInterface->command(
EFFECT_CMD_SET_CONFIG /*cmdCode*/, sizeof(effect_config_t) /*cmdSize*/,
&mDownmixConfig /*pCmdData*/,
&replySize, &cmdStatus /*pReplyData*/);
if (status != 0 || cmdStatus != 0) {
ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while configuring downmixer",
status, cmdStatus);
- EffectRelease(mDownmixHandle);
- mDownmixHandle = NULL;
+ mDownmixInterface.clear();
+ mEffectsFactory.clear();
return;
}
// Enable downmixer
replySize = sizeof(int);
- status = (*mDownmixHandle)->command(mDownmixHandle,
+ status = mDownmixInterface->command(
EFFECT_CMD_ENABLE /*cmdCode*/, 0 /*cmdSize*/, NULL /*pCmdData*/,
&replySize, &cmdStatus /*pReplyData*/);
if (status != 0 || cmdStatus != 0) {
ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while enabling downmixer",
status, cmdStatus);
- EffectRelease(mDownmixHandle);
- mDownmixHandle = NULL;
+ mDownmixInterface.clear();
+ mEffectsFactory.clear();
return;
}
@@ -211,15 +221,15 @@
param->vsize = sizeof(downmix_type_t);
memcpy(param->data + psizePadded, &downmixType, param->vsize);
replySize = sizeof(int);
- status = (*mDownmixHandle)->command(mDownmixHandle,
+ status = mDownmixInterface->command(
EFFECT_CMD_SET_PARAM /* cmdCode */, downmixParamSize /* cmdSize */,
param /*pCmdData*/, &replySize, &cmdStatus /*pReplyData*/);
free(param);
if (status != 0 || cmdStatus != 0) {
ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while setting downmix type",
status, cmdStatus);
- EffectRelease(mDownmixHandle);
- mDownmixHandle = NULL;
+ mDownmixInterface.clear();
+ mEffectsFactory.clear();
return;
}
ALOGV("DownmixerBufferProvider() downmix type set to %d", (int) downmixType);
@@ -228,8 +238,6 @@
DownmixerBufferProvider::~DownmixerBufferProvider()
{
ALOGV("~DownmixerBufferProvider (%p)", this);
- EffectRelease(mDownmixHandle);
- mDownmixHandle = NULL;
}
void DownmixerBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
@@ -239,7 +247,7 @@
mDownmixConfig.outputCfg.buffer.frameCount = frames;
mDownmixConfig.outputCfg.buffer.raw = dst;
// may be in-place if src == dst.
- status_t res = (*mDownmixHandle)->process(mDownmixHandle,
+ status_t res = mDownmixInterface->process(
&mDownmixConfig.inputCfg.buffer, &mDownmixConfig.outputCfg.buffer);
ALOGE_IF(res != OK, "DownmixBufferProvider error %d", res);
}
@@ -248,8 +256,13 @@
/*static*/ status_t DownmixerBufferProvider::init()
{
// find multichannel downmix effect if we have to play multichannel content
+ sp<EffectsFactoryHalInterface> effectsFactory = EffectsFactoryHalInterface::create();
+ if (effectsFactory == 0) {
+ ALOGE("AudioMixer() error: could not obtain the effects factory");
+ return NO_INIT;
+ }
uint32_t numEffects = 0;
- int ret = EffectQueryNumberEffects(&numEffects);
+ int ret = effectsFactory->queryNumberEffects(&numEffects);
if (ret != 0) {
ALOGE("AudioMixer() error %d querying number of effects", ret);
return NO_INIT;
@@ -257,7 +270,7 @@
ALOGV("EffectQueryNumberEffects() numEffects=%d", numEffects);
for (uint32_t i = 0 ; i < numEffects ; i++) {
- if (EffectQueryEffect(i, &sDwnmFxDesc) == 0) {
+ if (effectsFactory->getDescriptor(i, &sDwnmFxDesc) == 0) {
ALOGV("effect %d is called %s", i, sDwnmFxDesc.name);
if (memcmp(&sDwnmFxDesc.type, EFFECT_UIID_DOWNMIX, sizeof(effect_uuid_t)) == 0) {
ALOGI("found effect \"%s\" from %s",
diff --git a/services/audioflinger/BufferProviders.h b/services/audioflinger/BufferProviders.h
index abd43c6..cb13689 100644
--- a/services/audioflinger/BufferProviders.h
+++ b/services/audioflinger/BufferProviders.h
@@ -24,9 +24,13 @@
#include <media/AudioBufferProvider.h>
#include <system/audio.h>
#include <sonic.h>
+#include <utils/StrongPointer.h>
namespace android {
+class EffectHalInterface;
+class EffectsFactoryHalInterface;
+
// ----------------------------------------------------------------------------
class PassthruBufferProvider : public AudioBufferProvider {
@@ -97,12 +101,13 @@
//Overrides
virtual void copyFrames(void *dst, const void *src, size_t frames);
- bool isValid() const { return mDownmixHandle != NULL; }
+ bool isValid() const { return mDownmixInterface.get() != NULL; }
static status_t init();
static bool isMultichannelCapable() { return sIsMultichannelCapable; }
protected:
- effect_handle_t mDownmixHandle;
+ sp<EffectsFactoryHalInterface> mEffectsFactory;
+ sp<EffectHalInterface> mDownmixInterface;
effect_config_t mDownmixConfig;
// effect descriptor for the downmixer used by the mixer
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index e2fad6f..b8d24a0 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -24,7 +24,8 @@
#include <audio_effects/effect_visualizer.h>
#include <audio_utils/primitives.h>
#include <private/media/AudioEffectShared.h>
-#include <media/EffectsFactoryApi.h>
+#include <media/audiohal/EffectHalInterface.h>
+#include <media/audiohal/EffectsFactoryHalInterface.h>
#include "AudioFlinger.h"
#include "ServiceUtilities.h"
@@ -64,7 +65,6 @@
mThread(thread), mChain(chain), mId(id), mSessionId(sessionId),
mDescriptor(*desc),
// mConfig is set by configure() and not used before then
- mEffectInterface(NULL),
mStatus(NO_INIT), mState(IDLE),
// mMaxDisableWaitCnt is set by configure() and not used before then
// mDisableWaitCnt is set by process() and updateState() and not used before then
@@ -75,7 +75,15 @@
int lStatus;
// create effect engine from effect factory
- mStatus = EffectCreate(&desc->uuid, sessionId, thread->id(), &mEffectInterface);
+ mStatus = -ENODEV;
+ sp<AudioFlinger> audioFlinger = mAudioFlinger.promote();
+ if (audioFlinger != 0) {
+ sp<EffectsFactoryHalInterface> effectsFactory = audioFlinger->getEffectsFactory();
+ if (effectsFactory != 0) {
+ mStatus = effectsFactory->createEffect(
+ &desc->uuid, sessionId, thread->id(), &mEffectInterface);
+ }
+ }
if (mStatus != NO_ERROR) {
return;
@@ -86,21 +94,20 @@
goto Error;
}
- ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
+ ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface.get());
return;
Error:
- EffectRelease(mEffectInterface);
- mEffectInterface = NULL;
+ mEffectInterface.clear();
ALOGV("Constructor Error %d", mStatus);
}
AudioFlinger::EffectModule::~EffectModule()
{
ALOGV("Destructor %p", this);
- if (mEffectInterface != NULL) {
+ if (mEffectInterface != 0) {
remove_effect_from_hal_l();
// release effect engine
- EffectRelease(mEffectInterface);
+ mEffectInterface.clear();
}
}
@@ -266,7 +273,7 @@
{
Mutex::Autolock _l(mLock);
- if (mState == DESTROYED || mEffectInterface == NULL ||
+ if (mState == DESTROYED || mEffectInterface == 0 ||
mConfig.inputCfg.buffer.raw == NULL ||
mConfig.outputCfg.buffer.raw == NULL) {
return;
@@ -282,9 +289,7 @@
int ret;
if (isProcessImplemented()) {
// do the actual processing in the effect engine
- ret = (*mEffectInterface)->process(mEffectInterface,
- &mConfig.inputCfg.buffer,
- &mConfig.outputCfg.buffer);
+ ret = mEffectInterface->process(&mConfig.inputCfg.buffer, &mConfig.outputCfg.buffer);
} else {
if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
size_t frameCnt = mConfig.inputCfg.buffer.frameCount * FCC_2; //always stereo here
@@ -330,10 +335,10 @@
void AudioFlinger::EffectModule::reset_l()
{
- if (mStatus != NO_ERROR || mEffectInterface == NULL) {
+ if (mStatus != NO_ERROR || mEffectInterface == 0) {
return;
}
- (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_RESET, 0, NULL, 0, NULL);
+ mEffectInterface->command(EFFECT_CMD_RESET, 0, NULL, 0, NULL);
}
status_t AudioFlinger::EffectModule::configure()
@@ -343,7 +348,7 @@
uint32_t size;
audio_channel_mask_t channelMask;
- if (mEffectInterface == NULL) {
+ if (mEffectInterface == 0) {
status = NO_INIT;
goto exit;
}
@@ -406,12 +411,11 @@
status_t cmdStatus;
size = sizeof(int);
- status = (*mEffectInterface)->command(mEffectInterface,
- EFFECT_CMD_SET_CONFIG,
- sizeof(effect_config_t),
- &mConfig,
- &size,
- &cmdStatus);
+ status = mEffectInterface->command(EFFECT_CMD_SET_CONFIG,
+ sizeof(effect_config_t),
+ &mConfig,
+ &size,
+ &cmdStatus);
if (status == 0) {
status = cmdStatus;
}
@@ -433,12 +437,11 @@
}
*((int32_t *)p->data + 1)= latency;
- (*mEffectInterface)->command(mEffectInterface,
- EFFECT_CMD_SET_PARAM,
- sizeof(effect_param_t) + 8,
- &buf32,
- &size,
- &cmdStatus);
+ mEffectInterface->command(EFFECT_CMD_SET_PARAM,
+ sizeof(effect_param_t) + 8,
+ &buf32,
+ &size,
+ &cmdStatus);
}
mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
@@ -452,17 +455,16 @@
status_t AudioFlinger::EffectModule::init()
{
Mutex::Autolock _l(mLock);
- if (mEffectInterface == NULL) {
+ if (mEffectInterface == 0) {
return NO_INIT;
}
status_t cmdStatus;
uint32_t size = sizeof(status_t);
- status_t status = (*mEffectInterface)->command(mEffectInterface,
- EFFECT_CMD_INIT,
- 0,
- NULL,
- &size,
- &cmdStatus);
+ status_t status = mEffectInterface->command(EFFECT_CMD_INIT,
+ 0,
+ NULL,
+ &size,
+ &cmdStatus);
if (status == 0) {
status = cmdStatus;
}
@@ -475,9 +477,10 @@
(mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
- audio_stream_t *stream = thread->stream();
- if (stream != NULL) {
- stream->add_audio_effect(stream, mEffectInterface);
+ sp<StreamHalInterface> stream = thread->stream();
+ if (stream != 0) {
+ status_t result = stream->addEffect(mEffectInterface);
+ ALOGE_IF(result != OK, "Error when adding effect: %d", result);
}
}
}
@@ -503,7 +506,7 @@
status_t AudioFlinger::EffectModule::start_l()
{
- if (mEffectInterface == NULL) {
+ if (mEffectInterface == 0) {
return NO_INIT;
}
if (mStatus != NO_ERROR) {
@@ -511,12 +514,11 @@
}
status_t cmdStatus;
uint32_t size = sizeof(status_t);
- status_t status = (*mEffectInterface)->command(mEffectInterface,
- EFFECT_CMD_ENABLE,
- 0,
- NULL,
- &size,
- &cmdStatus);
+ status_t status = mEffectInterface->command(EFFECT_CMD_ENABLE,
+ 0,
+ NULL,
+ &size,
+ &cmdStatus);
if (status == 0) {
status = cmdStatus;
}
@@ -534,7 +536,7 @@
status_t AudioFlinger::EffectModule::stop_l()
{
- if (mEffectInterface == NULL) {
+ if (mEffectInterface == 0) {
return NO_INIT;
}
if (mStatus != NO_ERROR) {
@@ -542,12 +544,11 @@
}
status_t cmdStatus = NO_ERROR;
uint32_t size = sizeof(status_t);
- status_t status = (*mEffectInterface)->command(mEffectInterface,
- EFFECT_CMD_DISABLE,
- 0,
- NULL,
- &size,
- &cmdStatus);
+ status_t status = mEffectInterface->command(EFFECT_CMD_DISABLE,
+ 0,
+ NULL,
+ &size,
+ &cmdStatus);
if (status == NO_ERROR) {
status = cmdStatus;
}
@@ -563,9 +564,10 @@
(mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
- audio_stream_t *stream = thread->stream();
- if (stream != NULL) {
- stream->remove_audio_effect(stream, mEffectInterface);
+ sp<StreamHalInterface> stream = thread->stream();
+ if (stream != 0) {
+ status_t result = stream->removeEffect(mEffectInterface);
+ ALOGE_IF(result != OK, "Error when removing effect: %d", result);
}
}
}
@@ -586,9 +588,9 @@
void *pReplyData)
{
Mutex::Autolock _l(mLock);
- ALOGVV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
+ ALOGVV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface.get());
- if (mState == DESTROYED || mEffectInterface == NULL) {
+ if (mState == DESTROYED || mEffectInterface == 0) {
return NO_INIT;
}
if (mStatus != NO_ERROR) {
@@ -616,12 +618,11 @@
android_errorWriteLog(0x534e4554, "30204301");
return -EINVAL;
}
- status_t status = (*mEffectInterface)->command(mEffectInterface,
- cmdCode,
- cmdSize,
- pCmdData,
- replySize,
- pReplyData);
+ status_t status = mEffectInterface->command(cmdCode,
+ cmdSize,
+ pCmdData,
+ replySize,
+ pReplyData);
if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
uint32_t size = (replySize == NULL) ? 0 : *replySize;
for (size_t i = 1; i < mHandles.size(); i++) {
@@ -743,12 +744,11 @@
if (controller) {
pVolume = volume;
}
- status = (*mEffectInterface)->command(mEffectInterface,
- EFFECT_CMD_SET_VOLUME,
- size,
- volume,
- &size,
- pVolume);
+ status = mEffectInterface->command(EFFECT_CMD_SET_VOLUME,
+ size,
+ volume,
+ &size,
+ pVolume);
if (controller && status == NO_ERROR && size == sizeof(volume)) {
*left = volume[0];
*right = volume[1];
@@ -773,12 +773,11 @@
uint32_t size = sizeof(status_t);
uint32_t cmd = audio_is_output_devices(device) ? EFFECT_CMD_SET_DEVICE :
EFFECT_CMD_SET_INPUT_DEVICE;
- status = (*mEffectInterface)->command(mEffectInterface,
- cmd,
- sizeof(uint32_t),
- &device,
- &size,
- &cmdStatus);
+ status = mEffectInterface->command(cmd,
+ sizeof(uint32_t),
+ &device,
+ &size,
+ &cmdStatus);
}
return status;
}
@@ -793,12 +792,11 @@
if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
status_t cmdStatus;
uint32_t size = sizeof(status_t);
- status = (*mEffectInterface)->command(mEffectInterface,
- EFFECT_CMD_SET_AUDIO_MODE,
- sizeof(audio_mode_t),
- &mode,
- &size,
- &cmdStatus);
+ status = mEffectInterface->command(EFFECT_CMD_SET_AUDIO_MODE,
+ sizeof(audio_mode_t),
+ &mode,
+ &size,
+ &cmdStatus);
if (status == NO_ERROR) {
status = cmdStatus;
}
@@ -815,12 +813,11 @@
status_t status = NO_ERROR;
if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_SOURCE_MASK) == EFFECT_FLAG_AUDIO_SOURCE_IND) {
uint32_t size = 0;
- status = (*mEffectInterface)->command(mEffectInterface,
- EFFECT_CMD_SET_AUDIO_SOURCE,
- sizeof(audio_source_t),
- &source,
- &size,
- NULL);
+ status = mEffectInterface->command(EFFECT_CMD_SET_AUDIO_SOURCE,
+ sizeof(audio_source_t),
+ &source,
+ &size,
+ NULL);
}
return status;
}
@@ -867,12 +864,11 @@
cmd.isOffload = offloaded;
cmd.ioHandle = io;
- status = (*mEffectInterface)->command(mEffectInterface,
- EFFECT_CMD_OFFLOAD,
- sizeof(effect_offload_param_t),
- &cmd,
- &size,
- &cmdStatus);
+ status = mEffectInterface->command(EFFECT_CMD_OFFLOAD,
+ sizeof(effect_offload_param_t),
+ &cmd,
+ &size,
+ &cmdStatus);
if (status == NO_ERROR) {
status = cmdStatus;
}
@@ -1015,7 +1011,7 @@
result.append("\t\tSession Status State Engine:\n");
snprintf(buffer, SIZE, "\t\t%05d %03d %03d %p\n",
- mSessionId, mStatus, mState, mEffectInterface);
+ mSessionId, mStatus, mState, mEffectInterface.get());
result.append(buffer);
result.append("\t\tDescriptor:\n");
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 96cb607..a19b7fd 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -148,7 +148,7 @@
const audio_session_t mSessionId; // audio session ID
const effect_descriptor_t mDescriptor;// effect descriptor received from effect engine
effect_config_t mConfig; // input and output audio configuration
- effect_handle_t mEffectInterface; // Effect module C API
+ sp<EffectHalInterface> mEffectInterface; // Effect module HAL
status_t mStatus; // initialization status
effect_state mState; // current activation state
Vector<EffectHandle *> mHandles; // list of client handles
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index bee17fd..c94ea45 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -202,9 +202,9 @@
if (hwModule != AUDIO_MODULE_HANDLE_NONE) {
ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(hwModule);
if (index >= 0) {
- audio_hw_device_t *hwDevice =
+ sp<DeviceHalInterface> hwDevice =
audioflinger->mAudioHwDevs.valueAt(index)->hwDevice();
- hwDevice->release_audio_patch(hwDevice, halHandle);
+ hwDevice->releaseAudioPatch(halHandle);
}
}
}
@@ -344,13 +344,12 @@
goto exit;
}
- audio_hw_device_t *hwDevice = audioHwDevice->hwDevice();
- status = hwDevice->create_audio_patch(hwDevice,
- patch->num_sources,
- patch->sources,
- patch->num_sinks,
- patch->sinks,
- &halHandle);
+ sp<DeviceHalInterface> hwDevice = audioHwDevice->hwDevice();
+ status = hwDevice->createAudioPatch(patch->num_sources,
+ patch->sources,
+ patch->num_sinks,
+ patch->sinks,
+ &halHandle);
}
}
} break;
@@ -623,8 +622,8 @@
status = INVALID_OPERATION;
break;
}
- audio_hw_device_t *hwDevice = audioHwDevice->hwDevice();
- status = hwDevice->release_audio_patch(hwDevice, removedPatch->mHalHandle);
+ sp<DeviceHalInterface> hwDevice = audioHwDevice->hwDevice();
+ status = hwDevice->releaseAudioPatch(removedPatch->mHalHandle);
}
} break;
case AUDIO_PORT_TYPE_MIX: {
@@ -688,8 +687,8 @@
AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index);
if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) {
- audio_hw_device_t *hwDevice = audioHwDevice->hwDevice();
- return hwDevice->set_audio_port_config(hwDevice, config);
+ sp<DeviceHalInterface> hwDevice = audioHwDevice->hwDevice();
+ return hwDevice->setAudioPortConfig(config);
} else {
return INVALID_OPERATION;
}
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 5601bde..cfa3e1a 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -166,7 +166,7 @@
// 'volatile' means accessed without lock or
// barrier, but is read/written atomically
bool mIsInvalid; // non-resettable latch, set by invalidate()
- AudioTrackServerProxy* mAudioTrackServerProxy;
+ sp<AudioTrackServerProxy> mAudioTrackServerProxy;
bool mResumeToStopping; // track was paused in stopping state.
bool mFlushHwPending; // track requests for thread flush
audio_output_flags_t mFlags;
@@ -214,8 +214,8 @@
Vector < Buffer* > mBufferQueue;
AudioBufferProvider::Buffer mOutBuffer;
bool mActive;
- DuplicatingThread* const mSourceThread; // for waitTimeMs() in write()
- AudioTrackClientProxy* mClientProxy;
+ DuplicatingThread* const mSourceThread; // for waitTimeMs() in write()
+ sp<AudioTrackClientProxy> mClientProxy;
}; // end of OutputTrack
// playback track, used by PatchPanel
diff --git a/services/audioflinger/SpdifStreamOut.cpp b/services/audioflinger/SpdifStreamOut.cpp
index 004a068..a44ab2a 100644
--- a/services/audioflinger/SpdifStreamOut.cpp
+++ b/services/audioflinger/SpdifStreamOut.cpp
@@ -17,13 +17,12 @@
#define LOG_TAG "AudioFlinger"
//#define LOG_NDEBUG 0
-#include <hardware/audio.h>
+#include <system/audio.h>
#include <utils/Log.h>
#include <audio_utils/spdif/SPDIFEncoder.h>
#include "AudioHwDevice.h"
-#include "AudioStreamOut.h"
#include "SpdifStreamOut.h"
namespace android {
diff --git a/services/audioflinger/SpdifStreamOut.h b/services/audioflinger/SpdifStreamOut.h
index c870250..fc9bb6e 100644
--- a/services/audioflinger/SpdifStreamOut.h
+++ b/services/audioflinger/SpdifStreamOut.h
@@ -23,9 +23,7 @@
#include <system/audio.h>
-#include "AudioHwDevice.h"
#include "AudioStreamOut.h"
-#include "SpdifStreamOut.h"
#include <audio_utils/spdif/SPDIFEncoder.h>
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 8a4fbb5..951a280 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -33,13 +33,13 @@
#include <utils/Trace.h>
#include <private/media/AudioTrackShared.h>
-#include <hardware/audio.h>
#include <audio_effects/effect_ns.h>
#include <audio_effects/effect_aec.h>
#include <audio_utils/conversion.h>
#include <audio_utils/primitives.h>
#include <audio_utils/format.h>
#include <audio_utils/minifloat.h>
+#include <system/audio.h>
// NBAIO implementations
#include <media/nbaio/AudioStreamInSource.h>
@@ -143,6 +143,12 @@
// Direct output thread minimum sleep time in idle or active(underrun) state
static const nsecs_t kDirectMinSleepTimeUs = 10000;
+// The universal constant for ubiquitous 20ms value. The value of 20ms seems to provide a good
+// balance between power consumption and latency, and allows threads to be scheduled reliably
+// by the CFS scheduler.
+// FIXME Express other hardcoded references to 20ms with references to this constant and move
+// it appropriately.
+#define FMS_20 20
// Whether to use fast mixer
static const enum {
@@ -1833,7 +1839,7 @@
}
if (output != nullptr) {
dprintf(fd, " Hal stream dump:\n");
- (void)output->stream->common.dump(&output->stream->common, fd);
+ (void)output->stream->dump(fd);
}
}
@@ -1850,7 +1856,8 @@
ALOGV(" preExit()");
// FIXME this is using hard-coded strings but in the future, this functionality will be
// converted to use audio HAL extensions required to support tunneling
- mOutput->stream->common.set_parameters(&mOutput->stream->common, "exiting=1");
+ status_t result = mOutput->stream->setParameters(String8("exiting=1"));
+ ALOGE_IF(result != OK, "Error when setting parameters on exit: %d", result);
}
// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
@@ -1957,7 +1964,12 @@
&& audio_has_proportional_frames(format) && sharedBuffer == 0) {
// this must match AudioTrack.cpp calculateMinFrameCount().
// TODO: Move to a common library
- uint32_t latencyMs = mOutput->stream->get_latency(mOutput->stream);
+ uint32_t latencyMs = 0;
+ lStatus = mOutput->stream->getLatency(&latencyMs);
+ if (lStatus != OK) {
+ ALOGE("Error when retrieving output stream latency: %d", lStatus);
+ goto Exit;
+ }
uint32_t minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate);
if (minBufCount < 2) {
minBufCount = 2;
@@ -2088,11 +2100,11 @@
}
uint32_t AudioFlinger::PlaybackThread::latency_l() const
{
- if (initCheck() == NO_ERROR) {
- return correctLatency_l(mOutput->stream->get_latency(mOutput->stream));
- } else {
- return 0;
+ uint32_t latency;
+ if (initCheck() == NO_ERROR && mOutput->stream->getLatency(&latency) == OK) {
+ return correctLatency_l(latency);
}
+ return 0;
}
void AudioFlinger::PlaybackThread::setMasterVolume(float value)
@@ -2257,14 +2269,11 @@
String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
{
Mutex::Autolock _l(mLock);
- if (initCheck() != NO_ERROR) {
- return String8();
+ String8 out_s8;
+ if (initCheck() == NO_ERROR && mOutput->stream->getParameters(keys, &out_s8) == OK) {
+ return out_s8;
}
-
- char *s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string());
- const String8 out_s8(s);
- free(s);
- return out_s8;
+ return String8();
}
void AudioFlinger::PlaybackThread::ioConfigChanged(audio_io_config_event event, pid_t pid) {
@@ -2293,21 +2302,18 @@
mAudioFlinger->ioConfigChanged(event, desc, pid);
}
-void AudioFlinger::PlaybackThread::writeCallback()
+void AudioFlinger::PlaybackThread::onWriteReady()
{
- ALOG_ASSERT(mCallbackThread != 0);
mCallbackThread->resetWriteBlocked();
}
-void AudioFlinger::PlaybackThread::drainCallback()
+void AudioFlinger::PlaybackThread::onDrainReady()
{
- ALOG_ASSERT(mCallbackThread != 0);
mCallbackThread->resetDraining();
}
-void AudioFlinger::PlaybackThread::errorCallback()
+void AudioFlinger::PlaybackThread::onError()
{
- ALOG_ASSERT(mCallbackThread != 0);
mCallbackThread->setAsyncError();
}
@@ -2331,30 +2337,6 @@
}
}
-// static
-int AudioFlinger::PlaybackThread::asyncCallback(stream_callback_event_t event,
- void *param __unused,
- void *cookie)
-{
- AudioFlinger::PlaybackThread *me = (AudioFlinger::PlaybackThread *)cookie;
- ALOGV("asyncCallback() event %d", event);
- switch (event) {
- case STREAM_CBK_EVENT_WRITE_READY:
- me->writeCallback();
- break;
- case STREAM_CBK_EVENT_DRAIN_READY:
- me->drainCallback();
- break;
- case STREAM_CBK_EVENT_ERROR:
- me->errorCallback();
- break;
- default:
- ALOGW("asyncCallback() unknown event %d", event);
- break;
- }
- return 0;
-}
-
void AudioFlinger::PlaybackThread::readOutputParameters_l()
{
// unfortunately we have no way of recovering from errors here, hence the LOG_ALWAYS_FATAL
@@ -2371,7 +2353,8 @@
mChannelCount = audio_channel_count_from_out_mask(mChannelMask);
// Get actual HAL format.
- mHALFormat = mOutput->stream->common.get_format(&mOutput->stream->common);
+ status_t result = mOutput->stream->getFormat(&mHALFormat);
+ LOG_ALWAYS_FATAL_IF(result != OK, "Error when retrieving output stream format: %d", result);
// Get format from the shim, which will be different than the HAL format
// if playing compressed audio over HDMI passthrough.
mFormat = mOutput->getFormat();
@@ -2384,17 +2367,17 @@
mFormat);
}
mFrameSize = mOutput->getFrameSize();
- mBufferSize = mOutput->stream->common.get_buffer_size(&mOutput->stream->common);
+ result = mOutput->stream->getBufferSize(&mBufferSize);
+ LOG_ALWAYS_FATAL_IF(result != OK,
+ "Error when retrieving output stream buffer size: %d", result);
mFrameCount = mBufferSize / mFrameSize;
if (mFrameCount & 15) {
ALOGW("HAL output buffer size is %zu frames but AudioMixer requires multiples of 16 frames",
mFrameCount);
}
- if ((mOutput->flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING) &&
- (mOutput->stream->set_callback != NULL)) {
- if (mOutput->stream->set_callback(mOutput->stream,
- AudioFlinger::PlaybackThread::asyncCallback, this) == 0) {
+ if (mOutput->flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING) {
+ if (mOutput->stream->setCallback(this) == OK) {
mUseAsyncWrite = true;
mCallbackThread = new AudioFlinger::AsyncCallbackThread(this);
}
@@ -2402,14 +2385,15 @@
mHwSupportsPause = false;
if (mOutput->flags & AUDIO_OUTPUT_FLAG_DIRECT) {
- if (mOutput->stream->pause != NULL) {
- if (mOutput->stream->resume != NULL) {
+ bool supportsPause = false, supportsResume = false;
+ if (mOutput->stream->supportsPauseAndResume(&supportsPause, &supportsResume) == OK) {
+ if (supportsPause && supportsResume) {
mHwSupportsPause = true;
- } else {
+ } else if (supportsPause) {
ALOGW("direct output implements pause but not resume");
+ } else if (supportsResume) {
+ ALOGW("direct output implements resume but not pause");
}
- } else if (mOutput->stream->resume != NULL) {
- ALOGW("direct output implements resume but not pause");
}
}
if (!mHwSupportsPause && mOutput->flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) {
@@ -2599,12 +2583,12 @@
}
// this method must always be called either with ThreadBase mLock held or inside the thread loop
-audio_stream_t* AudioFlinger::PlaybackThread::stream() const
+sp<StreamHalInterface> AudioFlinger::PlaybackThread::stream() const
{
if (mOutput == NULL) {
return NULL;
}
- return &mOutput->stream->common;
+ return mOutput->stream;
}
uint32_t AudioFlinger::PlaybackThread::activeSleepTimeUs() const
@@ -2742,7 +2726,8 @@
void AudioFlinger::PlaybackThread::threadLoop_drain()
{
- if (mOutput->stream->drain) {
+ bool supportsDrain = false;
+ if (mOutput->stream->supportsDrain(&supportsDrain) == OK && supportsDrain) {
ALOGV("draining %s", (mMixerStatus == MIXER_DRAIN_TRACK) ? "early" : "full");
if (mUseAsyncWrite) {
ALOGW_IF(mDrainSequence & 1, "threadLoop_drain(): out of sequence drain request");
@@ -2750,9 +2735,8 @@
ALOG_ASSERT(mCallbackThread != 0);
mCallbackThread->setDraining(mDrainSequence);
}
- mOutput->stream->drain(mOutput->stream,
- (mMixerStatus == MIXER_DRAIN_TRACK) ? AUDIO_DRAIN_EARLY_NOTIFY
- : AUDIO_DRAIN_ALL);
+ status_t result = mOutput->stream->drain(mMixerStatus == MIXER_DRAIN_TRACK);
+ ALOGE_IF(result != OK, "Error when draining stream: %d", result);
}
}
@@ -3437,11 +3421,9 @@
}
return status;
}
- if ((mType == OFFLOAD || mType == DIRECT)
- && mOutput != NULL && mOutput->stream->get_presentation_position) {
+ if ((mType == OFFLOAD || mType == DIRECT) && mOutput != NULL) {
uint64_t position64;
- int ret = mOutput->getPresentationPosition(&position64, ×tamp.mTime);
- if (ret == 0) {
+ if (mOutput->getPresentationPosition(&position64, ×tamp.mTime) == OK) {
timestamp.mPosition = (uint32_t)position64;
return NO_ERROR;
}
@@ -3509,13 +3491,12 @@
mPatch = *patch;
if (mOutput->audioHwDev->version() >= AUDIO_DEVICE_API_VERSION_3_0) {
- audio_hw_device_t *hwDevice = mOutput->audioHwDev->hwDevice();
- status = hwDevice->create_audio_patch(hwDevice,
- patch->num_sources,
- patch->sources,
- patch->num_sinks,
- patch->sinks,
- handle);
+ sp<DeviceHalInterface> hwDevice = mOutput->audioHwDev->hwDevice();
+ status = hwDevice->createAudioPatch(patch->num_sources,
+ patch->sources,
+ patch->num_sinks,
+ patch->sinks,
+ handle);
} else {
char *address;
if (strcmp(patch->sinks[0].ext.device.address, "") != 0) {
@@ -3529,8 +3510,7 @@
AudioParameter param = AudioParameter(String8(address));
free(address);
param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), (int)type);
- status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
- param.toString().string());
+ status = mOutput->stream->setParameters(param.toString());
*handle = AUDIO_PATCH_HANDLE_NONE;
}
if (configChanged) {
@@ -3561,13 +3541,12 @@
mOutDevice = AUDIO_DEVICE_NONE;
if (mOutput->audioHwDev->version() >= AUDIO_DEVICE_API_VERSION_3_0) {
- audio_hw_device_t *hwDevice = mOutput->audioHwDev->hwDevice();
- status = hwDevice->release_audio_patch(hwDevice, handle);
+ sp<DeviceHalInterface> hwDevice = mOutput->audioHwDev->hwDevice();
+ status = hwDevice->releaseAudioPatch(handle);
} else {
AudioParameter param;
param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), 0);
- status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
- param.toString().string());
+ status = mOutput->stream->setParameters(param.toString());
}
return status;
}
@@ -4133,8 +4112,11 @@
// We have consumed all the buffers of this track.
// This would be incomplete if we auto-paused on underrun
{
- size_t audioHALFrames =
- (mOutput->stream->get_latency(mOutput->stream)*mSampleRate) / 1000;
+ uint32_t latency = 0;
+ status_t result = mOutput->stream->getLatency(&latency);
+ ALOGE_IF(result != OK,
+ "Error when retrieving output stream latency: %d", result);
+ size_t audioHALFrames = (latency * mSampleRate) / 1000;
int64_t framesWritten = mBytesWritten / mFrameSize;
if (!(mStandby || track->presentationComplete(framesWritten, audioHALFrames))) {
// track stays in active list until presentation is complete
@@ -4302,7 +4284,7 @@
// read original volumes with volume control
float typeVolume = mStreamTypes[track->streamType()].volume;
float v = masterVolume * typeVolume;
- AudioTrackServerProxy *proxy = track->mAudioTrackServerProxy;
+ sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
gain_minifloat_packed_t vlr = proxy->getVolumeLR();
vlf = float_from_gain(gain_minifloat_unpack_left(vlr));
vrf = float_from_gain(gain_minifloat_unpack_right(vlr));
@@ -4690,14 +4672,12 @@
}
if (status == NO_ERROR) {
- status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
- keyValuePair.string());
+ status = mOutput->stream->setParameters(keyValuePair);
if (!mStandby && status == INVALID_OPERATION) {
mOutput->standby();
mStandby = true;
mBytesWritten = 0;
- status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
- keyValuePair.string());
+ status = mOutput->stream->setParameters(keyValuePair);
}
if (status == NO_ERROR && reconfig) {
readOutputParameters_l();
@@ -4807,7 +4787,7 @@
} else {
float typeVolume = mStreamTypes[track->streamType()].volume;
float v = mMasterVolume * typeVolume;
- AudioTrackServerProxy *proxy = track->mAudioTrackServerProxy;
+ sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
gain_minifloat_packed_t vlr = proxy->getVolumeLR();
left = float_from_gain(gain_minifloat_unpack_left(vlr));
if (left > GAIN_FLOAT_UNITY) {
@@ -4838,9 +4818,8 @@
left = (float)vl / (1 << 24);
right = (float)vr / (1 << 24);
}
- if (mOutput->stream->set_volume) {
- mOutput->stream->set_volume(mOutput->stream, left, right);
- }
+ status_t result = mOutput->stream->setVolume(left, right);
+ ALOGE_IF(result != OK, "Error when setting output stream volume: %d", result);
}
}
}
@@ -5050,13 +5029,15 @@
// if resume is received before pause is executed.
if (mHwSupportsPause && !mStandby &&
(doHwPause || (mFlushPending && !mHwPaused && (count != 0)))) {
- mOutput->stream->pause(mOutput->stream);
+ status_t result = mOutput->stream->pause();
+ ALOGE_IF(result != OK, "Error when pausing output stream: %d", result);
}
if (mFlushPending) {
flushHw_l();
}
if (mHwSupportsPause && !mStandby && doHwResume) {
- mOutput->stream->resume(mOutput->stream);
+ status_t result = mOutput->stream->resume();
+ ALOGE_IF(result != OK, "Error when resuming output stream: %d", result);
}
// remove all the tracks that need to be...
removeTracks_l(*tracksToRemove);
@@ -5197,14 +5178,12 @@
}
}
if (status == NO_ERROR) {
- status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
- keyValuePair.string());
+ status = mOutput->stream->setParameters(keyValuePair);
if (!mStandby && status == INVALID_OPERATION) {
mOutput->standby();
mStandby = true;
mBytesWritten = 0;
- status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
- keyValuePair.string());
+ status = mOutput->stream->setParameters(keyValuePair);
}
if (status == NO_ERROR && reconfig) {
readOutputParameters_l();
@@ -5591,8 +5570,11 @@
// Drain has completed or we are in standby, signal presentation complete
if (!(mDrainSequence & 1) || !last || mStandby) {
track->mState = TrackBase::STOPPED;
- size_t audioHALFrames =
- (mOutput->stream->get_latency(mOutput->stream)*mSampleRate) / 1000;
+ uint32_t latency = 0;
+ status_t result = mOutput->stream->getLatency(&latency);
+ ALOGE_IF(result != OK,
+ "Error when retrieving output stream latency: %d", result);
+ size_t audioHALFrames = (latency * mSampleRate) / 1000;
int64_t framesWritten =
mBytesWritten / mOutput->getFrameSize();
track->presentationComplete(framesWritten, audioHALFrames);
@@ -5604,16 +5586,15 @@
// fill a buffer, then remove it from active list.
if (--(track->mRetryCount) <= 0) {
bool running = false;
- if (mOutput->stream->get_presentation_position != nullptr) {
- uint64_t position = 0;
- struct timespec unused;
- // The running check restarts the retry counter at least once.
- int ret = mOutput->stream->get_presentation_position(
- mOutput->stream, &position, &unused);
- if (ret == NO_ERROR && position != mOffloadUnderrunPosition) {
- running = true;
- mOffloadUnderrunPosition = position;
- }
+ uint64_t position = 0;
+ struct timespec unused;
+ // The running check restarts the retry counter at least once.
+ status_t ret = mOutput->stream->getPresentationPosition(&position, &unused);
+ if (ret == NO_ERROR && position != mOffloadUnderrunPosition) {
+ running = true;
+ mOffloadUnderrunPosition = position;
+ }
+ if (ret == NO_ERROR) {
ALOGVV("underrun counter, running(%d): %lld vs %lld", running,
(long long)position, (long long)mOffloadUnderrunPosition);
}
@@ -5641,13 +5622,15 @@
// before flush and then resume HW. This can happen in case of pause/flush/resume
// if resume is received before pause is executed.
if (!mStandby && (doHwPause || (mFlushPending && !mHwPaused && (count != 0)))) {
- mOutput->stream->pause(mOutput->stream);
+ status_t result = mOutput->stream->pause();
+ ALOGE_IF(result != OK, "Error when pausing output stream: %d", result);
}
if (mFlushPending) {
flushHw_l();
}
if (!mStandby && doHwResume) {
- mOutput->stream->resume(mOutput->stream);
+ status_t result = mOutput->stream->resume();
+ ALOGE_IF(result != OK, "Error when resuming output stream: %d", result);
}
// remove all the tracks that need to be...
@@ -5899,7 +5882,7 @@
) :
ThreadBase(audioFlinger, id, outDevice, inDevice, RECORD, systemReady),
mInput(input), mActiveTracksGen(0), mRsmpInBuffer(NULL),
- // mRsmpInFrames and mRsmpInFramesP2 are set by readInputParameters_l()
+ // mRsmpInFrames, mRsmpInFramesP2, and mRsmpInFramesOA are set by readInputParameters_l()
mRsmpInRear(0)
#ifdef TEE_SINK
, mTeeSink(teeSink)
@@ -5951,7 +5934,8 @@
if (initFastCapture) {
// create a Pipe for FastCapture to write to, and for us and fast tracks to read from
NBAIO_Format format = mInputSource->format();
- size_t pipeFramesP2 = roundup(mSampleRate / 25); // double-buffering of 20 ms each
+ // quadruple-buffering of 20 ms each; this ensures we can sleep for 20ms in RecordThread
+ size_t pipeFramesP2 = roundup(4 * FMS_20 * mSampleRate / 1000);
size_t pipeSize = pipeFramesP2 * Format_frameSize(format);
void *pipeBuffer;
const sp<MemoryDealer> roHeap(readOnlyHeap());
@@ -6281,20 +6265,41 @@
// If an NBAIO source is present, use it to read the normal capture's data
if (mPipeSource != 0) {
size_t framesToRead = mBufferSize / mFrameSize;
+ framesToRead = min(mRsmpInFramesOA - rear, mRsmpInFramesP2 / 2);
framesRead = mPipeSource->read((uint8_t*)mRsmpInBuffer + rear * mFrameSize,
framesToRead);
- if (framesRead == 0) {
- // since pipe is non-blocking, simulate blocking input
- sleepUs = (framesToRead * 1000000LL) / mSampleRate;
+ // since pipe is non-blocking, simulate blocking input by waiting for 1/2 of
+ // buffer size or at least for 20ms.
+ size_t sleepFrames = max(
+ min(mPipeFramesP2, mRsmpInFramesP2) / 2, FMS_20 * mSampleRate / 1000);
+ if (framesRead <= (ssize_t) sleepFrames) {
+ sleepUs = (sleepFrames * 1000000LL) / mSampleRate;
+ }
+ if (framesRead < 0) {
+ status_t status = (status_t) framesRead;
+ switch (status) {
+ case OVERRUN:
+ ALOGW("overrun on read from pipe");
+ framesRead = 0;
+ break;
+ case NEGOTIATE:
+ ALOGE("re-negotiation is needed");
+ framesRead = -1; // Will cause an attempt to recover.
+ break;
+ default:
+ ALOGE("unknown error %d on read from pipe", status);
+ break;
+ }
}
// otherwise use the HAL / AudioStreamIn directly
} else {
ATRACE_BEGIN("read");
- ssize_t bytesRead = mInput->stream->read(mInput->stream,
- (uint8_t*)mRsmpInBuffer + rear * mFrameSize, mBufferSize);
+ size_t bytesRead;
+ status_t result = mInput->stream->read(
+ (uint8_t*)mRsmpInBuffer + rear * mFrameSize, mBufferSize, &bytesRead);
ATRACE_END();
- if (bytesRead < 0) {
- framesRead = bytesRead;
+ if (result < 0) {
+ framesRead = result;
} else {
framesRead = bytesRead / mFrameSize;
}
@@ -6306,10 +6311,9 @@
mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = systemTime();
// Update server timestamp with kernel stats
- if (mInput->stream->get_capture_position != nullptr
- && mPipeSource.get() == nullptr /* don't obtain for FastCapture, could block */) {
+ if (mPipeSource.get() == nullptr /* don't obtain for FastCapture, could block */) {
int64_t position, time;
- int ret = mInput->stream->get_capture_position(mInput->stream, &position, &time);
+ int ret = mInput->stream->getCapturePosition(&position, &time);
if (ret == NO_ERROR) {
mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = position;
mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] = time;
@@ -6518,7 +6522,18 @@
sq->end(false /*didModify*/);
}
}
- mInput->stream->common.standby(&mInput->stream->common);
+ status_t result = mInput->stream->standby();
+ ALOGE_IF(result != OK, "Error when putting input stream into standby: %d", result);
+
+ // If going into standby, flush the pipe source.
+ if (mPipeSource.get() != nullptr) {
+ const ssize_t flushed = mPipeSource->flush();
+ if (flushed > 0) {
+ ALOGV("Input standby flushed PipeSource %zd frames", flushed);
+ mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER] += flushed;
+ mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = systemTime();
+ }
+ }
}
// RecordThread::createRecordTrack_l() must be called with AudioFlinger::mLock held
@@ -7361,22 +7376,22 @@
}
if (status == NO_ERROR) {
- status = mInput->stream->common.set_parameters(&mInput->stream->common,
- keyValuePair.string());
+ status = mInput->stream->setParameters(keyValuePair);
if (status == INVALID_OPERATION) {
inputStandBy();
- status = mInput->stream->common.set_parameters(&mInput->stream->common,
- keyValuePair.string());
+ status = mInput->stream->setParameters(keyValuePair);
}
if (reconfig) {
- if (status == BAD_VALUE &&
- audio_is_linear_pcm(mInput->stream->common.get_format(&mInput->stream->common)) &&
- audio_is_linear_pcm(reqFormat) &&
- (mInput->stream->common.get_sample_rate(&mInput->stream->common)
- <= (AUDIO_RESAMPLER_DOWN_RATIO_MAX * samplingRate)) &&
- audio_channel_count_from_in_mask(
- mInput->stream->common.get_channels(&mInput->stream->common)) <= FCC_8) {
- status = NO_ERROR;
+ if (status == BAD_VALUE) {
+ uint32_t sRate;
+ audio_channel_mask_t channelMask;
+ audio_format_t format;
+ if (mInput->stream->getAudioProperties(&sRate, &channelMask, &format) == OK &&
+ audio_is_linear_pcm(format) && audio_is_linear_pcm(reqFormat) &&
+ sRate <= (AUDIO_RESAMPLER_DOWN_RATIO_MAX * samplingRate) &&
+ audio_channel_count_from_in_mask(channelMask) <= FCC_8) {
+ status = NO_ERROR;
+ }
}
if (status == NO_ERROR) {
readInputParameters_l();
@@ -7391,14 +7406,13 @@
String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
{
Mutex::Autolock _l(mLock);
- if (initCheck() != NO_ERROR) {
- return String8();
+ if (initCheck() == NO_ERROR) {
+ String8 out_s8;
+ if (mInput->stream->getParameters(keys, &out_s8) == OK) {
+ return out_s8;
+ }
}
-
- char *s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string());
- const String8 out_s8(s);
- free(s);
- return out_s8;
+ return String8();
}
void AudioFlinger::RecordThread::ioConfigChanged(audio_io_config_event event, pid_t pid) {
@@ -7427,19 +7441,16 @@
void AudioFlinger::RecordThread::readInputParameters_l()
{
- mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common);
- mChannelMask = mInput->stream->common.get_channels(&mInput->stream->common);
+ status_t result = mInput->stream->getAudioProperties(&mSampleRate, &mChannelMask, &mHALFormat);
+ LOG_ALWAYS_FATAL_IF(result != OK, "Error retrieving audio properties from HAL: %d", result);
mChannelCount = audio_channel_count_from_in_mask(mChannelMask);
- if (mChannelCount > FCC_8) {
- ALOGE("HAL channel count %d > %d", mChannelCount, FCC_8);
- }
- mHALFormat = mInput->stream->common.get_format(&mInput->stream->common);
+ LOG_ALWAYS_FATAL_IF(mChannelCount > FCC_8, "HAL channel count %d > %d", mChannelCount, FCC_8);
mFormat = mHALFormat;
- if (!audio_is_linear_pcm(mFormat)) {
- ALOGE("HAL format %#x is not linear pcm", mFormat);
- }
- mFrameSize = audio_stream_in_frame_size(mInput->stream);
- mBufferSize = mInput->stream->common.get_buffer_size(&mInput->stream->common);
+ LOG_ALWAYS_FATAL_IF(!audio_is_linear_pcm(mFormat), "HAL format %#x is not linear pcm", mFormat);
+ result = mInput->stream->getFrameSize(&mFrameSize);
+ LOG_ALWAYS_FATAL_IF(result != OK, "Error retrieving frame size from HAL: %d", result);
+ result = mInput->stream->getBufferSize(&mBufferSize);
+ LOG_ALWAYS_FATAL_IF(result != OK, "Error retrieving buffer size from HAL: %d", result);
mFrameCount = mBufferSize / mFrameSize;
// This is the formula for calculating the temporary buffer size.
// With 7 HAL buffers, we can guarantee ability to down-sample the input by ratio of 6:1 to
@@ -7462,9 +7473,9 @@
// The current value is higher than necessary. However it should not add to latency.
// Over-allocate beyond mRsmpInFramesP2 to permit a HAL read past end of buffer
- size_t bufferSize = (mRsmpInFramesP2 + mFrameCount - 1) * mFrameSize;
- (void)posix_memalign(&mRsmpInBuffer, 32, bufferSize);
- memset(mRsmpInBuffer, 0, bufferSize); // if posix_memalign fails, will segv here.
+ mRsmpInFramesOA = mRsmpInFramesP2 + mFrameCount - 1;
+ (void)posix_memalign(&mRsmpInBuffer, 32, mRsmpInFramesOA * mFrameSize);
+ memset(mRsmpInBuffer, 0, mRsmpInFramesOA * mFrameSize); // if posix_memalign fails, will segv here.
// AudioRecord mSampleRate and mChannelCount are constant due to AudioRecord API constraints.
// But if thread's mSampleRate or mChannelCount changes, how will that affect active tracks?
@@ -7473,11 +7484,11 @@
uint32_t AudioFlinger::RecordThread::getInputFramesLost()
{
Mutex::Autolock _l(mLock);
- if (initCheck() != NO_ERROR) {
- return 0;
+ uint32_t result;
+ if (initCheck() == NO_ERROR && mInput->stream->getInputFramesLost(&result) == OK) {
+ return result;
}
-
- return mInput->stream->get_input_frames_lost(mInput->stream);
+ return 0;
}
// hasAudioSession_l() must be called with ThreadBase::mLock held
@@ -7524,12 +7535,12 @@
}
// this method must always be called either with ThreadBase mLock held or inside the thread loop
-audio_stream_t* AudioFlinger::RecordThread::stream() const
+sp<StreamHalInterface> AudioFlinger::RecordThread::stream() const
{
if (mInput == NULL) {
return NULL;
}
- return &mInput->stream->common;
+ return mInput->stream;
}
status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain)
@@ -7600,13 +7611,12 @@
}
if (mInput->audioHwDev->version() >= AUDIO_DEVICE_API_VERSION_3_0) {
- audio_hw_device_t *hwDevice = mInput->audioHwDev->hwDevice();
- status = hwDevice->create_audio_patch(hwDevice,
- patch->num_sources,
- patch->sources,
- patch->num_sinks,
- patch->sinks,
- handle);
+ sp<DeviceHalInterface> hwDevice = mInput->audioHwDev->hwDevice();
+ status = hwDevice->createAudioPatch(patch->num_sources,
+ patch->sources,
+ patch->num_sinks,
+ patch->sinks,
+ handle);
} else {
char *address;
if (strcmp(patch->sources[0].ext.device.address, "") != 0) {
@@ -7622,8 +7632,7 @@
(int)patch->sources[0].ext.device.type);
param.addInt(String8(AUDIO_PARAMETER_STREAM_INPUT_SOURCE),
(int)patch->sinks[0].ext.mix.usecase.source);
- status = mInput->stream->common.set_parameters(&mInput->stream->common,
- param.toString().string());
+ status = mInput->stream->setParameters(param.toString());
*handle = AUDIO_PATCH_HANDLE_NONE;
}
@@ -7642,13 +7651,12 @@
mInDevice = AUDIO_DEVICE_NONE;
if (mInput->audioHwDev->version() >= AUDIO_DEVICE_API_VERSION_3_0) {
- audio_hw_device_t *hwDevice = mInput->audioHwDev->hwDevice();
- status = hwDevice->release_audio_patch(hwDevice, handle);
+ sp<DeviceHalInterface> hwDevice = mInput->audioHwDev->hwDevice();
+ status = hwDevice->releaseAudioPatch(handle);
} else {
AudioParameter param;
param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), 0);
- status = mInput->stream->common.set_parameters(&mInput->stream->common,
- param.toString().string());
+ status = mInput->stream->setParameters(param.toString());
}
return status;
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index a55655f..da0c705 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -286,7 +286,7 @@
audio_devices_t outDevice() const { return mOutDevice; }
audio_devices_t inDevice() const { return mInDevice; }
- virtual audio_stream_t* stream() const = 0;
+ virtual sp<StreamHalInterface> stream() const = 0;
sp<EffectHandle> createEffect_l(
const sp<AudioFlinger::Client>& client,
@@ -484,7 +484,7 @@
};
// --- PlaybackThread ---
-class PlaybackThread : public ThreadBase {
+class PlaybackThread : public ThreadBase, public StreamOutHalInterfaceCallback {
public:
#include "PlaybackTracks.h"
@@ -541,13 +541,13 @@
virtual mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove) = 0;
void removeTracks_l(const Vector< sp<Track> >& tracksToRemove);
- void writeCallback();
- void resetWriteBlocked(uint32_t sequence);
- void drainCallback();
- void resetDraining(uint32_t sequence);
- void errorCallback();
+ // StreamOutHalInterfaceCallback implementation
+ virtual void onWriteReady();
+ virtual void onDrainReady();
+ virtual void onError();
- static int asyncCallback(stream_callback_event_t event, void *param, void *cookie);
+ void resetWriteBlocked(uint32_t sequence);
+ void resetDraining(uint32_t sequence);
virtual bool waitingAsyncCallback();
virtual bool waitingAsyncCallback_l();
@@ -593,7 +593,7 @@
AudioStreamOut* getOutput() const;
AudioStreamOut* clearOutput();
- virtual audio_stream_t* stream() const;
+ virtual sp<StreamHalInterface> stream() const;
// a very large number of suspend() will eventually wraparound, but unlikely
void suspend() { (void) android_atomic_inc(&mSuspended); }
@@ -1301,7 +1301,7 @@
void dump(int fd, const Vector<String16>& args);
AudioStreamIn* clearInput();
- virtual audio_stream_t* stream() const;
+ virtual sp<StreamHalInterface> stream() const;
virtual bool checkForNewParameter_l(const String8& keyValuePair,
@@ -1357,9 +1357,10 @@
Condition mStartStopCond;
// resampler converts input at HAL Hz to output at AudioRecord client Hz
- void *mRsmpInBuffer; //
+ void *mRsmpInBuffer; // size = mRsmpInFramesOA
size_t mRsmpInFrames; // size of resampler input in frames
size_t mRsmpInFramesP2;// size rounded up to a power-of-2
+ size_t mRsmpInFramesOA;// mRsmpInFramesP2 + over-allocation
// rolling index that is never cleared
int32_t mRsmpInRear; // last filled frame + 1
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 6b97246..7c48375 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -156,7 +156,7 @@
int mUid;
Vector < sp<SyncEvent> >mSyncEvents;
const bool mIsOut;
- ServerProxy* mServerProxy;
+ sp<ServerProxy> mServerProxy;
const int mId;
sp<NBAIO_Sink> mTeeSink;
sp<NBAIO_Source> mTeeSource;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index ba6e6e5..e1fe7e2 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -52,7 +52,7 @@
// TODO move to a common header (Also shared with AudioTrack.cpp)
#define NANOS_PER_SECOND 1000000000
-#define TIME_TO_NANOS(time) ((uint64_t)time.tv_sec * NANOS_PER_SECOND + time.tv_nsec)
+#define TIME_TO_NANOS(time) ((uint64_t)(time).tv_sec * NANOS_PER_SECOND + (time).tv_nsec)
namespace android {
@@ -93,7 +93,6 @@
mFrameCount(frameCount),
mSessionId(sessionId),
mIsOut(isOut),
- mServerProxy(NULL),
mId(android_atomic_inc(&nextTrackId)),
mTerminated(false),
mType(type),
@@ -218,7 +217,7 @@
dumpTee(-1, mTeeSource, mId);
#endif
// delete the proxy before deleting the shared memory it refers to, to avoid dangling reference
- delete mServerProxy;
+ mServerProxy.clear();
if (mCblk != NULL) {
if (mClient == 0) {
delete mCblk;
@@ -364,7 +363,6 @@
mFastIndex(-1),
mCachedVolume(1.0),
mIsInvalid(false),
- mAudioTrackServerProxy(NULL),
mResumeToStopping(false),
mFlushHwPending(false),
mFlags(flags)
@@ -1145,7 +1143,7 @@
sampleRate, format, channelMask, frameCount,
NULL, 0, AUDIO_SESSION_NONE, uid, AUDIO_OUTPUT_FLAG_NONE,
TYPE_OUTPUT),
- mActive(false), mSourceThread(sourceThread), mClientProxy(NULL)
+ mActive(false), mSourceThread(sourceThread)
{
if (mCblk != NULL) {
@@ -1170,7 +1168,6 @@
AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
{
clearBufferQueue();
- delete mClientProxy;
// superclass destructor will now delete the server proxy and shared memory both refer to
}
diff --git a/services/audioflinger/tests/Android.mk b/services/audioflinger/tests/Android.mk
index 3505e0f..75fc6f5 100644
--- a/services/audioflinger/tests/Android.mk
+++ b/services/audioflinger/tests/Android.mk
@@ -34,7 +34,7 @@
LOCAL_SRC_FILES:= \
test-mixer.cpp \
- ../AudioMixer.cpp.arm \
+ ../AudioMixer.cpp.arm \
../BufferProviders.cpp
LOCAL_C_INCLUDES := \
@@ -47,6 +47,7 @@
libsndfile
LOCAL_SHARED_LIBRARIES := \
+ libaudiohal \
libeffects \
libnbaio \
libaudioresampler \
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index bb8a8fa..a1221fc 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -67,6 +67,16 @@
API_INPUT_TELEPHONY_RX, // used for capture from telephony RX path
} input_type_t;
+ enum {
+ API_INPUT_CONCURRENCY_NONE = 0,
+ API_INPUT_CONCURRENCY_CALL = (1 << 0), // Concurrency with a call
+ API_INPUT_CONCURRENCY_CAPTURE = (1 << 1), // Concurrency with another capture
+
+ API_INPUT_CONCURRENCY_ALL = (API_INPUT_CONCURRENCY_CALL | API_INPUT_CONCURRENCY_CAPTURE),
+ };
+
+ typedef uint32_t concurrency_type__mask_t;
+
public:
virtual ~AudioPolicyInterface() {}
//
@@ -140,7 +150,8 @@
input_type_t *inputType) = 0;
// indicates to the audio policy manager that the input starts being used.
virtual status_t startInput(audio_io_handle_t input,
- audio_session_t session) = 0;
+ audio_session_t session,
+ concurrency_type__mask_t *concurrency) = 0;
// indicates to the audio policy manager that the input stops being used.
virtual status_t stopInput(audio_io_handle_t input,
audio_session_t session) = 0;
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 55ee91f..71d70de 100755
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -33,9 +33,9 @@
/**
* A device mask for all audio input devices that are considered "virtual" when evaluating
- * active inputs in getActiveInput()
+ * active inputs in getActiveInputs()
*/
-#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_FM_TUNER)
+#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX)
/**
@@ -109,6 +109,44 @@
((device & APM_AUDIO_DEVICE_OUT_MATCH_ADDRESS_ALL) != 0));
}
+/**
+ * Returns the priority of a given audio source for capture. The priority is used when more than one
+ * capture session is active on a given input stream to determine which session drives routing and
+ * effect configuration.
+ *
+ * @param[in] inputSource to consider. Valid sources are:
+ * - AUDIO_SOURCE_VOICE_COMMUNICATION
+ * - AUDIO_SOURCE_CAMCORDER
+ * - AUDIO_SOURCE_MIC
+ * - AUDIO_SOURCE_FM_TUNER
+ * - AUDIO_SOURCE_VOICE_RECOGNITION
+ * - AUDIO_SOURCE_HOTWORD
+ *
+ * @return the corresponding input source priority or 0 if priority is irrelevant for this source.
+ * This happens when the specified source cannot share a given input stream (e.g remote submix)
+ * The higher the value, the higher the priority.
+ */
+static inline int32_t source_priority(audio_source_t inputSource)
+{
+ switch (inputSource) {
+ case AUDIO_SOURCE_VOICE_COMMUNICATION:
+ return 6;
+ case AUDIO_SOURCE_CAMCORDER:
+ return 5;
+ case AUDIO_SOURCE_MIC:
+ return 4;
+ case AUDIO_SOURCE_FM_TUNER:
+ return 3;
+ case AUDIO_SOURCE_VOICE_RECOGNITION:
+ return 2;
+ case AUDIO_SOURCE_HOTWORD:
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
/* Indicates if audio formats are equivalent when considering a match between
* audio HAL supported formats and client requested formats
*/
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index e689320..5445413 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -63,7 +63,9 @@
const sp<AudioSession>& audioSession);
status_t removeAudioSession(audio_session_t session);
sp<AudioSession> getAudioSession(audio_session_t session) const;
- AudioSessionCollection getActiveAudioSessions() const;
+ AudioSessionCollection getAudioSessions(bool activeOnly) const;
+ size_t getAudioSessionCount(bool activeOnly) const;
+ audio_source_t getHighestPrioritySource(bool activeOnly) const;
// implementation of AudioSessionInfoProvider
virtual audio_config_base_t getConfig() const;
@@ -102,7 +104,7 @@
* Only considers inputs from physical devices (e.g. main mic, headset mic) when
* ignoreVirtualInputs is true.
*/
- audio_io_handle_t getActiveInput(bool ignoreVirtualInputs = true);
+ Vector<sp <AudioInputDescriptor> > getActiveInputs(bool ignoreVirtualInputs = true);
audio_devices_t getSupportedDevices(audio_io_handle_t handle) const;
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index c9652de..97a9c94 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -19,7 +19,7 @@
#include <utils/RefBase.h>
#include <media/AudioPolicy.h>
#include <utils/KeyedVector.h>
-#include <hardware/audio.h>
+#include <system/audio.h>
#include <utils/String8.h>
namespace android {
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
index d00d49f..99c0cd2 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
@@ -166,6 +166,10 @@
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig = NULL) const = 0;
virtual sp<AudioPort> getAudioPort() const = 0;
+ virtual bool hasSameHwModuleAs(const sp<AudioPortConfig>& other) const {
+ return (other != 0) &&
+ (other->getAudioPort()->getModuleHandle() == getAudioPort()->getModuleHandle());
+ }
uint32_t mSamplingRate;
audio_format_t mFormat;
audio_channel_mask_t mChannelMask;
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioSession.h b/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
index 388c25d..18fba25 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
@@ -91,8 +91,10 @@
uint32_t getOpenCount() const;
AudioSessionCollection getActiveSessions() const;
+ size_t getActiveSessionCount() const;
bool hasActiveSession() const;
bool isSourceActive(audio_source_t source) const;
+ audio_source_t getHighestPrioritySource(bool activeOnly) const;
// implementation of AudioSessionInfoUpdateListener
virtual void onSessionInfoUpdate() const;
diff --git a/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h
index 424df84..8822927 100644
--- a/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h
@@ -20,7 +20,7 @@
#include <utils/KeyedVector.h>
#include <utils/StrongPointer.h>
#include <utils/SortedVector.h>
-#include <hardware/audio.h>
+#include <system/audio.h>
namespace android {
diff --git a/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h b/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h
index 1612714..069c9e7 100644
--- a/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h
+++ b/services/audiopolicy/common/managerdefinitions/include/TypeConverter.h
@@ -67,19 +67,24 @@
};
struct StreamTraits
{
- typedef audio_stream_type_t Type;
- typedef Vector<Type> Collection;
+ typedef audio_stream_type_t Type;
+ typedef Vector<Type> Collection;
};
struct DeviceCategoryTraits
{
- typedef device_category Type;
- typedef Vector<Type> Collection;
+ typedef device_category Type;
+ typedef Vector<Type> Collection;
+};
+struct AudioModeTraits
+{
+ typedef audio_mode_t Type;
+ typedef Vector<Type> Collection;
};
template <typename T>
struct DefaultTraits
{
- typedef T Type;
- typedef Vector<Type> Collection;
+ typedef T Type;
+ typedef Vector<Type> Collection;
};
template <class Traits>
@@ -110,6 +115,8 @@
static uint32_t maskFromString(const std::string &str, const char *del = "|");
+ static void maskToString(uint32_t mask, std::string &str, const char *del = "|");
+
protected:
struct Table {
const char *literal;
@@ -117,7 +124,6 @@
};
static const Table mTable[];
- static const size_t mSize;
};
typedef TypeConverter<DeviceTraits> DeviceConverter;
@@ -130,6 +136,7 @@
typedef TypeConverter<GainModeTraits> GainModeConverter;
typedef TypeConverter<StreamTraits> StreamTypeConverter;
typedef TypeConverter<DeviceCategoryTraits> DeviceCategoryConverter;
+typedef TypeConverter<AudioModeTraits> AudioModeConverter;
inline
static SampleRateTraits::Collection samplingRatesFromString(const std::string &samplingRates,
diff --git a/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h b/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
index 10f0766..e7fcefc 100644
--- a/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
+++ b/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
@@ -18,7 +18,6 @@
#include "IVolumeCurvesCollection.h"
#include <policy.h>
-#include <hardware/audio.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
#include <utils/SortedVector.h>
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index c7d2ee4..44f9637 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -132,6 +132,12 @@
return mSessions.isSourceActive(source);
}
+audio_source_t AudioInputDescriptor::getHighestPrioritySource(bool activeOnly) const
+{
+
+ return mSessions.getHighestPrioritySource(activeOnly);
+}
+
bool AudioInputDescriptor::isSoundTrigger() const {
// sound trigger and non sound trigger sessions are not mixed
// on a given input
@@ -143,9 +149,22 @@
return mSessions.valueFor(session);
}
-AudioSessionCollection AudioInputDescriptor::getActiveAudioSessions() const
+AudioSessionCollection AudioInputDescriptor::getAudioSessions(bool activeOnly) const
{
- return mSessions.getActiveSessions();
+ if (activeOnly) {
+ return mSessions.getActiveSessions();
+ } else {
+ return mSessions;
+ }
+}
+
+size_t AudioInputDescriptor::getAudioSessionCount(bool activeOnly) const
+{
+ if (activeOnly) {
+ return mSessions.getActiveSessionCount();
+ } else {
+ return mSessions.size();
+ }
}
status_t AudioInputDescriptor::addAudioSession(audio_session_t session,
@@ -236,17 +255,19 @@
return count;
}
-audio_io_handle_t AudioInputCollection::getActiveInput(bool ignoreVirtualInputs)
+Vector<sp <AudioInputDescriptor> > AudioInputCollection::getActiveInputs(bool ignoreVirtualInputs)
{
+ Vector<sp <AudioInputDescriptor> > activeInputs;
+
for (size_t i = 0; i < size(); i++) {
const sp<AudioInputDescriptor> inputDescriptor = valueAt(i);
if ((inputDescriptor->isActive())
&& (!ignoreVirtualInputs ||
!is_virtual_input_device(inputDescriptor->mDevice))) {
- return keyAt(i);
+ activeInputs.add(inputDescriptor);
}
}
- return 0;
+ return activeInputs;
}
audio_devices_t AudioInputCollection::getSupportedDevices(audio_io_handle_t handle) const
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 1dbc3d0..93b7f47 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -81,7 +81,7 @@
return sharesHwModuleWith(outputDesc->subOutput1()) ||
sharesHwModuleWith(outputDesc->subOutput2());
} else {
- return (getModuleHandle() == outputDesc->getModuleHandle());
+ return hasSameHwModuleAs(outputDesc);
}
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
index da983c5..3b63239 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
@@ -18,6 +18,7 @@
//#define LOG_NDEBUG 0
#include <AudioPolicyInterface.h>
+#include "policy.h"
#include "AudioSession.h"
#include "AudioGain.h"
#include "TypeConverter.h"
@@ -214,9 +215,20 @@
return activeSessions;
}
+size_t AudioSessionCollection::getActiveSessionCount() const
+{
+ size_t activeCount = 0;
+ for (size_t i = 0; i < size(); i++) {
+ if (valueAt(i)->activeCount() != 0) {
+ activeCount++;
+ }
+ }
+ return activeCount;
+}
+
bool AudioSessionCollection::hasActiveSession() const
{
- return getActiveSessions().size() != 0;
+ return getActiveSessionCount() != 0;
}
bool AudioSessionCollection::isSourceActive(audio_source_t source) const
@@ -236,6 +248,25 @@
return false;
}
+audio_source_t AudioSessionCollection::getHighestPrioritySource(bool activeOnly) const
+{
+ audio_source_t source = AUDIO_SOURCE_DEFAULT;
+ int32_t priority = -1;
+
+ for (size_t i = 0; i < size(); i++) {
+ const sp<AudioSession> audioSession = valueAt(i);
+ if (activeOnly && audioSession->activeCount() == 0) {
+ continue;
+ }
+ int32_t curPriority = source_priority(audioSession->inputSource());
+ if (curPriority > priority) {
+ priority = curPriority;
+ source = audioSession->inputSource();
+ }
+ }
+ return source;
+}
+
void AudioSessionCollection::onSessionInfoUpdate() const
{
for (size_t i = 0; i < size(); i++) {
@@ -243,7 +274,6 @@
}
}
-
status_t AudioSessionCollection::dump(int fd, int spaces) const
{
const size_t SIZE = 256;
diff --git a/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
index a3536e5..e32d0d3 100644
--- a/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
@@ -22,7 +22,7 @@
#include "AudioGain.h"
#include "IOProfile.h"
#include "TypeConverter.h"
-#include <hardware/audio.h>
+#include <system/audio.h>
#include <utils/Log.h>
#include <cutils/misc.h>
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 7a942cd..356aef1 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -20,8 +20,8 @@
#include "HwModule.h"
#include "IOProfile.h"
#include "AudioGain.h"
-#include <hardware/audio.h>
#include <policy.h>
+#include <system/audio.h>
namespace android {
@@ -42,8 +42,8 @@
}
}
-status_t HwModule::addOutputProfile(const String8 &name, const audio_config_t *config,
- audio_devices_t device, const String8 &address)
+status_t HwModule::addOutputProfile(const String8& name, const audio_config_t *config,
+ audio_devices_t device, const String8& address)
{
sp<IOProfile> profile = new OutputProfile(name);
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index 57f2534..74ef4ec 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -108,8 +108,18 @@
AudioPort::dump(fd, 4);
- snprintf(buffer, SIZE, " - flags: 0x%04x\n", getFlags());
+ snprintf(buffer, SIZE, " - flags: 0x%04x", getFlags());
result.append(buffer);
+ std::string flagsLiteral;
+ if (getRole() == AUDIO_PORT_ROLE_SINK) {
+ InputFlagConverter::maskToString(getFlags(), flagsLiteral);
+ } else if (getRole() == AUDIO_PORT_ROLE_SOURCE) {
+ OutputFlagConverter::maskToString(getFlags(), flagsLiteral);
+ }
+ if (!flagsLiteral.empty()) {
+ result.appendFormat(" (%s)", flagsLiteral.c_str());
+ }
+ result.append("\n");
write(fd, result.string(), result.size());
mSupportedDevices.dump(fd, String8("Supported"), 4, false);
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
index 48bfd79..cfc0985 100644
--- a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
@@ -78,10 +78,6 @@
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_STUB),
};
-template<>
-const size_t DeviceConverter::mSize = sizeof(DeviceConverter::mTable) /
- sizeof(DeviceConverter::mTable[0]);
-
template <>
const OutputFlagConverter::Table OutputFlagConverter::mTable[] = {
@@ -96,9 +92,6 @@
MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_RAW),
MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_SYNC),
};
-template<>
-const size_t OutputFlagConverter::mSize = sizeof(OutputFlagConverter::mTable) /
- sizeof(OutputFlagConverter::mTable[0]);
template <>
@@ -108,9 +101,6 @@
MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_RAW),
MAKE_STRING_FROM_ENUM(AUDIO_INPUT_FLAG_SYNC),
};
-template<>
-const size_t InputFlagConverter::mSize = sizeof(InputFlagConverter::mTable) /
- sizeof(InputFlagConverter::mTable[0]);
template <>
@@ -144,9 +134,6 @@
MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_IEC61937),
MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
};
-template<>
-const size_t FormatConverter::mSize = sizeof(FormatConverter::mTable) /
- sizeof(FormatConverter::mTable[0]);
template <>
@@ -157,9 +144,6 @@
MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
};
-template<>
-const size_t OutputChannelConverter::mSize = sizeof(OutputChannelConverter::mTable) /
- sizeof(OutputChannelConverter::mTable[0]);
template <>
@@ -168,9 +152,6 @@
MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_STEREO),
MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
};
-template<>
-const size_t InputChannelConverter::mSize = sizeof(InputChannelConverter::mTable) /
- sizeof(InputChannelConverter::mTable[0]);
template <>
const ChannelIndexConverter::Table ChannelIndexConverter::mTable[] = {
@@ -183,9 +164,6 @@
{"AUDIO_CHANNEL_INDEX_MASK_7", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_7)},
{"AUDIO_CHANNEL_INDEX_MASK_8", static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_INDEX_MASK_8)},
};
-template<>
-const size_t ChannelIndexConverter::mSize = sizeof(ChannelIndexConverter::mTable) /
- sizeof(ChannelIndexConverter::mTable[0]);
template <>
@@ -195,9 +173,6 @@
MAKE_STRING_FROM_ENUM(AUDIO_GAIN_MODE_RAMP),
};
-template<>
-const size_t GainModeConverter::mSize = sizeof(GainModeConverter::mTable) /
- sizeof(GainModeConverter::mTable[0]);
template <>
const DeviceCategoryConverter::Table DeviceCategoryConverter::mTable[] = {
@@ -207,9 +182,6 @@
MAKE_STRING_FROM_ENUM(DEVICE_CATEGORY_EXT_MEDIA)
};
-template<>
-const size_t DeviceCategoryConverter::mSize = sizeof(DeviceCategoryConverter::mTable) /
- sizeof(DeviceCategoryConverter::mTable[0]);
template <>
const StreamTypeConverter::Table StreamTypeConverter::mTable[] = {
@@ -228,26 +200,37 @@
MAKE_STRING_FROM_ENUM(AUDIO_STREAM_PATCH),
};
+
template<>
-const size_t StreamTypeConverter::mSize = sizeof(StreamTypeConverter::mTable) /
- sizeof(StreamTypeConverter::mTable[0]);
+const AudioModeConverter::Table AudioModeConverter::mTable[] = {
+ MAKE_STRING_FROM_ENUM(AUDIO_MODE_INVALID),
+ MAKE_STRING_FROM_ENUM(AUDIO_MODE_CURRENT),
+ MAKE_STRING_FROM_ENUM(AUDIO_MODE_NORMAL),
+ MAKE_STRING_FROM_ENUM(AUDIO_MODE_RINGTONE),
+ MAKE_STRING_FROM_ENUM(AUDIO_MODE_IN_CALL),
+ MAKE_STRING_FROM_ENUM(AUDIO_MODE_IN_COMMUNICATION),
+};
+
template <class Traits>
bool TypeConverter<Traits>::toString(const typename Traits::Type &value, std::string &str)
{
- for (size_t i = 0; i < mSize; i++) {
+ for (size_t i = 0; i < sizeof(mTable) / sizeof(mTable[0]); i++) {
if (mTable[i].value == value) {
str = mTable[i].literal;
return true;
}
}
+ char result[64];
+ snprintf(result, sizeof(result), "Unknown enum value %d", value);
+ str = result;
return false;
}
template <class Traits>
bool TypeConverter<Traits>::fromString(const std::string &str, typename Traits::Type &result)
{
- for (size_t i = 0; i < mSize; i++) {
+ for (size_t i = 0; i < sizeof(mTable) / sizeof(mTable[0]); i++) {
if (strcmp(mTable[i].literal, str.c_str()) == 0) {
ALOGV("stringToEnum() found %s", mTable[i].literal);
result = mTable[i].value;
@@ -288,6 +271,19 @@
return value;
}
+template <class Traits>
+void TypeConverter<Traits>::maskToString(uint32_t mask, std::string &str, const char *del)
+{
+ bool first_flag = true;
+ for (size_t i = 0; i < sizeof(mTable) / sizeof(mTable[0]); i++) {
+ if ((mask & mTable[i].value) == mTable[i].value) {
+ if (!first_flag) str += del;
+ first_flag = false;
+ str += mTable[i].literal;
+ }
+ }
+}
+
template class TypeConverter<DeviceTraits>;
template class TypeConverter<OutputFlagTraits>;
template class TypeConverter<InputFlagTraits>;
@@ -298,6 +294,7 @@
template class TypeConverter<GainModeTraits>;
template class TypeConverter<StreamTraits>;
template class TypeConverter<DeviceCategoryTraits>;
+template class TypeConverter<AudioModeTraits>;
}; // namespace android
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index a8bdf86..a5746cc 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -33,11 +33,11 @@
#include <AudioPolicyEngineInstance.h>
#include <cutils/properties.h>
#include <utils/Log.h>
-#include <hardware/audio.h>
#include <hardware/audio_effect.h>
#include <media/AudioParameter.h>
#include <media/AudioPolicyHelper.h>
#include <soundtrigger/SoundTrigger.h>
+#include <system/audio.h>
#include "AudioPolicyManager.h"
#ifndef USE_XML_AUDIO_POLICY_CONF
#include <ConfigParsingUtils.h>
@@ -448,15 +448,17 @@
// FIXME: would be better to refine to only inputs whose profile connects to the
// call TX device but this information is not in the audio patch and logic here must be
// symmetric to the one in startInput()
- audio_io_handle_t activeInput = mInputs.getActiveInput();
- if (activeInput != 0) {
- sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput);
- if (activeDesc->getModuleHandle() == txSourceDeviceDesc->getModuleHandle()) {
- //FIXME: consider all active sessions
- AudioSessionCollection activeSessions = activeDesc->getActiveAudioSessions();
- audio_session_t activeSession = activeSessions.keyAt(0);
- stopInput(activeInput, activeSession);
- releaseInput(activeInput, activeSession);
+ Vector<sp <AudioInputDescriptor> > activeInputs = mInputs.getActiveInputs();
+ for (size_t i = 0; i < activeInputs.size(); i++) {
+ sp<AudioInputDescriptor> activeDesc = activeInputs[i];
+ if (activeDesc->hasSameHwModuleAs(txSourceDeviceDesc)) {
+ AudioSessionCollection activeSessions =
+ activeDesc->getAudioSessions(true /*activeOnly*/);
+ for (size_t j = 0; j < activeSessions.size(); j++) {
+ audio_session_t activeSession = activeSessions.keyAt(j);
+ stopInput(activeDesc->mIoHandle, activeSession);
+ releaseInput(activeDesc->mIoHandle, activeSession);
+ }
}
}
@@ -627,15 +629,16 @@
}
}
- audio_io_handle_t activeInput = mInputs.getActiveInput();
- if (activeInput != 0) {
- sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput);
- audio_devices_t newDevice = getNewInputDevice(activeInput);
+ Vector<sp <AudioInputDescriptor> > activeInputs = mInputs.getActiveInputs();
+ for (size_t i = 0; i < activeInputs.size(); i++) {
+ sp<AudioInputDescriptor> activeDesc = activeInputs[i];
+ audio_devices_t newDevice = getNewInputDevice(activeDesc);
// Force new input selection if the new device can not be reached via current input
- if (activeDesc->mProfile->getSupportedDevices().types() & (newDevice & ~AUDIO_DEVICE_BIT_IN)) {
- setInputDevice(activeInput, newDevice);
+ if (activeDesc->mProfile->getSupportedDevices().types() &
+ (newDevice & ~AUDIO_DEVICE_BIT_IN)) {
+ setInputDevice(activeDesc->mIoHandle, newDevice);
} else {
- closeInput(activeInput);
+ closeInput(activeDesc->mIoHandle);
}
}
}
@@ -1421,6 +1424,7 @@
*input = AUDIO_IO_HANDLE_NONE;
*inputType = API_INPUT_INVALID;
+
audio_devices_t device;
// handle legacy remote submix case where the address was not always specified
String8 address = String8("");
@@ -1564,14 +1568,22 @@
isSoundTrigger,
policyMix, mpClientInterface);
-// TODO enable input reuse
-#if 0
+
// reuse an open input if possible
for (size_t i = 0; i < mInputs.size(); i++) {
sp<AudioInputDescriptor> desc = mInputs.valueAt(i);
- // reuse input if it shares the same profile and same sound trigger attribute
- if (profile == desc->mProfile &&
- isSoundTrigger == desc->isSoundTrigger()) {
+ // reuse input if:
+ // - it shares the same profile
+ // AND
+ // - it is not a reroute submix input
+ // AND
+ // - it is: not used for sound trigger
+ // OR
+ // used for sound trigger and all clients use the same session ID
+ //
+ if ((profile == desc->mProfile) &&
+ (isSoundTrigger == desc->isSoundTrigger()) &&
+ !is_virtual_input_device(device)) {
sp<AudioSession> as = desc->getAudioSession(session);
if (as != 0) {
@@ -1581,16 +1593,33 @@
} else {
ALOGW("getInputForDevice() record with different attributes"
" exists for session %d", session);
- return input;
+ break;
}
+ } else if (isSoundTrigger) {
+ break;
+ }
+ // force close input if current source is now the highest priority request on this input
+ // and current input properties are not exactly as requested.
+ if ((desc->mSamplingRate != samplingRate ||
+ desc->mChannelMask != channelMask ||
+ !audio_formats_match(desc->mFormat, format)) &&
+ (source_priority(desc->getHighestPrioritySource(false /*activeOnly*/)) <
+ source_priority(inputSource))) {
+ ALOGV("%s: ", __FUNCTION__);
+ AudioSessionCollection sessions = desc->getAudioSessions(false /*activeOnly*/);
+ for (size_t j = 0; j < sessions.size(); j++) {
+ audio_session_t currentSession = sessions.keyAt(j);
+ stopInput(desc->mIoHandle, currentSession);
+ releaseInput(desc->mIoHandle, currentSession);
+ }
+ break;
} else {
desc->addAudioSession(session, audioSession);
+ ALOGV("%s: reusing input %d", __FUNCTION__, mInputs.keyAt(i));
+ return mInputs.keyAt(i);
}
- ALOGV("getInputForDevice() reusing input %d", mInputs.keyAt(i));
- return mInputs.keyAt(i);
}
}
-#endif
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
config.sample_rate = profileSamplingRate;
@@ -1633,10 +1662,50 @@
return input;
}
+bool AudioPolicyManager::isConcurentCaptureAllowed(const sp<AudioInputDescriptor>& inputDesc,
+ const sp<AudioSession>& audioSession)
+{
+ // Do not allow capture if an active voice call is using a software patch and
+ // the call TX source device is on the same HW module.
+ // FIXME: would be better to refine to only inputs whose profile connects to the
+ // call TX device but this information is not in the audio patch
+ if (mCallTxPatch != 0 &&
+ inputDesc->getModuleHandle() == mCallTxPatch->mPatch.sources[0].ext.device.hw_module) {
+ return false;
+ }
+
+ // starting concurrent capture is enabled if:
+ // 1) capturing for re-routing
+ // 2) capturing for HOTWORD source
+ // 3) capturing for FM TUNER source
+ // 3) All other active captures are either for re-routing or HOTWORD
+
+ if (is_virtual_input_device(inputDesc->mDevice) ||
+ audioSession->inputSource() == AUDIO_SOURCE_HOTWORD ||
+ audioSession->inputSource() == AUDIO_SOURCE_FM_TUNER) {
+ return true;
+ }
+
+ Vector< sp<AudioInputDescriptor> > activeInputs = mInputs.getActiveInputs();
+ for (size_t i = 0; i < activeInputs.size(); i++) {
+ sp<AudioInputDescriptor> activeInput = activeInputs[i];
+ if ((activeInput->inputSource() != AUDIO_SOURCE_HOTWORD) &&
+ (activeInput->inputSource() != AUDIO_SOURCE_FM_TUNER) &&
+ !is_virtual_input_device(activeInput->mDevice)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
status_t AudioPolicyManager::startInput(audio_io_handle_t input,
- audio_session_t session)
+ audio_session_t session,
+ concurrency_type__mask_t *concurrency)
{
ALOGV("startInput() input %d", input);
+ *concurrency = API_INPUT_CONCURRENCY_NONE;
ssize_t index = mInputs.indexOfKey(input);
if (index < 0) {
ALOGW("startInput() unknown input %d", input);
@@ -1650,86 +1719,66 @@
return BAD_VALUE;
}
- // virtual input devices are compatible with other input devices
- if (!is_virtual_input_device(inputDesc->mDevice)) {
-
- // for a non-virtual input device, check if there is another (non-virtual) active input
- audio_io_handle_t activeInput = mInputs.getActiveInput();
- if (activeInput != 0 && activeInput != input) {
-
- // If the already active input uses AUDIO_SOURCE_HOTWORD then it is closed,
- // otherwise the active input continues and the new input cannot be started.
- sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput);
- if ((activeDesc->inputSource() == AUDIO_SOURCE_HOTWORD) &&
- !activeDesc->hasPreemptedSession(session)) {
- ALOGW("startInput(%d) preempting low-priority input %d", input, activeInput);
- //FIXME: consider all active sessions
- AudioSessionCollection activeSessions = activeDesc->getActiveAudioSessions();
- audio_session_t activeSession = activeSessions.keyAt(0);
- SortedVector<audio_session_t> sessions =
- activeDesc->getPreemptedSessions();
- sessions.add(activeSession);
- inputDesc->setPreemptedSessions(sessions);
- stopInput(activeInput, activeSession);
- releaseInput(activeInput, activeSession);
- } else {
- ALOGE("startInput(%d) failed: other input %d already started", input, activeInput);
- return INVALID_OPERATION;
- }
- }
-
- // Do not allow capture if an active voice call is using a software patch and
- // the call TX source device is on the same HW module.
- // FIXME: would be better to refine to only inputs whose profile connects to the
- // call TX device but this information is not in the audio patch
- if (mCallTxPatch != 0 &&
- inputDesc->getModuleHandle() == mCallTxPatch->mPatch.sources[0].ext.device.hw_module) {
- return INVALID_OPERATION;
- }
+ if (!isConcurentCaptureAllowed(inputDesc, audioSession)) {
+ ALOGW("startInput(%d) failed: other input already started", input);
+ return INVALID_OPERATION;
}
+ if (isInCall()) {
+ *concurrency |= API_INPUT_CONCURRENCY_CALL;
+ }
+ if (mInputs.activeInputsCountOnDevices() != 0) {
+ *concurrency |= API_INPUT_CONCURRENCY_CAPTURE;
+ }
+
+ // increment activity count before calling getNewInputDevice() below as only active sessions
+ // are considered for device selection
+ audioSession->changeActiveCount(1);
+
// Routing?
mInputRoutes.incRouteActivity(session);
- if (!inputDesc->isActive() || mInputRoutes.hasRouteChanged(session)) {
- // if input maps to a dynamic policy with an activity listener, notify of state change
- if ((inputDesc->mPolicyMix != NULL)
- && ((inputDesc->mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
- mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mDeviceAddress,
- MIX_STATE_MIXING);
- }
-
+ if (audioSession->activeCount() == 1 || mInputRoutes.hasRouteChanged(session)) {
// indicate active capture to sound trigger service if starting capture from a mic on
// primary HW module
- audio_devices_t device = getNewInputDevice(input);
- audio_devices_t primaryInputDevices = availablePrimaryInputDevices();
- if (((device & primaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
- mInputs.activeInputsCountOnDevices(primaryInputDevices) == 0) {
- SoundTrigger::setCaptureState(true);
- }
+ audio_devices_t device = getNewInputDevice(inputDesc);
setInputDevice(input, device, true /* force */);
- // automatically enable the remote submix output when input is started if not
- // used by a policy mix of type MIX_TYPE_RECORDERS
- // For remote submix (a virtual device), we open only one input per capture request.
- if (audio_is_remote_submix_device(inputDesc->mDevice)) {
- String8 address = String8("");
- if (inputDesc->mPolicyMix == NULL) {
- address = String8("0");
- } else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) {
- address = inputDesc->mPolicyMix->mDeviceAddress;
+ if (inputDesc->getAudioSessionCount(true/*activeOnly*/) == 1) {
+ // if input maps to a dynamic policy with an activity listener, notify of state change
+ if ((inputDesc->mPolicyMix != NULL)
+ && ((inputDesc->mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
+ mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mDeviceAddress,
+ MIX_STATE_MIXING);
}
- if (address != "") {
- setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- address, "remote-submix");
+
+ audio_devices_t primaryInputDevices = availablePrimaryInputDevices();
+ if (((device & primaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
+ mInputs.activeInputsCountOnDevices(primaryInputDevices) == 0) {
+ SoundTrigger::setCaptureState(true);
+ }
+
+ // automatically enable the remote submix output when input is started if not
+ // used by a policy mix of type MIX_TYPE_RECORDERS
+ // For remote submix (a virtual device), we open only one input per capture request.
+ if (audio_is_remote_submix_device(inputDesc->mDevice)) {
+ String8 address = String8("");
+ if (inputDesc->mPolicyMix == NULL) {
+ address = String8("0");
+ } else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) {
+ address = inputDesc->mPolicyMix->mDeviceAddress;
+ }
+ if (address != "") {
+ setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ address, "remote-submix");
+ }
}
}
}
ALOGV("AudioPolicyManager::startInput() input source = %d", audioSession->inputSource());
- audioSession->changeActiveCount(1);
return NO_ERROR;
}
@@ -1760,41 +1809,46 @@
// Routing?
mInputRoutes.decRouteActivity(session);
- if (!inputDesc->isActive()) {
- // if input maps to a dynamic policy with an activity listener, notify of state change
- if ((inputDesc->mPolicyMix != NULL)
- && ((inputDesc->mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
- mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mDeviceAddress,
- MIX_STATE_IDLE);
- }
+ if (audioSession->activeCount() == 0) {
- // automatically disable the remote submix output when input is stopped if not
- // used by a policy mix of type MIX_TYPE_RECORDERS
- if (audio_is_remote_submix_device(inputDesc->mDevice)) {
- String8 address = String8("");
- if (inputDesc->mPolicyMix == NULL) {
- address = String8("0");
- } else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) {
- address = inputDesc->mPolicyMix->mDeviceAddress;
+ if (inputDesc->isActive()) {
+ setInputDevice(input, getNewInputDevice(inputDesc), false /* force */);
+ } else {
+ // if input maps to a dynamic policy with an activity listener, notify of state change
+ if ((inputDesc->mPolicyMix != NULL)
+ && ((inputDesc->mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
+ mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mDeviceAddress,
+ MIX_STATE_IDLE);
}
- if (address != "") {
- setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- address, "remote-submix");
+
+ // automatically disable the remote submix output when input is stopped if not
+ // used by a policy mix of type MIX_TYPE_RECORDERS
+ if (audio_is_remote_submix_device(inputDesc->mDevice)) {
+ String8 address = String8("");
+ if (inputDesc->mPolicyMix == NULL) {
+ address = String8("0");
+ } else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) {
+ address = inputDesc->mPolicyMix->mDeviceAddress;
+ }
+ if (address != "") {
+ setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ address, "remote-submix");
+ }
}
- }
- audio_devices_t device = inputDesc->mDevice;
- resetInputDevice(input);
+ audio_devices_t device = inputDesc->mDevice;
+ resetInputDevice(input);
- // indicate inactive capture to sound trigger service if stopping capture from a mic on
- // primary HW module
- audio_devices_t primaryInputDevices = availablePrimaryInputDevices();
- if (((device & primaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
- mInputs.activeInputsCountOnDevices(primaryInputDevices) == 0) {
- SoundTrigger::setCaptureState(false);
+ // indicate inactive capture to sound trigger service if stopping capture from a mic on
+ // primary HW module
+ audio_devices_t primaryInputDevices = availablePrimaryInputDevices();
+ if (((device & primaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
+ mInputs.activeInputsCountOnDevices(primaryInputDevices) == 0) {
+ SoundTrigger::setCaptureState(false);
+ }
+ inputDesc->clearPreemptedSessions();
}
- inputDesc->clearPreemptedSessions();
}
return NO_ERROR;
}
@@ -2276,7 +2330,9 @@
snprintf(buffer, SIZE, " Primary Output: %d\n",
hasPrimaryOutput() ? mPrimaryOutput->mIoHandle : AUDIO_IO_HANDLE_NONE);
result.append(buffer);
- snprintf(buffer, SIZE, " Phone state: %d\n", mEngine->getPhoneState());
+ std::string stateLiteral;
+ AudioModeConverter::toString(mEngine->getPhoneState(), stateLiteral);
+ snprintf(buffer, SIZE, " Phone state: %s\n", stateLiteral.c_str());
result.append(buffer);
snprintf(buffer, SIZE, " Force use for communications %d\n",
mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION));
@@ -2665,7 +2721,7 @@
// create a software bridge in PatchPanel if:
// - source and sink devices are on differnt HW modules OR
// - audio HAL version is < 3.0
- if ((srcDeviceDesc->getModuleHandle() != sinkDeviceDesc->getModuleHandle()) ||
+ if (!srcDeviceDesc->hasSameHwModuleAs(sinkDeviceDesc) ||
(srcDeviceDesc->mModule->getHalVersion() < AUDIO_DEVICE_API_VERSION_3_0)) {
// support only one sink device for now to simplify output selection logic
if (patch->num_sinks > 1) {
@@ -2765,7 +2821,7 @@
return BAD_VALUE;
}
setInputDevice(inputDesc->mIoHandle,
- getNewInputDevice(inputDesc->mIoHandle),
+ getNewInputDevice(inputDesc),
true,
NULL);
} else if (patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE) {
@@ -4173,7 +4229,7 @@
ALOGVV("getOutputsForDevice() device %04x", device);
for (size_t i = 0; i < openOutputs.size(); i++) {
- ALOGVV("output %d isDuplicated=%d device=%04x",
+ ALOGVV("output %zu isDuplicated=%d device=%04x",
i, openOutputs.valueAt(i)->isDuplicated(),
openOutputs.valueAt(i)->supportedDevices());
if ((device & openOutputs.valueAt(i)->supportedDevices()) == device) {
@@ -4295,33 +4351,36 @@
((mAvailableInputDevices.types() & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET &
~AUDIO_DEVICE_BIT_IN) != 0) ||
((mAvailableOutputDevices.types() & AUDIO_DEVICE_OUT_ALL_SCO) != 0);
- // suspend A2DP output if:
- // (NOT already suspended) &&
- // ((SCO device is connected &&
- // (forced usage for communication || for record is SCO))) ||
- // (phone state is ringing || in call)
+
+ // if suspended, restore A2DP output if:
+ // ((SCO device is NOT connected) ||
+ // ((forced usage communication is NOT SCO) && (forced usage for record is NOT SCO) &&
+ // (phone state is NOT in call) && (phone state is NOT ringing)))
//
- // restore A2DP output if:
- // (Already suspended) &&
- // ((SCO device is NOT connected ||
- // (forced usage NOT for communication && NOT for record is SCO))) &&
- // (phone state is NOT ringing && NOT in call)
+ // if not suspended, suspend A2DP output if:
+ // (SCO device is connected) &&
+ // ((forced usage for communication is SCO) || (forced usage for record is SCO) ||
+ // ((phone state is in call) || (phone state is ringing)))
//
if (mA2dpSuspended) {
- if ((!isScoConnected ||
- ((mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) != AUDIO_POLICY_FORCE_BT_SCO) &&
- (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) != AUDIO_POLICY_FORCE_BT_SCO))) &&
- ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) &&
+ if (!isScoConnected ||
+ ((mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) !=
+ AUDIO_POLICY_FORCE_BT_SCO) &&
+ (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) !=
+ AUDIO_POLICY_FORCE_BT_SCO) &&
+ (mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) &&
(mEngine->getPhoneState() != AUDIO_MODE_RINGTONE))) {
mpClientInterface->restoreOutput(a2dpOutput);
mA2dpSuspended = false;
}
} else {
- if ((isScoConnected &&
- ((mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) == AUDIO_POLICY_FORCE_BT_SCO) ||
- (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO))) ||
- ((mEngine->getPhoneState() == AUDIO_MODE_IN_CALL) ||
+ if (isScoConnected &&
+ ((mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) ==
+ AUDIO_POLICY_FORCE_BT_SCO) ||
+ (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) ==
+ AUDIO_POLICY_FORCE_BT_SCO) ||
+ (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL) ||
(mEngine->getPhoneState() == AUDIO_MODE_RINGTONE))) {
mpClientInterface->suspendOutput(a2dpOutput);
@@ -4392,9 +4451,9 @@
return device;
}
-audio_devices_t AudioPolicyManager::getNewInputDevice(audio_io_handle_t input)
+audio_devices_t AudioPolicyManager::getNewInputDevice(const sp<AudioInputDescriptor>& inputDesc)
{
- sp<AudioInputDescriptor> inputDesc = mInputs.valueFor(input);
+ audio_devices_t device = AUDIO_DEVICE_NONE;
ssize_t index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
if (index >= 0) {
@@ -4406,7 +4465,12 @@
}
}
- audio_devices_t device = getDeviceAndMixForInputSource(inputDesc->inputSource());
+ audio_source_t source = inputDesc->getHighestPrioritySource(true /*activeOnly*/);
+ if (isInCall()) {
+ device = getDeviceAndMixForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
+ } else if (source != AUDIO_SOURCE_DEFAULT) {
+ device = getDeviceAndMixForInputSource(source);
+ }
return device;
}
@@ -4614,7 +4678,7 @@
== AUDIO_DEVICE_NONE) {
continue;
}
- ALOGVV("checkDeviceMuteStrategies() %s strategy %d (curDevice %04x)",
+ ALOGVV("checkDeviceMuteStrategies() %s strategy %zu (curDevice %04x)",
mute ? "muting" : "unmuting", i, curDevice);
setStrategyMute((routing_strategy)i, mute, desc, mute ? 0 : delayMs);
if (isStrategyActive(desc, (routing_strategy)i)) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 5c2b673..44e9baf 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -139,7 +139,8 @@
// indicates to the audio policy manager that the input starts being used.
virtual status_t startInput(audio_io_handle_t input,
- audio_session_t session);
+ audio_session_t session,
+ concurrency_type__mask_t *concurrency);
// indicates to the audio policy manager that the input stops being used.
virtual status_t stopInput(audio_io_handle_t input,
@@ -405,7 +406,7 @@
void updateDevicesAndOutputs();
// selects the most appropriate device on input for current state
- audio_devices_t getNewInputDevice(audio_io_handle_t input);
+ audio_devices_t getNewInputDevice(const sp<AudioInputDescriptor>& inputDesc);
virtual uint32_t getMaxEffectsCpuLoad()
{
@@ -506,6 +507,8 @@
void clearAudioSources(uid_t uid);
+ bool isConcurentCaptureAllowed(const sp<AudioInputDescriptor>& inputDesc,
+ const sp<AudioSession>& audioSession);
static bool streamsMatchForvolume(audio_stream_type_t stream1,
audio_stream_type_t stream2);
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index b732b20..9a28137 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -57,11 +57,11 @@
}
mInputSources.clear();
- for (i = 0; i < mInputs.size(); i++) {
- mInputs.valueAt(i)->mEffects.clear();
- delete mInputs.valueAt(i);
+ for (i = 0; i < mInputSessions.size(); i++) {
+ mInputSessions.valueAt(i)->mEffects.clear();
+ delete mInputSessions.valueAt(i);
}
- mInputs.clear();
+ mInputSessions.clear();
// release audio output processing resources
for (i = 0; i < mOutputStreams.size(); i++) {
@@ -93,19 +93,19 @@
ALOGV("addInputEffects(): no processing needs to be attached to this source");
return status;
}
- ssize_t idx = mInputs.indexOfKey(input);
- EffectVector *inputDesc;
+ ssize_t idx = mInputSessions.indexOfKey(audioSession);
+ EffectVector *sessionDesc;
if (idx < 0) {
- inputDesc = new EffectVector(audioSession);
- mInputs.add(input, inputDesc);
+ sessionDesc = new EffectVector(audioSession);
+ mInputSessions.add(audioSession, sessionDesc);
} else {
// EffectVector is existing and we just need to increase ref count
- inputDesc = mInputs.valueAt(idx);
+ sessionDesc = mInputSessions.valueAt(idx);
}
- inputDesc->mRefCount++;
+ sessionDesc->mRefCount++;
- ALOGV("addInputEffects(): input: %d, refCount: %d", input, inputDesc->mRefCount);
- if (inputDesc->mRefCount == 1) {
+ ALOGV("addInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
+ if (sessionDesc->mRefCount == 1) {
Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
for (size_t i = 0; i < effects.size(); i++) {
EffectDesc *effect = effects[i];
@@ -123,30 +123,31 @@
}
ALOGV("addInputEffects(): added Fx %s on source: %d",
effect->mName, (int32_t)aliasSource);
- inputDesc->mEffects.add(fx);
+ sessionDesc->mEffects.add(fx);
}
- inputDesc->setProcessorEnabled(true);
+ sessionDesc->setProcessorEnabled(true);
}
return status;
}
-status_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input)
+status_t AudioPolicyEffects::releaseInputEffects(audio_io_handle_t input,
+ audio_session_t audioSession)
{
status_t status = NO_ERROR;
Mutex::Autolock _l(mLock);
- ssize_t index = mInputs.indexOfKey(input);
+ ssize_t index = mInputSessions.indexOfKey(audioSession);
if (index < 0) {
return status;
}
- EffectVector *inputDesc = mInputs.valueAt(index);
- inputDesc->mRefCount--;
- ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, inputDesc->mRefCount);
- if (inputDesc->mRefCount == 0) {
- inputDesc->setProcessorEnabled(false);
- delete inputDesc;
- mInputs.removeItemsAt(index);
+ EffectVector *sessionDesc = mInputSessions.valueAt(index);
+ sessionDesc->mRefCount--;
+ ALOGV("releaseInputEffects(): input: %d, refCount: %d", input, sessionDesc->mRefCount);
+ if (sessionDesc->mRefCount == 0) {
+ sessionDesc->setProcessorEnabled(false);
+ delete sessionDesc;
+ mInputSessions.removeItemsAt(index);
ALOGV("releaseInputEffects(): all effects released");
}
return status;
@@ -160,16 +161,16 @@
Mutex::Autolock _l(mLock);
size_t index;
- for (index = 0; index < mInputs.size(); index++) {
- if (mInputs.valueAt(index)->mSessionId == audioSession) {
+ for (index = 0; index < mInputSessions.size(); index++) {
+ if (mInputSessions.valueAt(index)->mSessionId == audioSession) {
break;
}
}
- if (index == mInputs.size()) {
+ if (index == mInputSessions.size()) {
*count = 0;
return BAD_VALUE;
}
- Vector< sp<AudioEffect> > effects = mInputs.valueAt(index)->mEffects;
+ Vector< sp<AudioEffect> > effects = mInputSessions.valueAt(index)->mEffects;
for (size_t i = 0; i < effects.size(); i++) {
effect_descriptor_t desc = effects[i]->descriptor();
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index afdaf98..9428409 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -62,7 +62,8 @@
audio_session_t audioSession);
// Add all input effects associated to this input
- status_t releaseInputEffects(audio_io_handle_t input);
+ status_t releaseInputEffects(audio_io_handle_t input,
+ audio_session_t audioSession);
// Return a list of effect descriptors for default output effects
@@ -178,12 +179,12 @@
size_t *curSize,
size_t *totSize);
- // protects access to mInputSources, mInputs, mOutputStreams, mOutputSessions
+ // protects access to mInputSources, mInputSessions, mOutputStreams, mOutputSessions
Mutex mLock;
// Automatic input effects are configured per audio_source_t
KeyedVector< audio_source_t, EffectDescVector* > mInputSources;
// Automatic input effects are unique for audio_io_handle_t
- KeyedVector< audio_io_handle_t, EffectVector* > mInputs;
+ KeyedVector< audio_session_t, EffectVector* > mInputSessions;
// Automatic output effects are organized per audio_stream_type_t
KeyedVector< audio_stream_type_t, EffectDescVector* > mOutputStreams;
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 451ce84..f6da920 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -361,8 +361,23 @@
return NO_INIT;
}
Mutex::Autolock _l(mLock);
+ AudioPolicyInterface::concurrency_type__mask_t concurrency;
+ status_t status = mAudioPolicyManager->startInput(input, session, &concurrency);
- return mAudioPolicyManager->startInput(input, session);
+ if (status == NO_ERROR) {
+ LOG_ALWAYS_FATAL_IF(concurrency & ~AudioPolicyInterface::API_INPUT_CONCURRENCY_ALL,
+ "startInput(): invalid concurrency type %d", (int)concurrency);
+
+ // enforce permission (if any) required for each type of concurrency
+ if (concurrency & AudioPolicyInterface::API_INPUT_CONCURRENCY_CALL) {
+ //TODO: check incall capture permission
+ }
+ if (concurrency & AudioPolicyInterface::API_INPUT_CONCURRENCY_CAPTURE) {
+ //TODO: check concurrent capture permission
+ }
+ }
+
+ return status;
}
status_t AudioPolicyService::stopInput(audio_io_handle_t input,
@@ -390,7 +405,7 @@
}
if (audioPolicyEffects != 0) {
// release audio processors from the input
- status_t status = audioPolicyEffects->releaseInputEffects(input);
+ status_t status = audioPolicyEffects->releaseInputEffects(input, session);
if(status != NO_ERROR) {
ALOGW("Failed to release effects on input %d", input);
}
@@ -566,7 +581,8 @@
*count = 0;
return NO_INIT;
}
- return audioPolicyEffects->queryDefaultInputEffects(audioSession, descriptors, count);
+ return audioPolicyEffects->queryDefaultInputEffects(
+ (audio_session_t)audioSession, descriptors, count);
}
bool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info)
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp
index 946c380..517fba1 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp
@@ -307,7 +307,7 @@
}
void AudioPolicyService::releaseInput(audio_io_handle_t input,
- audio_session_t session __unused)
+ audio_session_t session)
{
if (mpAudioPolicy == NULL) {
return;
@@ -321,7 +321,7 @@
}
if (audioPolicyEffects != 0) {
// release audio processors from the input
- status_t status = audioPolicyEffects->releaseInputEffects(input);
+ status_t status = audioPolicyEffects->releaseInputEffects(input, session);
if(status != NO_ERROR) {
ALOGW("Failed to release effects on input %d", input);
}
diff --git a/services/mediadrm/tests/Android.mk b/services/mediadrm/tests/Android.mk
index 8cbf782..e2f7399 100644
--- a/services/mediadrm/tests/Android.mk
+++ b/services/mediadrm/tests/Android.mk
@@ -19,7 +19,6 @@
frameworks/av/media/libmediaplayerservice \
LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
LOCAL_32_BIT_ONLY := true
diff --git a/services/mediaextractor/Android.mk b/services/mediaextractor/Android.mk
index a9a2d3c..4e337a0 100644
--- a/services/mediaextractor/Android.mk
+++ b/services/mediaextractor/Android.mk
@@ -5,19 +5,20 @@
LOCAL_SRC_FILES := MediaExtractorService.cpp
LOCAL_SHARED_LIBRARIES := libmedia libstagefright libbinder libutils liblog
LOCAL_MODULE:= libmediaextractorservice
-LOCAL_32_BIT_ONLY := true
include $(BUILD_SHARED_LIBRARY)
# service executable
include $(CLEAR_VARS)
+# seccomp filters are defined for the following architectures:
LOCAL_REQUIRED_MODULES_arm := mediaextractor-seccomp.policy
+LOCAL_REQUIRED_MODULES_arm64 := mediaextractor-seccomp.policy
LOCAL_REQUIRED_MODULES_x86 := mediaextractor-seccomp.policy
+# TODO add seccomp filter for x86_64.
LOCAL_SRC_FILES := main_extractorservice.cpp minijail/minijail.cpp
LOCAL_SHARED_LIBRARIES := libmedia libmediaextractorservice libbinder libutils liblog libicuuc libminijail
LOCAL_STATIC_LIBRARIES := libicuandroid_utils
LOCAL_MODULE:= mediaextractor
-LOCAL_32_BIT_ONLY := true
LOCAL_INIT_RC := mediaextractor.rc
LOCAL_C_INCLUDES := frameworks/av/media/libmedia
include $(BUILD_EXECUTABLE)
diff --git a/services/mediaextractor/minijail/Android.mk b/services/mediaextractor/minijail/Android.mk
index 79c5505..3a93340 100644
--- a/services/mediaextractor/minijail/Android.mk
+++ b/services/mediaextractor/minijail/Android.mk
@@ -1,18 +1,12 @@
LOCAL_PATH := $(call my-dir)
-ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), arm arm64 x86 x86_64))
+# TODO add filter for x86_64
+ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), arm arm64 x86))
include $(CLEAR_VARS)
LOCAL_MODULE := mediaextractor-seccomp.policy
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/seccomp_policy
-
-# mediaextractor runs in 32-bit combatibility mode. For 64 bit architectures,
-# use the 32 bit policy
-ifdef TARGET_2ND_ARCH
- LOCAL_SRC_FILES := $(LOCAL_PATH)/seccomp_policy/mediaextractor-seccomp-$(TARGET_2ND_ARCH).policy
-else
- LOCAL_SRC_FILES := $(LOCAL_PATH)/seccomp_policy/mediaextractor-seccomp-$(TARGET_ARCH).policy
-endif
+LOCAL_SRC_FILES := $(LOCAL_PATH)/seccomp_policy/mediaextractor-seccomp-$(TARGET_ARCH).policy
# allow device specific additions to the syscall whitelist
ifneq (,$(wildcard $(BOARD_SECCOMP_POLICY)/mediaextractor-seccomp.policy))
diff --git a/services/mediaextractor/minijail/seccomp_policy/mediaextractor-seccomp-arm64.policy b/services/mediaextractor/minijail/seccomp_policy/mediaextractor-seccomp-arm64.policy
new file mode 100644
index 0000000..ae6ac05
--- /dev/null
+++ b/services/mediaextractor/minijail/seccomp_policy/mediaextractor-seccomp-arm64.policy
@@ -0,0 +1,36 @@
+# Organized by frequency of systemcall - in descending order for
+# best performance.
+ioctl: 1
+futex: 1
+prctl: 1
+write: 1
+getpriority: 1
+close: 1
+dup: 1
+mmap: 1
+munmap: 1
+openat: 1
+mprotect: 1
+madvise: 1
+getuid: 1
+fstat: 1
+read: 1
+setpriority: 1
+sigaltstack: 1
+clone: 1
+lseek: 1
+newfstatat: 1
+faccessat: 1
+restart_syscall: 1
+exit: 1
+exit_group: 1
+rt_sigreturn: 1
+getrlimit: 1
+
+# for attaching to debuggerd on process crash
+rt_sigaction: 1
+# socket: arg0 == AF_LOCAL
+socket: arg0 == 1
+connect: 1
+rt_tgsigqueueinfo: 1
+writev: 1
diff --git a/services/mediaresourcemanager/Android.mk b/services/mediaresourcemanager/Android.mk
index b72230f..e9bc955 100644
--- a/services/mediaresourcemanager/Android.mk
+++ b/services/mediaresourcemanager/Android.mk
@@ -14,7 +14,6 @@
$(TOPDIR)frameworks/av/include
LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
include $(BUILD_SHARED_LIBRARY)
diff --git a/services/mediaresourcemanager/test/Android.mk b/services/mediaresourcemanager/test/Android.mk
index 3b4ef0d..6abcf92 100644
--- a/services/mediaresourcemanager/test/Android.mk
+++ b/services/mediaresourcemanager/test/Android.mk
@@ -21,7 +21,6 @@
frameworks/av/services/mediaresourcemanager \
LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
LOCAL_32_BIT_ONLY := true
@@ -47,7 +46,6 @@
frameworks/av/services/mediaresourcemanager \
LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
LOCAL_32_BIT_ONLY := true