diff options
120 files changed, 4591 insertions, 1335 deletions
diff --git a/camera/Camera.cpp b/camera/Camera.cpp index ee458f1..d43cb0b 100644 --- a/camera/Camera.cpp +++ b/camera/Camera.cpp @@ -27,7 +27,8 @@ #include <camera/ICameraRecordingProxyListener.h> #include <camera/ICameraService.h> -#include <surfaceflinger/Surface.h> +#include <gui/ISurfaceTexture.h> +#include <gui/Surface.h> namespace android { diff --git a/camera/ICamera.cpp b/camera/ICamera.cpp index 70f5dbc..8d8408c 100644 --- a/camera/ICamera.cpp +++ b/camera/ICamera.cpp @@ -22,6 +22,8 @@ #include <sys/types.h> #include <binder/Parcel.h> #include <camera/ICamera.h> +#include <gui/ISurfaceTexture.h> +#include <gui/Surface.h> namespace android { diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk index 11e94e8..f26747b 100644 --- a/cmds/stagefright/Android.mk +++ b/cmds/stagefright/Android.mk @@ -147,4 +147,28 @@ LOCAL_MODULE:= sf2 include $(BUILD_EXECUTABLE) +################################################################################ + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + codec.cpp \ + SimplePlayer.cpp \ + +LOCAL_SHARED_LIBRARIES := \ + libstagefright liblog libutils libbinder libstagefright_foundation \ + libmedia libgui libcutils libui + +LOCAL_C_INCLUDES:= \ + $(JNI_H_INCLUDE) \ + frameworks/base/media/libstagefright \ + $(TOP)/frameworks/base/include/media/stagefright/openmax + +LOCAL_CFLAGS += -Wno-multichar + +LOCAL_MODULE_TAGS := debug + +LOCAL_MODULE:= codec + +include $(BUILD_EXECUTABLE) diff --git a/cmds/stagefright/SimplePlayer.cpp b/cmds/stagefright/SimplePlayer.cpp new file mode 100644 index 0000000..f269e80 --- /dev/null +++ b/cmds/stagefright/SimplePlayer.cpp @@ -0,0 +1,646 @@ +/* + * Copyright (C) 2012 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 "SimplePlayer" +#include <utils/Log.h> + +#include "SimplePlayer.h" + +#include <gui/SurfaceTextureClient.h> +#include <media/AudioTrack.h> +#include <media/stagefright/foundation/ABuffer.h> +#include <media/stagefright/foundation/ADebug.h> +#include <media/stagefright/foundation/AMessage.h> +#include <media/stagefright/MediaCodec.h> +#include <media/stagefright/MediaErrors.h> +#include <media/stagefright/NativeWindowWrapper.h> +#include <media/stagefright/NuMediaExtractor.h> + +namespace android { + +SimplePlayer::SimplePlayer() + : mState(UNINITIALIZED), + mDoMoreStuffGeneration(0), + mStartTimeRealUs(-1ll) { +} + +SimplePlayer::~SimplePlayer() { +} + +// static +status_t PostAndAwaitResponse( + const sp<AMessage> &msg, sp<AMessage> *response) { + status_t err = msg->postAndAwaitResponse(response); + + if (err != OK) { + return err; + } + + if (!(*response)->findInt32("err", &err)) { + err = OK; + } + + return err; +} +status_t SimplePlayer::setDataSource(const char *path) { + sp<AMessage> msg = new AMessage(kWhatSetDataSource, id()); + msg->setString("path", path); + sp<AMessage> response; + return PostAndAwaitResponse(msg, &response); +} + +status_t SimplePlayer::setSurface(const sp<ISurfaceTexture> &surfaceTexture) { + sp<AMessage> msg = new AMessage(kWhatSetSurface, id()); + + sp<SurfaceTextureClient> surfaceTextureClient; + if (surfaceTexture != NULL) { + surfaceTextureClient = new SurfaceTextureClient(surfaceTexture); + } + + msg->setObject( + "native-window", new NativeWindowWrapper(surfaceTextureClient)); + + sp<AMessage> response; + return PostAndAwaitResponse(msg, &response); +} + +status_t SimplePlayer::prepare() { + sp<AMessage> msg = new AMessage(kWhatPrepare, id()); + sp<AMessage> response; + return PostAndAwaitResponse(msg, &response); +} + +status_t SimplePlayer::start() { + sp<AMessage> msg = new AMessage(kWhatStart, id()); + sp<AMessage> response; + return PostAndAwaitResponse(msg, &response); +} + +status_t SimplePlayer::stop() { + sp<AMessage> msg = new AMessage(kWhatStop, id()); + sp<AMessage> response; + return PostAndAwaitResponse(msg, &response); +} + +status_t SimplePlayer::reset() { + sp<AMessage> msg = new AMessage(kWhatReset, id()); + sp<AMessage> response; + return PostAndAwaitResponse(msg, &response); +} + +void SimplePlayer::onMessageReceived(const sp<AMessage> &msg) { + switch (msg->what()) { + case kWhatSetDataSource: + { + status_t err; + if (mState != UNINITIALIZED) { + err = INVALID_OPERATION; + } else { + CHECK(msg->findString("path", &mPath)); + mState = UNPREPARED; + } + + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + sp<AMessage> response = new AMessage; + response->setInt32("err", err); + response->postReply(replyID); + break; + } + + case kWhatSetSurface: + { + status_t err; + if (mState != UNPREPARED) { + err = INVALID_OPERATION; + } else { + sp<RefBase> obj; + CHECK(msg->findObject("native-window", &obj)); + + mNativeWindow = static_cast<NativeWindowWrapper *>(obj.get()); + + err = OK; + } + + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + sp<AMessage> response = new AMessage; + response->setInt32("err", err); + response->postReply(replyID); + break; + } + + case kWhatPrepare: + { + status_t err; + if (mState != UNPREPARED) { + err = INVALID_OPERATION; + } else { + err = onPrepare(); + + if (err == OK) { + mState = STOPPED; + } + } + + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + sp<AMessage> response = new AMessage; + response->setInt32("err", err); + response->postReply(replyID); + break; + } + + case kWhatStart: + { + status_t err = OK; + + if (mState == UNPREPARED) { + err = onPrepare(); + + if (err == OK) { + mState = STOPPED; + } + } + + if (err == OK) { + if (mState != STOPPED) { + err = INVALID_OPERATION; + } else { + err = onStart(); + + if (err == OK) { + mState = STARTED; + } + } + } + + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + sp<AMessage> response = new AMessage; + response->setInt32("err", err); + response->postReply(replyID); + break; + } + + case kWhatStop: + { + status_t err; + + if (mState != STARTED) { + err = INVALID_OPERATION; + } else { + err = onStop(); + + if (err == OK) { + mState = STOPPED; + } + } + + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + sp<AMessage> response = new AMessage; + response->setInt32("err", err); + response->postReply(replyID); + break; + } + + case kWhatReset: + { + status_t err = OK; + + if (mState == STARTED) { + CHECK_EQ(onStop(), (status_t)OK); + mState = STOPPED; + } + + if (mState == STOPPED) { + err = onReset(); + mState = UNINITIALIZED; + } + + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + sp<AMessage> response = new AMessage; + response->setInt32("err", err); + response->postReply(replyID); + break; + } + + case kWhatDoMoreStuff: + { + int32_t generation; + CHECK(msg->findInt32("generation", &generation)); + + if (generation != mDoMoreStuffGeneration) { + break; + } + + status_t err = onDoMoreStuff(); + + if (err == OK) { + msg->post(10000ll); + } + break; + } + + default: + TRESPASS(); + } +} + +status_t SimplePlayer::onPrepare() { + CHECK_EQ(mState, UNPREPARED); + + mExtractor = new NuMediaExtractor; + + status_t err = mExtractor->setDataSource(mPath.c_str()); + + if (err != OK) { + mExtractor.clear(); + return err; + } + + if (mCodecLooper == NULL) { + mCodecLooper = new ALooper; + mCodecLooper->start(); + } + + bool haveAudio = false; + bool haveVideo = false; + for (size_t i = 0; i < mExtractor->countTracks(); ++i) { + sp<AMessage> format; + status_t err = mExtractor->getTrackFormat(i, &format); + CHECK_EQ(err, (status_t)OK); + + AString mime; + CHECK(format->findString("mime", &mime)); + + if (!haveAudio && !strncasecmp(mime.c_str(), "audio/", 6)) { + haveAudio = true; + } else if (!haveVideo && !strncasecmp(mime.c_str(), "video/", 6)) { + haveVideo = true; + } else { + continue; + } + + err = mExtractor->selectTrack(i); + CHECK_EQ(err, (status_t)OK); + + CodecState *state = + &mStateByTrackIndex.editValueAt( + mStateByTrackIndex.add(i, CodecState())); + + state->mNumFramesWritten = 0; + state->mCodec = MediaCodec::CreateByType( + mCodecLooper, mime.c_str(), false /* encoder */); + + CHECK(state->mCodec != NULL); + + err = state->mCodec->configure( + format, mNativeWindow->getSurfaceTextureClient(), + 0 /* flags */); + + CHECK_EQ(err, (status_t)OK); + + size_t j = 0; + sp<ABuffer> buffer; + while (format->findBuffer(StringPrintf("csd-%d", j).c_str(), &buffer)) { + state->mCSD.push_back(buffer); + + ++j; + } + } + + for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) { + CodecState *state = &mStateByTrackIndex.editValueAt(i); + + status_t err = state->mCodec->start(); + CHECK_EQ(err, (status_t)OK); + + err = state->mCodec->getInputBuffers(&state->mBuffers[0]); + CHECK_EQ(err, (status_t)OK); + + err = state->mCodec->getOutputBuffers(&state->mBuffers[1]); + CHECK_EQ(err, (status_t)OK); + + for (size_t j = 0; j < state->mCSD.size(); ++j) { + const sp<ABuffer> &srcBuffer = state->mCSD.itemAt(j); + + size_t index; + err = state->mCodec->dequeueInputBuffer(&index, -1ll); + CHECK_EQ(err, (status_t)OK); + + const sp<ABuffer> &dstBuffer = state->mBuffers[0].itemAt(index); + + CHECK_LE(srcBuffer->size(), dstBuffer->capacity()); + dstBuffer->setRange(0, srcBuffer->size()); + memcpy(dstBuffer->data(), srcBuffer->data(), srcBuffer->size()); + + err = state->mCodec->queueInputBuffer( + index, + 0, + dstBuffer->size(), + 0ll, + MediaCodec::BUFFER_FLAG_CODECCONFIG); + CHECK_EQ(err, (status_t)OK); + } + } + + return OK; +} + +status_t SimplePlayer::onStart() { + CHECK_EQ(mState, STOPPED); + + mStartTimeRealUs = -1ll; + + sp<AMessage> msg = new AMessage(kWhatDoMoreStuff, id()); + msg->setInt32("generation", ++mDoMoreStuffGeneration); + msg->post(); + + return OK; +} + +status_t SimplePlayer::onStop() { + CHECK_EQ(mState, STARTED); + + ++mDoMoreStuffGeneration; + + return OK; +} + +status_t SimplePlayer::onReset() { + CHECK_EQ(mState, STOPPED); + + for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) { + CodecState *state = &mStateByTrackIndex.editValueAt(i); + + CHECK_EQ(state->mCodec->stop(), (status_t)OK); + } + + mStartTimeRealUs = -1ll; + + mStateByTrackIndex.clear(); + mCodecLooper.clear(); + mExtractor.clear(); + mNativeWindow.clear(); + mPath.clear(); + + return OK; +} + +status_t SimplePlayer::onDoMoreStuff() { + ALOGV("onDoMoreStuff"); + for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) { + CodecState *state = &mStateByTrackIndex.editValueAt(i); + + status_t err; + do { + size_t index; + err = state->mCodec->dequeueInputBuffer(&index); + + if (err == OK) { + ALOGV("dequeued input buffer on track %d", + mStateByTrackIndex.keyAt(i)); + + state->mAvailInputBufferIndices.push_back(index); + } else { + ALOGV("dequeueInputBuffer on track %d returned %d", + mStateByTrackIndex.keyAt(i), err); + } + } while (err == OK); + + do { + BufferInfo info; + err = state->mCodec->dequeueOutputBuffer( + &info.mIndex, + &info.mOffset, + &info.mSize, + &info.mPresentationTimeUs, + &info.mFlags); + + if (err == OK) { + ALOGV("dequeued output buffer on track %d", + mStateByTrackIndex.keyAt(i)); + + state->mAvailOutputBufferInfos.push_back(info); + } else if (err == INFO_FORMAT_CHANGED) { + err = onOutputFormatChanged(mStateByTrackIndex.keyAt(i), state); + CHECK_EQ(err, (status_t)OK); + } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) { + err = state->mCodec->getOutputBuffers(&state->mBuffers[1]); + CHECK_EQ(err, (status_t)OK); + } else { + ALOGV("dequeueOutputBuffer on track %d returned %d", + mStateByTrackIndex.keyAt(i), err); + } + } while (err == OK + || err == INFO_FORMAT_CHANGED + || err == INFO_OUTPUT_BUFFERS_CHANGED); + } + + for (;;) { + size_t trackIndex; + status_t err = mExtractor->getSampleTrackIndex(&trackIndex); + + if (err != OK) { + ALOGI("encountered input EOS."); + break; + } else { + CodecState *state = &mStateByTrackIndex.editValueFor(trackIndex); + + if (state->mAvailInputBufferIndices.empty()) { + break; + } + + size_t index = *state->mAvailInputBufferIndices.begin(); + state->mAvailInputBufferIndices.erase( + state->mAvailInputBufferIndices.begin()); + + const sp<ABuffer> &dstBuffer = + state->mBuffers[0].itemAt(index); + + err = mExtractor->readSampleData(dstBuffer); + CHECK_EQ(err, (status_t)OK); + + int64_t timeUs; + CHECK_EQ(mExtractor->getSampleTime(&timeUs), (status_t)OK); + + err = state->mCodec->queueInputBuffer( + index, + dstBuffer->offset(), + dstBuffer->size(), + timeUs, + 0); + CHECK_EQ(err, (status_t)OK); + + ALOGV("enqueued input data on track %d", trackIndex); + + err = mExtractor->advance(); + CHECK_EQ(err, (status_t)OK); + } + } + + int64_t nowUs = ALooper::GetNowUs(); + + if (mStartTimeRealUs < 0ll) { + mStartTimeRealUs = nowUs + 1000000ll; + } + + for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) { + CodecState *state = &mStateByTrackIndex.editValueAt(i); + + while (!state->mAvailOutputBufferInfos.empty()) { + BufferInfo *info = &*state->mAvailOutputBufferInfos.begin(); + + int64_t whenRealUs = info->mPresentationTimeUs + mStartTimeRealUs; + int64_t lateByUs = nowUs - whenRealUs; + + if (lateByUs > -10000ll) { + bool release = true; + + if (lateByUs > 30000ll) { + ALOGI("track %d buffer late by %lld us, dropping.", + mStateByTrackIndex.keyAt(i), lateByUs); + state->mCodec->releaseOutputBuffer(info->mIndex); + } else { + if (state->mAudioTrack != NULL) { + const sp<ABuffer> &srcBuffer = + state->mBuffers[1].itemAt(info->mIndex); + + renderAudio(state, info, srcBuffer); + + if (info->mSize > 0) { + release = false; + } + } + + if (release) { + state->mCodec->renderOutputBufferAndRelease( + info->mIndex); + } + } + + if (release) { + state->mAvailOutputBufferInfos.erase( + state->mAvailOutputBufferInfos.begin()); + + info = NULL; + } else { + break; + } + } else { + ALOGV("track %d buffer early by %lld us.", + mStateByTrackIndex.keyAt(i), -lateByUs); + break; + } + } + } + + return OK; +} + +status_t SimplePlayer::onOutputFormatChanged( + size_t trackIndex, CodecState *state) { + sp<AMessage> format; + status_t err = state->mCodec->getOutputFormat(&format); + + if (err != OK) { + return err; + } + + AString mime; + CHECK(format->findString("mime", &mime)); + + if (!strncasecmp(mime.c_str(), "audio/", 6)) { + int32_t channelCount; + int32_t sampleRate; + CHECK(format->findInt32("channel-count", &channelCount)); + CHECK(format->findInt32("sample-rate", &sampleRate)); + + state->mAudioTrack = new AudioTrack( + AUDIO_STREAM_MUSIC, + sampleRate, + AUDIO_FORMAT_PCM_16_BIT, + (channelCount == 1) + ? AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO, + 0); + + state->mNumFramesWritten = 0; + } + + return OK; +} + +void SimplePlayer::renderAudio( + CodecState *state, BufferInfo *info, const sp<ABuffer> &buffer) { + CHECK(state->mAudioTrack != NULL); + + if (state->mAudioTrack->stopped()) { + state->mAudioTrack->start(); + } + + uint32_t numFramesPlayed; + CHECK_EQ(state->mAudioTrack->getPosition(&numFramesPlayed), (status_t)OK); + + uint32_t numFramesAvailableToWrite = + state->mAudioTrack->frameCount() + - (state->mNumFramesWritten - numFramesPlayed); + + size_t numBytesAvailableToWrite = + numFramesAvailableToWrite * state->mAudioTrack->frameSize(); + + size_t copy = info->mSize; + if (copy > numBytesAvailableToWrite) { + copy = numBytesAvailableToWrite; + } + + if (copy == 0) { + return; + } + + int64_t startTimeUs = ALooper::GetNowUs(); + + ssize_t nbytes = state->mAudioTrack->write( + buffer->base() + info->mOffset, copy); + + CHECK_EQ(nbytes, (ssize_t)copy); + + int64_t delayUs = ALooper::GetNowUs() - startTimeUs; + + uint32_t numFramesWritten = nbytes / state->mAudioTrack->frameSize(); + + if (delayUs > 2000ll) { + ALOGW("AudioTrack::write took %lld us, numFramesAvailableToWrite=%u, " + "numFramesWritten=%u", + delayUs, numFramesAvailableToWrite, numFramesWritten); + } + + info->mOffset += nbytes; + info->mSize -= nbytes; + + state->mNumFramesWritten += numFramesWritten; +} + +} // namespace android diff --git a/cmds/stagefright/SimplePlayer.h b/cmds/stagefright/SimplePlayer.h new file mode 100644 index 0000000..2548252 --- /dev/null +++ b/cmds/stagefright/SimplePlayer.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2012 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/stagefright/foundation/AHandler.h> +#include <media/stagefright/foundation/AString.h> +#include <utils/KeyedVector.h> + +namespace android { + +struct ABuffer; +struct ALooper; +struct AudioTrack; +struct ISurfaceTexture; +struct MediaCodec; +struct NativeWindowWrapper; +struct NuMediaExtractor; + +struct SimplePlayer : public AHandler { + SimplePlayer(); + + status_t setDataSource(const char *path); + status_t setSurface(const sp<ISurfaceTexture> &surfaceTexture); + status_t prepare(); + status_t start(); + status_t stop(); + status_t reset(); + +protected: + virtual ~SimplePlayer(); + + virtual void onMessageReceived(const sp<AMessage> &msg); + +private: + enum State { + UNINITIALIZED, + UNPREPARED, + STOPPED, + STARTED + }; + + enum { + kWhatSetDataSource, + kWhatSetSurface, + kWhatPrepare, + kWhatStart, + kWhatStop, + kWhatReset, + kWhatDoMoreStuff, + }; + + struct BufferInfo { + size_t mIndex; + size_t mOffset; + size_t mSize; + int64_t mPresentationTimeUs; + uint32_t mFlags; + }; + + struct CodecState + { + sp<MediaCodec> mCodec; + Vector<sp<ABuffer> > mCSD; + Vector<sp<ABuffer> > mBuffers[2]; + + List<size_t> mAvailInputBufferIndices; + List<BufferInfo> mAvailOutputBufferInfos; + + sp<AudioTrack> mAudioTrack; + uint32_t mNumFramesWritten; + }; + + State mState; + AString mPath; + sp<NativeWindowWrapper> mNativeWindow; + + sp<NuMediaExtractor> mExtractor; + sp<ALooper> mCodecLooper; + KeyedVector<size_t, CodecState> mStateByTrackIndex; + int32_t mDoMoreStuffGeneration; + + int64_t mStartTimeRealUs; + + status_t onPrepare(); + status_t onStart(); + status_t onStop(); + status_t onReset(); + status_t onDoMoreStuff(); + status_t onOutputFormatChanged(size_t trackIndex, CodecState *state); + + void renderAudio( + CodecState *state, BufferInfo *info, const sp<ABuffer> &buffer); + + DISALLOW_EVIL_CONSTRUCTORS(SimplePlayer); +}; + +} // namespace android diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp new file mode 100644 index 0000000..b850190 --- /dev/null +++ b/cmds/stagefright/codec.cpp @@ -0,0 +1,408 @@ +/* + * Copyright (C) 2012 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 "codec" +#include <utils/Log.h> + +#include "SimplePlayer.h" + +#include <binder/ProcessState.h> + +#include <media/stagefright/foundation/ABuffer.h> +#include <media/stagefright/foundation/ADebug.h> +#include <media/stagefright/foundation/ALooper.h> +#include <media/stagefright/foundation/AMessage.h> +#include <media/stagefright/DataSource.h> +#include <media/stagefright/MediaCodec.h> +#include <media/stagefright/MediaDefs.h> +#include <media/stagefright/NuMediaExtractor.h> +#include <gui/SurfaceComposerClient.h> + +static void usage(const char *me) { + fprintf(stderr, "usage: %s [-a] use audio\n" + "\t\t[-v] use video\n" + "\t\t[-p] playback\n", me); + + exit(1); +} + +namespace android { + +struct CodecState { + sp<MediaCodec> mCodec; + Vector<sp<ABuffer> > mCSD; + size_t mCSDIndex; + Vector<sp<ABuffer> > mInBuffers; + Vector<sp<ABuffer> > mOutBuffers; + bool mSawOutputEOS; +}; + +} // namespace android + +static int decode( + const android::sp<android::ALooper> &looper, + const char *path, + bool useAudio, + bool useVideo) { + using namespace android; + + sp<NuMediaExtractor> extractor = new NuMediaExtractor; + if (extractor->setDataSource(path) != OK) { + fprintf(stderr, "unable to instantiate extractor.\n"); + return 1; + } + + KeyedVector<size_t, CodecState> stateByTrack; + + bool haveAudio = false; + bool haveVideo = false; + for (size_t i = 0; i < extractor->countTracks(); ++i) { + sp<AMessage> format; + status_t err = extractor->getTrackFormat(i, &format); + CHECK_EQ(err, (status_t)OK); + + AString mime; + CHECK(format->findString("mime", &mime)); + + if (useAudio && !haveAudio + && !strncasecmp(mime.c_str(), "audio/", 6)) { + haveAudio = true; + } else if (useVideo && !haveVideo + && !strncasecmp(mime.c_str(), "video/", 6)) { + haveVideo = true; + } else { + continue; + } + + ALOGV("selecting track %d", i); + + err = extractor->selectTrack(i); + CHECK_EQ(err, (status_t)OK); + + CodecState *state = + &stateByTrack.editValueAt(stateByTrack.add(i, CodecState())); + + state->mCodec = MediaCodec::CreateByType( + looper, mime.c_str(), false /* encoder */); + + CHECK(state->mCodec != NULL); + + err = state->mCodec->configure( + format, NULL /* surfaceTexture */, 0 /* flags */); + + CHECK_EQ(err, (status_t)OK); + + size_t j = 0; + sp<ABuffer> buffer; + while (format->findBuffer(StringPrintf("csd-%d", j).c_str(), &buffer)) { + state->mCSD.push_back(buffer); + + ++j; + } + + state->mCSDIndex = 0; + state->mSawOutputEOS = false; + + ALOGV("got %d pieces of codec specific data.", state->mCSD.size()); + } + + CHECK(!stateByTrack.isEmpty()); + + for (size_t i = 0; i < stateByTrack.size(); ++i) { + CodecState *state = &stateByTrack.editValueAt(i); + + sp<MediaCodec> codec = state->mCodec; + + CHECK_EQ((status_t)OK, codec->start()); + + CHECK_EQ((status_t)OK, codec->getInputBuffers(&state->mInBuffers)); + CHECK_EQ((status_t)OK, codec->getOutputBuffers(&state->mOutBuffers)); + + ALOGV("got %d input and %d output buffers", + state->mInBuffers.size(), state->mOutBuffers.size()); + + while (state->mCSDIndex < state->mCSD.size()) { + size_t index; + status_t err = codec->dequeueInputBuffer(&index); + + if (err == -EAGAIN) { + usleep(10000); + continue; + } + + CHECK_EQ(err, (status_t)OK); + + const sp<ABuffer> &srcBuffer = + state->mCSD.itemAt(state->mCSDIndex++); + + const sp<ABuffer> &buffer = state->mInBuffers.itemAt(index); + + memcpy(buffer->data(), srcBuffer->data(), srcBuffer->size()); + + err = codec->queueInputBuffer( + index, + 0 /* offset */, + srcBuffer->size(), + 0ll /* timeUs */, + MediaCodec::BUFFER_FLAG_CODECCONFIG); + + CHECK_EQ(err, (status_t)OK); + } + } + + bool sawInputEOS = false; + + for (;;) { + if (!sawInputEOS) { + size_t trackIndex; + status_t err = extractor->getSampleTrackIndex(&trackIndex); + + if (err != OK) { + ALOGV("signalling EOS."); + + for (size_t i = 0; i < stateByTrack.size(); ++i) { + CodecState *state = &stateByTrack.editValueAt(i); + + for (;;) { + size_t index; + err = state->mCodec->dequeueInputBuffer(&index); + + if (err == -EAGAIN) { + continue; + } + + CHECK_EQ(err, (status_t)OK); + + err = state->mCodec->queueInputBuffer( + index, + 0 /* offset */, + 0 /* size */, + 0ll /* timeUs */, + MediaCodec::BUFFER_FLAG_EOS); + + CHECK_EQ(err, (status_t)OK); + break; + } + } + + sawInputEOS = true; + } else { + CodecState *state = &stateByTrack.editValueFor(trackIndex); + + size_t index; + err = state->mCodec->dequeueInputBuffer(&index); + + if (err == OK) { + ALOGV("filling input buffer %d", index); + + const sp<ABuffer> &buffer = state->mInBuffers.itemAt(index); + + err = extractor->readSampleData(buffer); + CHECK_EQ(err, (status_t)OK); + + int64_t timeUs; + err = extractor->getSampleTime(&timeUs); + CHECK_EQ(err, (status_t)OK); + + err = state->mCodec->queueInputBuffer( + index, + 0 /* offset */, + buffer->size(), + timeUs, + 0 /* flags */); + + CHECK_EQ(err, (status_t)OK); + + extractor->advance(); + } else { + CHECK_EQ(err, -EAGAIN); + } + } + } + + bool sawOutputEOSOnAllTracks = true; + for (size_t i = 0; i < stateByTrack.size(); ++i) { + CodecState *state = &stateByTrack.editValueAt(i); + if (!state->mSawOutputEOS) { + sawOutputEOSOnAllTracks = false; + break; + } + } + + if (sawOutputEOSOnAllTracks) { + break; + } + + for (size_t i = 0; i < stateByTrack.size(); ++i) { + CodecState *state = &stateByTrack.editValueAt(i); + + if (state->mSawOutputEOS) { + continue; + } + + size_t index; + size_t offset; + size_t size; + int64_t presentationTimeUs; + uint32_t flags; + status_t err = state->mCodec->dequeueOutputBuffer( + &index, &offset, &size, &presentationTimeUs, &flags, + 10000ll); + + if (err == OK) { + ALOGV("draining output buffer %d, time = %lld us", + index, presentationTimeUs); + + err = state->mCodec->releaseOutputBuffer(index); + CHECK_EQ(err, (status_t)OK); + + if (flags & MediaCodec::BUFFER_FLAG_EOS) { + ALOGV("reached EOS on output."); + + state->mSawOutputEOS = true; + } + } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) { + ALOGV("INFO_OUTPUT_BUFFERS_CHANGED"); + CHECK_EQ((status_t)OK, + state->mCodec->getOutputBuffers(&state->mOutBuffers)); + + ALOGV("got %d output buffers", state->mOutBuffers.size()); + } else if (err == INFO_FORMAT_CHANGED) { + sp<AMessage> format; + CHECK_EQ((status_t)OK, state->mCodec->getOutputFormat(&format)); + + ALOGV("INFO_FORMAT_CHANGED: %s", format->debugString().c_str()); + } else { + CHECK_EQ(err, -EAGAIN); + } + } + } + + for (size_t i = 0; i < stateByTrack.size(); ++i) { + CodecState *state = &stateByTrack.editValueAt(i); + + CHECK_EQ((status_t)OK, state->mCodec->stop()); + } + + return 0; +} + +int main(int argc, char **argv) { + using namespace android; + + const char *me = argv[0]; + + bool useAudio = false; + bool useVideo = false; + bool playback = false; + + int res; + while ((res = getopt(argc, argv, "havp")) >= 0) { + switch (res) { + case 'a': + { + useAudio = true; + break; + } + + case 'v': + { + useVideo = true; + break; + } + + case 'p': + { + playback = true; + break; + } + + case '?': + case 'h': + default: + { + usage(me); + } + } + } + + argc -= optind; + argv += optind; + + if (argc != 1) { + usage(me); + } + + if (!useAudio && !useVideo) { + useAudio = useVideo = true; + } + + ProcessState::self()->startThreadPool(); + + DataSource::RegisterDefaultSniffers(); + + sp<ALooper> looper = new ALooper; + looper->start(); + + if (playback) { + sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient; + CHECK_EQ(composerClient->initCheck(), (status_t)OK); + + ssize_t displayWidth = composerClient->getDisplayWidth(0); + ssize_t displayHeight = composerClient->getDisplayHeight(0); + + ALOGV("display is %ld x %ld\n", displayWidth, displayHeight); + + sp<SurfaceControl> control = + composerClient->createSurface( + String8("A Surface"), + 0, + displayWidth, + displayHeight, + PIXEL_FORMAT_RGB_565, + 0); + + CHECK(control != NULL); + CHECK(control->isValid()); + + SurfaceComposerClient::openGlobalTransaction(); + CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK); + CHECK_EQ(control->show(), (status_t)OK); + SurfaceComposerClient::closeGlobalTransaction(); + + sp<Surface> surface = control->getSurface(); + CHECK(surface != NULL); + + sp<SimplePlayer> player = new SimplePlayer; + looper->registerHandler(player); + + player->setDataSource(argv[0]); + player->setSurface(surface->getSurfaceTexture()); + player->start(); + sleep(60); + player->stop(); + player->reset(); + + composerClient->dispose(); + } else { + decode(looper, argv[0], useAudio, useVideo); + } + + looper->stop(); + + return 0; +} diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp index ae80f88..1d28793 100644 --- a/cmds/stagefright/sf2.cpp +++ b/cmds/stagefright/sf2.cpp @@ -32,8 +32,7 @@ #include <media/stagefright/NativeWindowWrapper.h> #include <media/stagefright/Utils.h> -#include <surfaceflinger/ISurfaceComposer.h> -#include <surfaceflinger/SurfaceComposerClient.h> +#include <gui/SurfaceComposerClient.h> #include "include/ESDS.h" @@ -198,9 +197,7 @@ protected: (new AMessage(kWhatSeek, id()))->post(5000000ll); } else if (what == ACodec::kWhatOutputFormatChanged) { - } else { - CHECK_EQ(what, (int32_t)ACodec::kWhatShutdownCompleted); - + } else if (what == ACodec::kWhatShutdownCompleted) { mDecodeLooper->unregisterHandler(mCodec->id()); if (mDecodeLooper != looper()) { @@ -360,7 +357,7 @@ private: buffer->meta()->setInt32("csd", true); mCSD.push(buffer); - msg->setObject("csd", buffer); + msg->setBuffer("csd", buffer); } else if (meta->findData(kKeyESDS, &type, &data, &size)) { ESDS esds((const char *)data, size); CHECK_EQ(esds.InitCheck(), (status_t)OK); @@ -410,9 +407,8 @@ private: return; } - sp<RefBase> obj; - CHECK(msg->findObject("buffer", &obj)); - sp<ABuffer> outBuffer = static_cast<ABuffer *>(obj.get()); + sp<ABuffer> outBuffer; + CHECK(msg->findBuffer("buffer", &outBuffer)); if (mCSDIndex < mCSD.size()) { outBuffer = mCSD.editItemAt(mCSDIndex++); @@ -511,15 +507,14 @@ private: } } - reply->setObject("buffer", outBuffer); + reply->setBuffer("buffer", outBuffer); reply->post(); } void onDrainThisBuffer(const sp<AMessage> &msg) { - sp<RefBase> obj; - CHECK(msg->findObject("buffer", &obj)); + sp<ABuffer> buffer; + CHECK(msg->findBuffer("buffer", &buffer)); - sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); mTotalBytesReceived += buffer->size(); sp<AMessage> reply; diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp index 7cb8f62..dab2e0f 100644 --- a/cmds/stagefright/stagefright.cpp +++ b/cmds/stagefright/stagefright.cpp @@ -55,9 +55,7 @@ #include <fcntl.h> #include <gui/SurfaceTextureClient.h> - -#include <surfaceflinger/ISurfaceComposer.h> -#include <surfaceflinger/SurfaceComposerClient.h> +#include <gui/SurfaceComposerClient.h> using namespace android; diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp index 0d6c738..efa1445 100644 --- a/cmds/stagefright/stream.cpp +++ b/cmds/stagefright/stream.cpp @@ -32,8 +32,7 @@ #include <binder/IServiceManager.h> #include <media/IMediaPlayerService.h> -#include <surfaceflinger/ISurfaceComposer.h> -#include <surfaceflinger/SurfaceComposerClient.h> +#include <gui/SurfaceComposerClient.h> #include <fcntl.h> diff --git a/include/camera/ICamera.h b/include/camera/ICamera.h index 400d7f4..3d18837 100644 --- a/include/camera/ICamera.h +++ b/include/camera/ICamera.h @@ -20,15 +20,15 @@ #include <utils/RefBase.h> #include <binder/IInterface.h> #include <binder/Parcel.h> -#include <surfaceflinger/Surface.h> #include <binder/IMemory.h> #include <utils/String8.h> #include <camera/Camera.h> -#include <gui/ISurfaceTexture.h> namespace android { class ICameraClient; +class ISurfaceTexture; +class Surface; class ICamera: public IInterface { diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h index 3963d9c..70799a6 100644 --- a/include/media/stagefright/ACodec.h +++ b/include/media/stagefright/ACodec.h @@ -22,6 +22,7 @@ #include <android/native_window.h> #include <media/IOMX.h> #include <media/stagefright/foundation/AHierarchicalStateMachine.h> +#include <OMX_Audio.h> namespace android { @@ -37,6 +38,9 @@ struct ACodec : public AHierarchicalStateMachine { kWhatFlushCompleted = 'fcom', kWhatOutputFormatChanged = 'outC', kWhatError = 'erro', + kWhatComponentAllocated = 'cAll', + kWhatComponentConfigured = 'cCon', + kWhatBuffersAllocated = 'allc', }; ACodec(); @@ -47,6 +51,10 @@ struct ACodec : public AHierarchicalStateMachine { void signalResume(); void initiateShutdown(); + void initiateAllocateComponent(const sp<AMessage> &msg); + void initiateConfigureComponent(const sp<AMessage> &msg); + void initiateStart(); + protected: virtual ~ACodec(); @@ -70,6 +78,9 @@ private: kWhatFlush = 'flus', kWhatResume = 'resm', kWhatDrainDeferredMessages = 'drai', + kWhatAllocateComponent = 'allo', + kWhatConfigureComponent = 'conf', + kWhatStart = 'star', }; enum { @@ -118,6 +129,7 @@ private: List<sp<AMessage> > mDeferredQueue; bool mSentFormat; + bool mIsEncoder; status_t allocateBuffersOnPort(OMX_U32 portIndex); status_t freeBuffersOnPort(OMX_U32 portIndex); @@ -132,8 +144,8 @@ private: uint32_t portIndex, IOMX::buffer_id bufferID, ssize_t *index = NULL); - void setComponentRole(bool isEncoder, const char *mime); - void configureCodec(const char *mime, const sp<AMessage> &msg); + status_t setComponentRole(bool isEncoder, const char *mime); + status_t configureCodec(const char *mime, const sp<AMessage> &msg); status_t setVideoPortFormatType( OMX_U32 portIndex, @@ -145,20 +157,37 @@ private: status_t setupVideoDecoder( const char *mime, int32_t width, int32_t height); + status_t setupVideoEncoder( + const char *mime, const sp<AMessage> &msg); + status_t setVideoFormatOnPort( OMX_U32 portIndex, int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat); - status_t setupAACDecoder(int32_t numChannels, int32_t sampleRate); - status_t setupAMRDecoder(bool isWAMR); - status_t setupG711Decoder(int32_t numChannels); + status_t setupAACCodec( + bool encoder, + int32_t numChannels, int32_t sampleRate, int32_t bitRate); + + status_t selectAudioPortFormat( + OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat); + + status_t setupAMRCodec(bool encoder, bool isWAMR, int32_t bitRate); + status_t setupG711Codec(bool encoder, int32_t numChannels); status_t setupRawAudioFormat( OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels); status_t setMinBufferSize(OMX_U32 portIndex, size_t size); + status_t setupMPEG4EncoderParameters(const sp<AMessage> &msg); + status_t setupH263EncoderParameters(const sp<AMessage> &msg); + status_t setupAVCEncoderParameters(const sp<AMessage> &msg); + + status_t verifySupportForProfileAndLevel(int32_t profile, int32_t level); + status_t configureBitrate(int32_t bitrate); + status_t setupErrorCorrectionParameters(); + status_t initNativeWindow(); // Returns true iff all buffers on the given port have status OWNED_BY_US. @@ -173,7 +202,9 @@ private: void sendFormatChange(); - void signalError(OMX_ERRORTYPE error = OMX_ErrorUndefined); + void signalError( + OMX_ERRORTYPE error = OMX_ErrorUndefined, + status_t internalError = UNKNOWN_ERROR); DISALLOW_EVIL_CONSTRUCTORS(ACodec); }; diff --git a/include/media/stagefright/HardwareAPI.h b/include/media/stagefright/HardwareAPI.h index 32eed3f..17efd35 100644 --- a/include/media/stagefright/HardwareAPI.h +++ b/include/media/stagefright/HardwareAPI.h @@ -19,7 +19,7 @@ #define HARDWARE_API_H_ #include <media/stagefright/OMXPluginBase.h> -#include <ui/android_native_buffer.h> +#include <system/window.h> #include <utils/RefBase.h> #include <OMX_Component.h> diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h new file mode 100644 index 0000000..8c11c9c --- /dev/null +++ b/include/media/stagefright/MediaCodec.h @@ -0,0 +1,183 @@ +/* + * Copyright 2012, 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_H_ + +#define MEDIA_CODEC_H_ + +#include <gui/ISurfaceTexture.h> +#include <media/stagefright/foundation/AHandler.h> +#include <utils/Vector.h> + +namespace android { + +struct ABuffer; +struct ACodec; +struct AMessage; +struct SoftwareRenderer; +struct SurfaceTextureClient; + +struct MediaCodec : public AHandler { + enum ConfigureFlags { + CONFIGURE_FLAG_ENCODE = 1, + }; + + enum BufferFlags { + BUFFER_FLAG_SYNCFRAME = 1, + BUFFER_FLAG_CODECCONFIG = 2, + BUFFER_FLAG_EOS = 4, + }; + + static sp<MediaCodec> CreateByType( + const sp<ALooper> &looper, const char *mime, bool encoder); + + static sp<MediaCodec> CreateByComponentName( + const sp<ALooper> &looper, const char *name); + + status_t configure( + const sp<AMessage> &format, + const sp<SurfaceTextureClient> &nativeWindow, + uint32_t flags); + + status_t start(); + status_t stop(); + + status_t flush(); + + status_t queueInputBuffer( + size_t index, + size_t offset, + size_t size, + int64_t presentationTimeUs, + uint32_t flags); + + status_t dequeueInputBuffer(size_t *index, int64_t timeoutUs = 0ll); + + status_t dequeueOutputBuffer( + size_t *index, + size_t *offset, + size_t *size, + int64_t *presentationTimeUs, + uint32_t *flags, + int64_t timeoutUs = 0ll); + + status_t renderOutputBufferAndRelease(size_t index); + status_t releaseOutputBuffer(size_t index); + + status_t getOutputFormat(sp<AMessage> *format) const; + + status_t getInputBuffers(Vector<sp<ABuffer> > *buffers) const; + status_t getOutputBuffers(Vector<sp<ABuffer> > *buffers) const; + +protected: + virtual ~MediaCodec(); + virtual void onMessageReceived(const sp<AMessage> &msg); + +private: + enum State { + UNINITIALIZED, + INITIALIZING, + INITIALIZED, + CONFIGURING, + CONFIGURED, + STARTING, + STARTED, + FLUSHING, + STOPPING, + }; + + enum { + kPortIndexInput = 0, + kPortIndexOutput = 1, + }; + + enum { + kWhatInit = 'init', + kWhatConfigure = 'conf', + kWhatStart = 'strt', + kWhatStop = 'stop', + kWhatDequeueInputBuffer = 'deqI', + kWhatQueueInputBuffer = 'queI', + kWhatDequeueOutputBuffer = 'deqO', + kWhatReleaseOutputBuffer = 'relO', + kWhatGetBuffers = 'getB', + kWhatFlush = 'flus', + kWhatGetOutputFormat = 'getO', + kWhatDequeueInputTimedOut = 'dITO', + kWhatDequeueOutputTimedOut = 'dOTO', + kWhatCodecNotify = 'codc', + }; + + enum { + kFlagIsSoftwareCodec = 1, + kFlagOutputFormatChanged = 2, + kFlagOutputBuffersChanged = 4, + kFlagStickyError = 8, + kFlagDequeueInputPending = 16, + kFlagDequeueOutputPending = 32, + }; + + struct BufferInfo { + void *mBufferID; + sp<ABuffer> mData; + sp<AMessage> mNotify; + bool mOwnedByClient; + }; + + State mState; + sp<ALooper> mLooper; + sp<ALooper> mCodecLooper; + sp<ACodec> mCodec; + uint32_t mReplyID; + uint32_t mFlags; + sp<SurfaceTextureClient> mNativeWindow; + SoftwareRenderer *mSoftRenderer; + sp<AMessage> mOutputFormat; + + List<size_t> mAvailPortBuffers[2]; + Vector<BufferInfo> mPortBuffers[2]; + + int32_t mDequeueInputTimeoutGeneration; + uint32_t mDequeueInputReplyID; + + int32_t mDequeueOutputTimeoutGeneration; + uint32_t mDequeueOutputReplyID; + + MediaCodec(const sp<ALooper> &looper); + + static status_t PostAndAwaitResponse( + const sp<AMessage> &msg, sp<AMessage> *response); + + status_t init(const char *name, bool nameIsType, bool encoder); + + void setState(State newState); + void returnBuffersToCodec(); + void returnBuffersToCodecOnPort(int32_t portIndex); + size_t updateBuffers(int32_t portIndex, const sp<AMessage> &msg); + status_t onQueueInputBuffer(const sp<AMessage> &msg); + status_t onReleaseOutputBuffer(const sp<AMessage> &msg); + ssize_t dequeuePortBuffer(int32_t portIndex); + + bool handleDequeueInputBuffer(uint32_t replyID, bool newRequest = false); + bool handleDequeueOutputBuffer(uint32_t replyID, bool newRequest = false); + void cancelPendingDequeueOperations(); + + DISALLOW_EVIL_CONSTRUCTORS(MediaCodec); +}; + +} // namespace android + +#endif // MEDIA_CODEC_H_ diff --git a/include/media/stagefright/MediaErrors.h b/include/media/stagefright/MediaErrors.h index 21d00b8..dd3bf28 100644 --- a/include/media/stagefright/MediaErrors.h +++ b/include/media/stagefright/MediaErrors.h @@ -40,6 +40,7 @@ enum { // Not technically an error. INFO_FORMAT_CHANGED = MEDIA_ERROR_BASE - 12, INFO_DISCONTINUITY = MEDIA_ERROR_BASE - 13, + INFO_OUTPUT_BUFFERS_CHANGED = MEDIA_ERROR_BASE - 14, // The following constant values should be in sync with // drm/drm_framework_common.h diff --git a/include/media/stagefright/NativeWindowWrapper.h b/include/media/stagefright/NativeWindowWrapper.h index f323cbc..97cc0ce 100644 --- a/include/media/stagefright/NativeWindowWrapper.h +++ b/include/media/stagefright/NativeWindowWrapper.h @@ -18,40 +18,28 @@ #define NATIVE_WINDOW_WRAPPER_H_ -#include <surfaceflinger/Surface.h> #include <gui/SurfaceTextureClient.h> namespace android { -// Both Surface and SurfaceTextureClient are RefBase that implement the -// ANativeWindow interface, but at different addresses. ANativeWindow is not -// a RefBase but acts like one for use with sp<>. This wrapper converts a -// Surface or SurfaceTextureClient into a single reference-counted object -// that holds an sp reference to the underlying Surface or SurfaceTextureClient, -// It provides a method to get the ANativeWindow. +// SurfaceTextureClient derives from ANativeWindow which derives from multiple +// base classes, in order to carry it in AMessages, we'll temporarily wrap it +// into a NativeWindowWrapper. struct NativeWindowWrapper : RefBase { NativeWindowWrapper( - const sp<Surface> &surface) : - mSurface(surface) { } - - NativeWindowWrapper( const sp<SurfaceTextureClient> &surfaceTextureClient) : mSurfaceTextureClient(surfaceTextureClient) { } sp<ANativeWindow> getNativeWindow() const { - if (mSurface != NULL) { - return mSurface; - } else { - return mSurfaceTextureClient; - } + return mSurfaceTextureClient; } - // If needed later we can provide a method to ask what kind of native window + sp<SurfaceTextureClient> getSurfaceTextureClient() const { + return mSurfaceTextureClient; + } private: - // At most one of mSurface and mSurfaceTextureClient will be non-NULL - const sp<Surface> mSurface; const sp<SurfaceTextureClient> mSurfaceTextureClient; DISALLOW_EVIL_CONSTRUCTORS(NativeWindowWrapper); diff --git a/include/media/stagefright/NuMediaExtractor.h b/include/media/stagefright/NuMediaExtractor.h new file mode 100644 index 0000000..96efdff --- /dev/null +++ b/include/media/stagefright/NuMediaExtractor.h @@ -0,0 +1,80 @@ +/* + * Copyright 2012, 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 NU_MEDIA_EXTRACTOR_H_ +#define NU_MEDIA_EXTRACTOR_H_ + +#include <media/stagefright/foundation/ABase.h> +#include <utils/Errors.h> +#include <utils/RefBase.h> +#include <utils/Vector.h> + +namespace android { + +struct ABuffer; +struct AMessage; +struct MediaBuffer; +struct MediaExtractor; +struct MediaSource; + +struct NuMediaExtractor : public RefBase { + NuMediaExtractor(); + + status_t setDataSource(const char *path); + + size_t countTracks() const; + status_t getTrackFormat(size_t index, sp<AMessage> *format) const; + + status_t selectTrack(size_t index); + + status_t seekTo(int64_t timeUs); + + status_t advance(); + status_t readSampleData(const sp<ABuffer> &buffer); + status_t getSampleTrackIndex(size_t *trackIndex); + status_t getSampleTime(int64_t *sampleTimeUs); + +protected: + virtual ~NuMediaExtractor(); + +private: + enum TrackFlags { + kIsVorbis = 1, + }; + + struct TrackInfo { + sp<MediaSource> mSource; + size_t mTrackIndex; + status_t mFinalResult; + MediaBuffer *mSample; + int64_t mSampleTimeUs; + uint32_t mFlags; // bitmask of "TrackFlags" + }; + + sp<MediaExtractor> mImpl; + + Vector<TrackInfo> mSelectedTracks; + + ssize_t fetchTrackSamples(int64_t seekTimeUs = -1ll); + void releaseTrackSamples(); + + DISALLOW_EVIL_CONSTRUCTORS(NuMediaExtractor); +}; + +} // namespace android + +#endif // NU_MEDIA_EXTRACTOR_H_ + diff --git a/include/media/stagefright/foundation/AMessage.h b/include/media/stagefright/foundation/AMessage.h index 7ec54aa..e5416e4 100644 --- a/include/media/stagefright/foundation/AMessage.h +++ b/include/media/stagefright/foundation/AMessage.h @@ -25,6 +25,7 @@ namespace android { +struct ABuffer; struct AString; struct Parcel; @@ -50,6 +51,7 @@ struct AMessage : public RefBase { void setPointer(const char *name, void *value); void setString(const char *name, const char *s, ssize_t len = -1); void setObject(const char *name, const sp<RefBase> &obj); + void setBuffer(const char *name, const sp<ABuffer> &buffer); void setMessage(const char *name, const sp<AMessage> &obj); void setRect( @@ -64,6 +66,7 @@ struct AMessage : public RefBase { bool findPointer(const char *name, void **value) const; bool findString(const char *name, AString *value) const; bool findObject(const char *name, sp<RefBase> *obj) const; + bool findBuffer(const char *name, sp<ABuffer> *buffer) const; bool findMessage(const char *name, sp<AMessage> *obj) const; bool findRect( @@ -90,10 +93,6 @@ struct AMessage : public RefBase { AString debugString(int32_t indent = 0) const; -protected: - virtual ~AMessage(); - -private: enum Type { kTypeInt32, kTypeInt64, @@ -105,8 +104,16 @@ private: kTypeObject, kTypeMessage, kTypeRect, + kTypeBuffer, }; + size_t countEntries() const; + const char *getEntryNameAt(size_t index, Type *type) const; + +protected: + virtual ~AMessage(); + +private: uint32_t mWhat; ALooper::handler_id mTarget; @@ -131,7 +138,7 @@ private: }; enum { - kMaxNumItems = 16 + kMaxNumItems = 32 }; Item mItems[kMaxNumItems]; size_t mNumItems; @@ -140,6 +147,9 @@ private: void freeItem(Item *item); const Item *findItem(const char *name, Type type) const; + void setObjectInternal( + const char *name, const sp<RefBase> &obj, Type type); + DISALLOW_EVIL_CONSTRUCTORS(AMessage); }; diff --git a/include/private/surfaceflinger/LayerState.h b/include/private/gui/LayerState.h index 3eb5c99..ca277e0 100644 --- a/include/private/surfaceflinger/LayerState.h +++ b/include/private/gui/LayerState.h @@ -23,8 +23,7 @@ #include <utils/Errors.h> #include <ui/Region.h> - -#include <surfaceflinger/ISurface.h> +#include <gui/ISurface.h> namespace android { diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/gui/SharedBufferStack.h index 0da03d1..0da03d1 100644 --- a/include/private/surfaceflinger/SharedBufferStack.h +++ b/include/private/gui/SharedBufferStack.h diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h deleted file mode 100644 index 6b1fa77..0000000 --- a/include/private/opengles/gl_context.h +++ /dev/null @@ -1,640 +0,0 @@ -/* - * Copyright (C) 2006 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_OPENGLES_CONTEXT_H -#define ANDROID_OPENGLES_CONTEXT_H - -#include <stdint.h> -#include <stddef.h> -#include <sys/types.h> -#include <pthread.h> -#ifdef HAVE_ANDROID_OS -#include <bionic_tls.h> -#endif - -#include <private/pixelflinger/ggl_context.h> -#include <hardware/gralloc.h> - -#include <GLES/gl.h> -#include <GLES/glext.h> - -namespace android { - - -const unsigned int OGLES_NUM_COMPRESSED_TEXTURE_FORMATS = 10 -#ifdef GL_OES_compressed_ETC1_RGB8_texture - + 1 -#endif - ; - -class EGLTextureObject; -class EGLSurfaceManager; -class EGLBufferObjectManager; - -namespace gl { - -struct ogles_context_t; -struct matrixx_t; -struct transform_t; -struct buffer_t; - -ogles_context_t* getGlContext(); - -template<typename T> -static inline void swap(T& a, T& b) { - T t(a); a = b; b = t; -} -template<typename T> -inline T max(T a, T b) { - return a<b ? b : a; -} -template<typename T> -inline T max(T a, T b, T c) { - return max(a, max(b, c)); -} -template<typename T> -inline T min(T a, T b) { - return a<b ? a : b; -} -template<typename T> -inline T min(T a, T b, T c) { - return min(a, min(b, c)); -} -template<typename T> -inline T min(T a, T b, T c, T d) { - return min(min(a,b), min(c,d)); -} - -// ---------------------------------------------------------------------------- -// vertices -// ---------------------------------------------------------------------------- - -struct vec3_t { - union { - struct { GLfixed x, y, z; }; - struct { GLfixed r, g, b; }; - struct { GLfixed S, T, R; }; - GLfixed v[3]; - }; -}; - -struct vec4_t { - union { - struct { GLfixed x, y, z, w; }; - struct { GLfixed r, g, b, a; }; - struct { GLfixed S, T, R, Q; }; - GLfixed v[4]; - }; -}; - -struct vertex_t { - enum { - // these constant matter for our clipping - CLIP_L = 0x0001, // clipping flags - CLIP_R = 0x0002, - CLIP_B = 0x0004, - CLIP_T = 0x0008, - CLIP_N = 0x0010, - CLIP_F = 0x0020, - - EYE = 0x0040, - RESERVED = 0x0080, - - USER_CLIP_0 = 0x0100, // user clipping flags - USER_CLIP_1 = 0x0200, - USER_CLIP_2 = 0x0400, - USER_CLIP_3 = 0x0800, - USER_CLIP_4 = 0x1000, - USER_CLIP_5 = 0x2000, - - LIT = 0x4000, // lighting has been applied - TT = 0x8000, // texture coords transformed - - FRUSTUM_CLIP_ALL= 0x003F, - USER_CLIP_ALL = 0x3F00, - CLIP_ALL = 0x3F3F, - }; - - // the fields below are arranged to minimize d-cache usage - // we group together, by cache-line, the fields most likely to be used - - union { - vec4_t obj; - vec4_t eye; - }; - vec4_t clip; - - uint32_t flags; - size_t index; // cache tag, and vertex index - GLfixed fog; - uint8_t locked; - uint8_t mru; - uint8_t reserved[2]; - vec4_t window; - - vec4_t color; - vec4_t texture[GGL_TEXTURE_UNIT_COUNT]; - uint32_t reserved1[4]; - - inline void clear() { - flags = index = locked = mru = 0; - } -}; - -struct point_size_t { - GGLcoord size; - GLboolean smooth; -}; - -struct line_width_t { - GGLcoord width; - GLboolean smooth; -}; - -struct polygon_offset_t { - GLfixed factor; - GLfixed units; - GLboolean enable; -}; - -// ---------------------------------------------------------------------------- -// arrays -// ---------------------------------------------------------------------------- - -struct array_t { - typedef void (*fetcher_t)(ogles_context_t*, GLfixed*, const GLvoid*); - fetcher_t fetch; - GLvoid const* physical_pointer; - GLint size; - GLsizei stride; - GLvoid const* pointer; - buffer_t const* bo; - uint16_t type; - GLboolean enable; - GLboolean pad; - GLsizei bounds; - void init(GLint, GLenum, GLsizei, const GLvoid *, const buffer_t*, GLsizei); - inline void resolve(); - inline const GLubyte* element(GLint i) const { - return (const GLubyte*)physical_pointer + i * stride; - } -}; - -struct array_machine_t { - array_t vertex; - array_t normal; - array_t color; - array_t texture[GGL_TEXTURE_UNIT_COUNT]; - uint8_t activeTexture; - uint8_t tmu; - uint16_t cull; - uint32_t flags; - GLenum indicesType; - buffer_t const* array_buffer; - buffer_t const* element_array_buffer; - - void (*compileElements)(ogles_context_t*, vertex_t*, GLint, GLsizei); - void (*compileElement)(ogles_context_t*, vertex_t*, GLint); - - void (*mvp_transform)(transform_t const*, vec4_t*, vec4_t const*); - void (*mv_transform)(transform_t const*, vec4_t*, vec4_t const*); - void (*tex_transform[2])(transform_t const*, vec4_t*, vec4_t const*); - void (*perspective)(ogles_context_t*c, vertex_t* v); - void (*clipVertex)(ogles_context_t* c, vertex_t* nv, - GGLfixed t, const vertex_t* s, const vertex_t* p); - void (*clipEye)(ogles_context_t* c, vertex_t* nv, - GGLfixed t, const vertex_t* s, const vertex_t* p); -}; - -struct vertex_cache_t { - enum { - // must be at least 4 - // 3 vertice for triangles - // or 2 + 2 for indexed triangles w/ cache contention - VERTEX_BUFFER_SIZE = 8, - // must be a power of two and at least 3 - VERTEX_CACHE_SIZE = 64, // 8 KB - - INDEX_BITS = 16, - INDEX_MASK = ((1LU<<INDEX_BITS)-1), - INDEX_SEQ = 1LU<<INDEX_BITS, - }; - vertex_t* vBuffer; - vertex_t* vCache; - uint32_t sequence; - void* base; - uint32_t total; - uint32_t misses; - int64_t startTime; - void init(); - void uninit(); - void clear(); - void dump_stats(GLenum mode); -}; - -// ---------------------------------------------------------------------------- -// fog -// ---------------------------------------------------------------------------- - -struct fog_t { - GLfixed density; - GLfixed start; - GLfixed end; - GLfixed invEndMinusStart; - GLenum mode; - GLfixed (*fog)(ogles_context_t* c, GLfixed z); -}; - -// ---------------------------------------------------------------------------- -// user clip planes -// ---------------------------------------------------------------------------- - -const unsigned int OGLES_MAX_CLIP_PLANES = 6; - -struct clip_plane_t { - vec4_t equation; -}; - -struct user_clip_planes_t { - clip_plane_t plane[OGLES_MAX_CLIP_PLANES]; - uint32_t enable; -}; - -// ---------------------------------------------------------------------------- -// lighting -// ---------------------------------------------------------------------------- - -const unsigned int OGLES_MAX_LIGHTS = 8; - -struct light_t { - vec4_t ambient; - vec4_t diffuse; - vec4_t specular; - vec4_t implicitAmbient; - vec4_t implicitDiffuse; - vec4_t implicitSpecular; - vec4_t position; // position in eye space - vec4_t objPosition; - vec4_t normalizedObjPosition; - vec4_t spotDir; - vec4_t normalizedSpotDir; - GLfixed spotExp; - GLfixed spotCutoff; - GLfixed spotCutoffCosine; - GLfixed attenuation[3]; - GLfixed rConstAttenuation; - GLboolean enable; -}; - -struct material_t { - vec4_t ambient; - vec4_t diffuse; - vec4_t specular; - vec4_t emission; - GLfixed shininess; -}; - -struct light_model_t { - vec4_t ambient; - GLboolean twoSide; -}; - -struct color_material_t { - GLenum face; - GLenum mode; - GLboolean enable; -}; - -struct lighting_t { - light_t lights[OGLES_MAX_LIGHTS]; - material_t front; - light_model_t lightModel; - color_material_t colorMaterial; - vec4_t implicitSceneEmissionAndAmbient; - vec4_t objViewer; - uint32_t enabledLights; - GLboolean enable; - GLenum shadeModel; - typedef void (*light_fct_t)(ogles_context_t*, vertex_t*); - void (*lightVertex)(ogles_context_t* c, vertex_t* v); - void (*lightTriangle)(ogles_context_t* c, - vertex_t* v0, vertex_t* v1, vertex_t* v2); -}; - -struct culling_t { - GLenum cullFace; - GLenum frontFace; - GLboolean enable; -}; - -// ---------------------------------------------------------------------------- -// textures -// ---------------------------------------------------------------------------- - -struct texture_unit_t { - GLuint name; - EGLTextureObject* texture; - uint8_t dirty; -}; - -struct texture_state_t -{ - texture_unit_t tmu[GGL_TEXTURE_UNIT_COUNT]; - int active; // active tmu - EGLTextureObject* defaultTexture; - GGLContext* ggl; - uint8_t packAlignment; - uint8_t unpackAlignment; -}; - -// ---------------------------------------------------------------------------- -// transformation and matrices -// ---------------------------------------------------------------------------- - -struct matrixf_t; - -struct matrixx_t { - GLfixed m[16]; - void load(const matrixf_t& rhs); -}; - -struct matrix_stack_t; - - -struct matrixf_t { - void loadIdentity(); - void load(const matrixf_t& rhs); - - inline GLfloat* editElements() { return m; } - inline GLfloat const* elements() const { return m; } - - void set(const GLfixed* rhs); - void set(const GLfloat* rhs); - - static void multiply(matrixf_t& r, - const matrixf_t& lhs, const matrixf_t& rhs); - - void dump(const char* what); - -private: - friend struct matrix_stack_t; - GLfloat m[16]; - void load(const GLfixed* rhs); - void load(const GLfloat* rhs); - void multiply(const matrixf_t& rhs); - void translate(GLfloat x, GLfloat y, GLfloat z); - void scale(GLfloat x, GLfloat y, GLfloat z); - void rotate(GLfloat a, GLfloat x, GLfloat y, GLfloat z); -}; - -enum { - OP_IDENTITY = 0x00, - OP_TRANSLATE = 0x01, - OP_UNIFORM_SCALE = 0x02, - OP_SCALE = 0x05, - OP_ROTATE = 0x08, - OP_SKEW = 0x10, - OP_ALL = 0x1F -}; - -struct transform_t { - enum { - FLAGS_2D_PROJECTION = 0x1 - }; - matrixx_t matrix; - uint32_t flags; - uint32_t ops; - - union { - struct { - void (*point2)(transform_t const* t, vec4_t*, vec4_t const*); - void (*point3)(transform_t const* t, vec4_t*, vec4_t const*); - void (*point4)(transform_t const* t, vec4_t*, vec4_t const*); - }; - void (*pointv[3])(transform_t const* t, vec4_t*, vec4_t const*); - }; - - void loadIdentity(); - void picker(); - void dump(const char* what); -}; - -struct mvui_transform_t : public transform_t -{ - void picker(); -}; - -struct matrix_stack_t { - enum { - DO_PICKER = 0x1, - DO_FLOAT_TO_FIXED = 0x2 - }; - transform_t transform; - uint8_t maxDepth; - uint8_t depth; - uint8_t dirty; - uint8_t reserved; - matrixf_t *stack; - uint8_t *ops; - void init(int depth); - void uninit(); - void loadIdentity(); - void load(const GLfixed* rhs); - void load(const GLfloat* rhs); - void multiply(const matrixf_t& rhs); - void translate(GLfloat x, GLfloat y, GLfloat z); - void scale(GLfloat x, GLfloat y, GLfloat z); - void rotate(GLfloat a, GLfloat x, GLfloat y, GLfloat z); - GLint push(); - GLint pop(); - void validate(); - matrixf_t& top() { return stack[depth]; } - const matrixf_t& top() const { return stack[depth]; } - uint32_t top_ops() const { return ops[depth]; } - inline bool isRigidBody() const { - return !(ops[depth] & ~(OP_TRANSLATE|OP_UNIFORM_SCALE|OP_ROTATE)); - } -}; - -struct vp_transform_t { - transform_t transform; - matrixf_t matrix; - GLfloat zNear; - GLfloat zFar; - void loadIdentity(); -}; - -struct transform_state_t { - enum { - MODELVIEW = 0x01, - PROJECTION = 0x02, - VIEWPORT = 0x04, - TEXTURE = 0x08, - MVUI = 0x10, - MVIT = 0x20, - MVP = 0x40, - }; - matrix_stack_t *current; - matrix_stack_t modelview; - matrix_stack_t projection; - matrix_stack_t texture[GGL_TEXTURE_UNIT_COUNT]; - - // modelview * projection - transform_t mvp __attribute__((aligned(32))); - // viewport transformation - vp_transform_t vpt __attribute__((aligned(32))); - // same for 4-D vertices - transform_t mvp4; - // full modelview inverse transpose - transform_t mvit4; - // upper 3x3 of mv-inverse-transpose (for normals) - mvui_transform_t mvui; - - GLenum matrixMode; - GLenum rescaleNormals; - uint32_t dirty; - void invalidate(); - void update_mvp(); - void update_mvit(); - void update_mvui(); -}; - -struct viewport_t { - GLint x; - GLint y; - GLsizei w; - GLsizei h; - struct { - GLint x; - GLint y; - } surfaceport; - struct { - GLint x; - GLint y; - GLsizei w; - GLsizei h; - } scissor; -}; - -// ---------------------------------------------------------------------------- -// Lerping -// ---------------------------------------------------------------------------- - -struct compute_iterators_t -{ - void initTriangle( - vertex_t const* v0, - vertex_t const* v1, - vertex_t const* v2); - - void initLine( - vertex_t const* v0, - vertex_t const* v1); - - inline void initLerp(vertex_t const* v0, uint32_t enables); - - int iteratorsScale(int32_t it[3], - int32_t c0, int32_t c1, int32_t c2) const; - - void iterators1616(GGLfixed it[3], - GGLfixed c0, GGLfixed c1, GGLfixed c2) const; - - void iterators0032(int32_t it[3], - int32_t c0, int32_t c1, int32_t c2) const; - - void iterators0032(int64_t it[3], - int32_t c0, int32_t c1, int32_t c2) const; - - GGLcoord area() const { return m_area; } - -private: - // don't change order of members here -- used by iterators.S - GGLcoord m_dx01, m_dy10, m_dx20, m_dy02; - GGLcoord m_x0, m_y0; - GGLcoord m_area; - uint8_t m_scale; - uint8_t m_area_scale; - uint8_t m_reserved[2]; - -}; - -// ---------------------------------------------------------------------------- -// state -// ---------------------------------------------------------------------------- - -#ifdef HAVE_ANDROID_OS - // We have a dedicated TLS slot in bionic - inline void setGlThreadSpecific(ogles_context_t *value) { - ((uint32_t *)__get_tls())[TLS_SLOT_OPENGL] = (uint32_t)value; - } - inline ogles_context_t* getGlThreadSpecific() { - return (ogles_context_t *)(((unsigned *)__get_tls())[TLS_SLOT_OPENGL]); - } -#else - extern pthread_key_t gGLKey; - inline void setGlThreadSpecific(ogles_context_t *value) { - pthread_setspecific(gGLKey, value); - } - inline ogles_context_t* getGlThreadSpecific() { - return static_cast<ogles_context_t*>(pthread_getspecific(gGLKey)); - } -#endif - - -struct prims_t { - typedef ogles_context_t* GL; - void (*renderPoint)(GL, vertex_t*); - void (*renderLine)(GL, vertex_t*, vertex_t*); - void (*renderTriangle)(GL, vertex_t*, vertex_t*, vertex_t*); -}; - -struct ogles_context_t { - context_t rasterizer; - array_machine_t arrays __attribute__((aligned(32))); - texture_state_t textures; - transform_state_t transforms; - vertex_cache_t vc; - prims_t prims; - culling_t cull; - lighting_t lighting; - user_clip_planes_t clipPlanes; - compute_iterators_t lerp; __attribute__((aligned(32))); - vertex_t current; - vec4_t currentColorClamped; - vec3_t currentNormal; - viewport_t viewport; - point_size_t point; - line_width_t line; - polygon_offset_t polygonOffset; - fog_t fog; - uint32_t perspective : 1; - uint32_t transformTextures : 1; - EGLSurfaceManager* surfaceManager; - EGLBufferObjectManager* bufferObjectManager; - - GLenum error; - - static inline ogles_context_t* get() { - return getGlThreadSpecific(); - } - -}; - -}; // namespace gl -}; // namespace android - -#endif // ANDROID_OPENGLES_CONTEXT_H - diff --git a/include/private/ui/android_natives_priv.h b/include/private/ui/android_natives_priv.h deleted file mode 100644 index 6b9f524..0000000 --- a/include/private/ui/android_natives_priv.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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. - */ - -#include <ui/android_native_buffer.h> diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp index 64cc919..86d65db 100644 --- a/media/libmedia/IMediaPlayer.cpp +++ b/media/libmedia/IMediaPlayer.cpp @@ -23,8 +23,6 @@ #include <media/IMediaPlayer.h> #include <media/IStreamSource.h> -#include <surfaceflinger/ISurface.h> -#include <surfaceflinger/Surface.h> #include <gui/ISurfaceTexture.h> #include <utils/String8.h> diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp index 42f55c2..2f4e31a 100644 --- a/media/libmedia/IMediaRecorder.cpp +++ b/media/libmedia/IMediaRecorder.cpp @@ -19,10 +19,10 @@ #define LOG_TAG "IMediaRecorder" #include <utils/Log.h> #include <binder/Parcel.h> -#include <surfaceflinger/Surface.h> #include <camera/ICamera.h> #include <media/IMediaRecorderClient.h> #include <media/IMediaRecorder.h> +#include <gui/Surface.h> #include <gui/ISurfaceTexture.h> #include <unistd.h> diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp index 27c7e03..48e427a 100644 --- a/media/libmedia/IOMX.cpp +++ b/media/libmedia/IOMX.cpp @@ -22,8 +22,6 @@ #include <binder/Parcel.h> #include <media/IOMX.h> #include <media/stagefright/foundation/ADebug.h> -#include <surfaceflinger/ISurface.h> -#include <surfaceflinger/Surface.h> namespace android { diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 250425b..9d45907 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -32,8 +32,6 @@ #include <media/mediaplayer.h> #include <media/AudioSystem.h> -#include <surfaceflinger/Surface.h> - #include <binder/MemoryBase.h> #include <utils/KeyedVector.h> diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index 8d947d8..cc73014 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -18,7 +18,6 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "MediaRecorder" #include <utils/Log.h> -#include <surfaceflinger/Surface.h> #include <media/mediarecorder.h> #include <binder/IServiceManager.h> #include <utils/String8.h> diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index c5f4f86..ca79657 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -40,7 +40,7 @@ #include <media/MediaProfiles.h> #include <camera/ICamera.h> #include <camera/CameraParameters.h> -#include <surfaceflinger/Surface.h> +#include <gui/Surface.h> #include <utils/Errors.h> #include <sys/types.h> diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index b731d0f..e618f67 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -38,7 +38,6 @@ #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaErrors.h> #include <media/stagefright/MetaData.h> -#include <surfaceflinger/Surface.h> #include <gui/ISurfaceTexture.h> #include "avc_utils.h" @@ -387,10 +386,10 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { audio ? "audio" : "video"); mRenderer->queueEOS(audio, UNKNOWN_ERROR); - } else { - CHECK_EQ((int)what, (int)ACodec::kWhatDrainThisBuffer); - + } else if (what == ACodec::kWhatDrainThisBuffer) { renderBuffer(audio, codecRequest); + } else { + ALOGV("Unhandled codec notification %d.", what); } break; @@ -768,7 +767,7 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) { mediaTimeUs / 1E6); #endif - reply->setObject("buffer", accessUnit); + reply->setBuffer("buffer", accessUnit); reply->post(); return OK; @@ -793,10 +792,8 @@ void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) { return; } - sp<RefBase> obj; - CHECK(msg->findObject("buffer", &obj)); - - sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); + sp<ABuffer> buffer; + CHECK(msg->findBuffer("buffer", &buffer)); int64_t &skipUntilMediaTimeUs = audio diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h index ffc710e..6be14be 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h @@ -21,8 +21,6 @@ #include <media/MediaPlayerInterface.h> #include <media/stagefright/foundation/AHandler.h> #include <media/stagefright/NativeWindowWrapper.h> -#include <gui/SurfaceTextureClient.h> -#include <surfaceflinger/Surface.h> namespace android { diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp index 56c2773..460fc98 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp @@ -29,8 +29,6 @@ #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MetaData.h> #include <media/stagefright/Utils.h> -#include <surfaceflinger/Surface.h> -#include <gui/ISurfaceTexture.h> namespace android { @@ -214,8 +212,6 @@ sp<AMessage> NuPlayer::Decoder::makeFormat(const sp<MetaData> &meta) { buffer->meta()->setInt32("csd", true); mCSD.push(buffer); - - msg->setObject("csd", buffer); } else if (meta->findData(kKeyESDS, &type, &data, &size)) { ESDS esds((const char *)data, size); CHECK_EQ(esds.InitCheck(), (status_t)OK); @@ -242,9 +238,8 @@ void NuPlayer::Decoder::onFillThisBuffer(const sp<AMessage> &msg) { CHECK(msg->findMessage("reply", &reply)); #if 0 - sp<RefBase> obj; - CHECK(msg->findObject("buffer", &obj)); - sp<ABuffer> outBuffer = static_cast<ABuffer *>(obj.get()); + sp<ABuffer> outBuffer; + CHECK(msg->findBuffer("buffer", &outBuffer)); #else sp<ABuffer> outBuffer; #endif @@ -253,7 +248,7 @@ void NuPlayer::Decoder::onFillThisBuffer(const sp<AMessage> &msg) { outBuffer = mCSD.editItemAt(mCSDIndex++); outBuffer->meta()->setInt64("timeUs", 0); - reply->setObject("buffer", outBuffer); + reply->setBuffer("buffer", outBuffer); reply->post(); return; } diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp index 15259cb..5738ecb 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp @@ -60,7 +60,7 @@ void NuPlayer::Renderer::queueBuffer( const sp<AMessage> ¬ifyConsumed) { sp<AMessage> msg = new AMessage(kWhatQueueBuffer, id()); msg->setInt32("audio", static_cast<int32_t>(audio)); - msg->setObject("buffer", buffer); + msg->setBuffer("buffer", buffer); msg->setMessage("notifyConsumed", notifyConsumed); msg->post(); } @@ -411,9 +411,8 @@ void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) { return; } - sp<RefBase> obj; - CHECK(msg->findObject("buffer", &obj)); - sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); + sp<ABuffer> buffer; + CHECK(msg->findBuffer("buffer", &buffer)); sp<AMessage> notifyConsumed; CHECK(msg->findMessage("notifyConsumed", ¬ifyConsumed)); diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp index 6eb0d07..4c65b65 100644 --- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp +++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp @@ -218,10 +218,8 @@ void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) { CHECK(msg->findSize("trackIndex", &trackIndex)); CHECK_LT(trackIndex, mTracks.size()); - sp<RefBase> obj; - CHECK(msg->findObject("accessUnit", &obj)); - - sp<ABuffer> accessUnit = static_cast<ABuffer *>(obj.get()); + sp<ABuffer> accessUnit; + CHECK(msg->findBuffer("accessUnit", &accessUnit)); int32_t damaged; if (accessUnit->meta()->findInt32("damaged", &damaged) diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index ca44ea3..85bd7ba 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -31,9 +31,6 @@ #include <media/stagefright/OMXClient.h> #include <media/stagefright/OMXCodec.h> -#include <surfaceflinger/Surface.h> -#include <gui/SurfaceTextureClient.h> - #include <OMX_Component.h> namespace android { @@ -171,6 +168,9 @@ protected: private: void onSetup(const sp<AMessage> &msg); + void onAllocateComponent(const sp<AMessage> &msg); + void onConfigureComponent(const sp<AMessage> &msg); + void onStart(); DISALLOW_EVIL_CONSTRUCTORS(UninitializedState); }; @@ -265,6 +265,8 @@ protected: private: void changeStateIfWeOwnAllBuffers(); + bool mComponentNowIdle; + DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState); }; @@ -309,7 +311,8 @@ private: ACodec::ACodec() : mNode(NULL), - mSentFormat(false) { + mSentFormat(false), + mIsEncoder(false) { mUninitializedState = new UninitializedState(this); mLoadedToIdleState = new LoadedToIdleState(this); mIdleToExecutingState = new IdleToExecutingState(this); @@ -341,6 +344,22 @@ void ACodec::initiateSetup(const sp<AMessage> &msg) { msg->post(); } +void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) { + msg->setWhat(kWhatAllocateComponent); + msg->setTarget(id()); + msg->post(); +} + +void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) { + msg->setWhat(kWhatConfigureComponent); + msg->setTarget(id()); + msg->post(); +} + +void ACodec::initiateStart() { + (new AMessage(kWhatStart, id()))->post(); +} + void ACodec::signalFlush() { ALOGV("[%s] signalFlush", mComponentName.c_str()); (new AMessage(kWhatFlush, id()))->post(); @@ -360,62 +379,75 @@ status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { CHECK(mDealer[portIndex] == NULL); CHECK(mBuffers[portIndex].isEmpty()); + status_t err; if (mNativeWindow != NULL && portIndex == kPortIndexOutput) { - return allocateOutputBuffersFromNativeWindow(); - } + err = allocateOutputBuffersFromNativeWindow(); + } else { + OMX_PARAM_PORTDEFINITIONTYPE def; + InitOMXParams(&def); + def.nPortIndex = portIndex; - OMX_PARAM_PORTDEFINITIONTYPE def; - InitOMXParams(&def); - def.nPortIndex = portIndex; + err = mOMX->getParameter( + mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); - status_t err = mOMX->getParameter( - mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); + if (err == OK) { + ALOGV("[%s] Allocating %lu buffers of size %lu on %s port", + mComponentName.c_str(), + def.nBufferCountActual, def.nBufferSize, + portIndex == kPortIndexInput ? "input" : "output"); - if (err != OK) { - return err; - } + size_t totalSize = def.nBufferCountActual * def.nBufferSize; + mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec"); - ALOGV("[%s] Allocating %lu buffers of size %lu on %s port", - mComponentName.c_str(), - def.nBufferCountActual, def.nBufferSize, - portIndex == kPortIndexInput ? "input" : "output"); + for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) { + sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize); + CHECK(mem.get() != NULL); - size_t totalSize = def.nBufferCountActual * def.nBufferSize; - mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec"); + IOMX::buffer_id buffer; - for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) { - sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize); - CHECK(mem.get() != NULL); + if (!strncasecmp( + mComponentName.c_str(), "OMX.TI.DUCATI1.VIDEO.", 21)) { + if (portIndex == kPortIndexInput && i == 0) { + // Only log this warning once per allocation round. - IOMX::buffer_id buffer; + ALOGW("OMX.TI.DUCATI1.VIDEO.* require the use of " + "OMX_AllocateBuffer instead of the preferred " + "OMX_UseBuffer. Vendor must fix this."); + } - if (!strcasecmp( - mComponentName.c_str(), "OMX.TI.DUCATI1.VIDEO.DECODER")) { - if (portIndex == kPortIndexInput && i == 0) { - // Only log this warning once per allocation round. + err = mOMX->allocateBufferWithBackup( + mNode, portIndex, mem, &buffer); + } else { + err = mOMX->useBuffer(mNode, portIndex, mem, &buffer); + } - ALOGW("OMX.TI.DUCATI1.VIDEO.DECODER requires the use of " - "OMX_AllocateBuffer instead of the preferred " - "OMX_UseBuffer. Vendor must fix this."); + BufferInfo info; + info.mBufferID = buffer; + info.mStatus = BufferInfo::OWNED_BY_US; + info.mData = new ABuffer(mem->pointer(), def.nBufferSize); + mBuffers[portIndex].push(info); } - - err = mOMX->allocateBufferWithBackup( - mNode, portIndex, mem, &buffer); - } else { - err = mOMX->useBuffer(mNode, portIndex, mem, &buffer); } + } - if (err != OK) { - return err; - } + if (err != OK) { + return err; + } - BufferInfo info; - info.mBufferID = buffer; - info.mStatus = BufferInfo::OWNED_BY_US; - info.mData = new ABuffer(mem->pointer(), def.nBufferSize); - mBuffers[portIndex].push(info); + sp<AMessage> notify = mNotify->dup(); + notify->setInt32("what", ACodec::kWhatBuffersAllocated); + + notify->setInt32("portIndex", portIndex); + for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { + AString name = StringPrintf("buffer-id_%d", i); + notify->setPointer(name.c_str(), mBuffers[portIndex][i].mBufferID); + + name = StringPrintf("data_%d", i); + notify->setBuffer(name.c_str(), mBuffers[portIndex][i].mData); } + notify->post(); + return OK; } @@ -671,7 +703,7 @@ ACodec::BufferInfo *ACodec::findBufferByID( return NULL; } -void ACodec::setComponentRole( +status_t ACodec::setComponentRole( bool isEncoder, const char *mime) { struct MimeToRole { const char *mime; @@ -700,6 +732,8 @@ void ACodec::setComponentRole( "video_decoder.mpeg4", "video_encoder.mpeg4" }, { MEDIA_MIMETYPE_VIDEO_H263, "video_decoder.h263", "video_encoder.h263" }, + { MEDIA_MIMETYPE_VIDEO_VPX, + "video_decoder.vpx", "video_encoder.vpx" }, }; static const size_t kNumMimeToRole = @@ -713,7 +747,7 @@ void ACodec::setComponentRole( } if (i == kNumMimeToRole) { - return; + return ERROR_UNSUPPORTED; } const char *role = @@ -736,50 +770,83 @@ void ACodec::setComponentRole( if (err != OK) { ALOGW("[%s] Failed to set standard component role '%s'.", mComponentName.c_str(), role); + + return err; } } + + return OK; } -void ACodec::configureCodec( +status_t ACodec::configureCodec( const char *mime, const sp<AMessage> &msg) { - setComponentRole(false /* isEncoder */, mime); + int32_t encoder; + if (!msg->findInt32("encoder", &encoder)) { + encoder = false; + } - if (!strncasecmp(mime, "video/", 6)) { - int32_t width, height; - CHECK(msg->findInt32("width", &width)); - CHECK(msg->findInt32("height", &height)); + mIsEncoder = encoder; - CHECK_EQ(setupVideoDecoder(mime, width, height), - (status_t)OK); + status_t err = setComponentRole(encoder /* isEncoder */, mime); + + if (err != OK) { + return err; + } + + int32_t bitRate = 0; + if (encoder && !msg->findInt32("bitrate", &bitRate)) { + return INVALID_OPERATION; + } + + if (!strncasecmp(mime, "video/", 6)) { + if (encoder) { + err = setupVideoEncoder(mime, msg); + } else { + int32_t width, height; + if (!msg->findInt32("width", &width) + || !msg->findInt32("height", &height)) { + err = INVALID_OPERATION; + } else { + err = setupVideoDecoder(mime, width, height); + } + } } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { int32_t numChannels, sampleRate; - CHECK(msg->findInt32("channel-count", &numChannels)); - CHECK(msg->findInt32("sample-rate", &sampleRate)); - - CHECK_EQ(setupAACDecoder(numChannels, sampleRate), (status_t)OK); + if (!msg->findInt32("channel-count", &numChannels) + || !msg->findInt32("sample-rate", &sampleRate)) { + err = INVALID_OPERATION; + } else { + err = setupAACCodec(encoder, numChannels, sampleRate, bitRate); + } } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) { - CHECK_EQ(setupAMRDecoder(false /* isWAMR */), (status_t)OK); + err = setupAMRCodec(encoder, false /* isWAMR */, bitRate); } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { - CHECK_EQ(setupAMRDecoder(true /* isWAMR */), (status_t)OK); + err = setupAMRCodec(encoder, true /* isWAMR */, bitRate); } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW) || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) { // These are PCM-like formats with a fixed sample rate but // a variable number of channels. int32_t numChannels; - CHECK(msg->findInt32("channel-count", &numChannels)); + if (!msg->findInt32("channel-count", &numChannels)) { + err = INVALID_OPERATION; + } else { + err = setupG711Codec(encoder, numChannels); + } + } - CHECK_EQ(setupG711Decoder(numChannels), (status_t)OK); + if (err != OK) { + return err; } int32_t maxInputSize; if (msg->findInt32("max-input-size", &maxInputSize)) { - CHECK_EQ(setMinBufferSize(kPortIndexInput, (size_t)maxInputSize), - (status_t)OK); + err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize); } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) { - CHECK_EQ(setMinBufferSize(kPortIndexInput, 8192), // XXX - (status_t)OK); + err = setMinBufferSize(kPortIndexInput, 8192); // XXX } + + return err; } status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) { @@ -819,12 +886,113 @@ status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) { return OK; } -status_t ACodec::setupAACDecoder(int32_t numChannels, int32_t sampleRate) { +status_t ACodec::selectAudioPortFormat( + OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) { + OMX_AUDIO_PARAM_PORTFORMATTYPE format; + InitOMXParams(&format); + + format.nPortIndex = portIndex; + for (OMX_U32 index = 0;; ++index) { + format.nIndex = index; + + status_t err = mOMX->getParameter( + mNode, OMX_IndexParamAudioPortFormat, + &format, sizeof(format)); + + if (err != OK) { + return err; + } + + if (format.eEncoding == desiredFormat) { + break; + } + } + + return mOMX->setParameter( + mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format)); +} + +status_t ACodec::setupAACCodec( + bool encoder, + int32_t numChannels, int32_t sampleRate, int32_t bitRate) { + status_t err = setupRawAudioFormat( + encoder ? kPortIndexInput : kPortIndexOutput, + sampleRate, + numChannels); + + if (err != OK) { + return err; + } + + if (encoder) { + err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC); + + if (err != OK) { + return err; + } + + OMX_PARAM_PORTDEFINITIONTYPE def; + InitOMXParams(&def); + def.nPortIndex = kPortIndexOutput; + + err = mOMX->getParameter( + mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); + + if (err != OK) { + return err; + } + + def.format.audio.bFlagErrorConcealment = OMX_TRUE; + def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; + + err = mOMX->setParameter( + mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); + + if (err != OK) { + return err; + } + + OMX_AUDIO_PARAM_AACPROFILETYPE profile; + InitOMXParams(&profile); + profile.nPortIndex = kPortIndexOutput; + + err = mOMX->getParameter( + mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); + + if (err != OK) { + return err; + } + + profile.nChannels = numChannels; + + profile.eChannelMode = + (numChannels == 1) + ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo; + + profile.nSampleRate = sampleRate; + profile.nBitRate = bitRate; + profile.nAudioBandWidth = 0; + profile.nFrameLength = 0; + profile.nAACtools = OMX_AUDIO_AACToolAll; + profile.nAACERtools = OMX_AUDIO_AACERNone; + profile.eAACProfile = OMX_AUDIO_AACObjectLC; + profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; + + err = mOMX->setParameter( + mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); + + if (err != OK) { + return err; + } + + return err; + } + OMX_AUDIO_PARAM_AACPROFILETYPE profile; InitOMXParams(&profile); profile.nPortIndex = kPortIndexInput; - status_t err = mOMX->getParameter( + err = mOMX->getParameter( mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); if (err != OK) { @@ -835,16 +1003,59 @@ status_t ACodec::setupAACDecoder(int32_t numChannels, int32_t sampleRate) { profile.nSampleRate = sampleRate; profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS; - err = mOMX->setParameter( + return mOMX->setParameter( mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); +} - return err; +static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate( + bool isAMRWB, int32_t bps) { + if (isAMRWB) { + if (bps <= 6600) { + return OMX_AUDIO_AMRBandModeWB0; + } else if (bps <= 8850) { + return OMX_AUDIO_AMRBandModeWB1; + } else if (bps <= 12650) { + return OMX_AUDIO_AMRBandModeWB2; + } else if (bps <= 14250) { + return OMX_AUDIO_AMRBandModeWB3; + } else if (bps <= 15850) { + return OMX_AUDIO_AMRBandModeWB4; + } else if (bps <= 18250) { + return OMX_AUDIO_AMRBandModeWB5; + } else if (bps <= 19850) { + return OMX_AUDIO_AMRBandModeWB6; + } else if (bps <= 23050) { + return OMX_AUDIO_AMRBandModeWB7; + } + + // 23850 bps + return OMX_AUDIO_AMRBandModeWB8; + } else { // AMRNB + if (bps <= 4750) { + return OMX_AUDIO_AMRBandModeNB0; + } else if (bps <= 5150) { + return OMX_AUDIO_AMRBandModeNB1; + } else if (bps <= 5900) { + return OMX_AUDIO_AMRBandModeNB2; + } else if (bps <= 6700) { + return OMX_AUDIO_AMRBandModeNB3; + } else if (bps <= 7400) { + return OMX_AUDIO_AMRBandModeNB4; + } else if (bps <= 7950) { + return OMX_AUDIO_AMRBandModeNB5; + } else if (bps <= 10200) { + return OMX_AUDIO_AMRBandModeNB6; + } + + // 12200 bps + return OMX_AUDIO_AMRBandModeNB7; + } } -status_t ACodec::setupAMRDecoder(bool isWAMR) { +status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) { OMX_AUDIO_PARAM_AMRTYPE def; InitOMXParams(&def); - def.nPortIndex = kPortIndexInput; + def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput; status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); @@ -854,14 +1065,24 @@ status_t ACodec::setupAMRDecoder(bool isWAMR) { } def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; + def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate); + + err = mOMX->setParameter( + mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); - def.eAMRBandMode = - isWAMR ? OMX_AUDIO_AMRBandModeWB0 : OMX_AUDIO_AMRBandModeNB0; + if (err != OK) { + return err; + } - return mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); + return setupRawAudioFormat( + encoder ? kPortIndexInput : kPortIndexOutput, + isWAMR ? 16000 : 8000 /* sampleRate */, + 1 /* numChannels */); } -status_t ACodec::setupG711Decoder(int32_t numChannels) { +status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) { + CHECK(!encoder); // XXX TODO + return setupRawAudioFormat( kPortIndexInput, 8000 /* sampleRate */, numChannels); } @@ -1001,22 +1222,36 @@ status_t ACodec::setSupportedOutputFormat() { &format, sizeof(format)); } -status_t ACodec::setupVideoDecoder( - const char *mime, int32_t width, int32_t height) { - OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused; +static status_t GetVideoCodingTypeFromMime( + const char *mime, OMX_VIDEO_CODINGTYPE *codingType) { if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { - compressionFormat = OMX_VIDEO_CodingAVC; + *codingType = OMX_VIDEO_CodingAVC; } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { - compressionFormat = OMX_VIDEO_CodingMPEG4; + *codingType = OMX_VIDEO_CodingMPEG4; } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { - compressionFormat = OMX_VIDEO_CodingH263; + *codingType = OMX_VIDEO_CodingH263; } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) { - compressionFormat = OMX_VIDEO_CodingMPEG2; + *codingType = OMX_VIDEO_CodingMPEG2; + } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) { + *codingType = OMX_VIDEO_CodingVPX; } else { - TRESPASS(); + *codingType = OMX_VIDEO_CodingUnused; + return ERROR_UNSUPPORTED; } - status_t err = setVideoPortFormatType( + return OK; +} + +status_t ACodec::setupVideoDecoder( + const char *mime, int32_t width, int32_t height) { + OMX_VIDEO_CODINGTYPE compressionFormat; + status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat); + + if (err != OK) { + return err; + } + + err = setVideoPortFormatType( kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); if (err != OK) { @@ -1046,6 +1281,489 @@ status_t ACodec::setupVideoDecoder( return OK; } +status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) { + int32_t tmp; + if (!msg->findInt32("color-format", &tmp)) { + return INVALID_OPERATION; + } + + OMX_COLOR_FORMATTYPE colorFormat = + static_cast<OMX_COLOR_FORMATTYPE>(tmp); + + status_t err = setVideoPortFormatType( + kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat); + + if (err != OK) { + ALOGE("[%s] does not support color format %d", + mComponentName.c_str(), colorFormat); + + return err; + } + + /* Input port configuration */ + + OMX_PARAM_PORTDEFINITIONTYPE def; + InitOMXParams(&def); + + OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; + + def.nPortIndex = kPortIndexInput; + + err = mOMX->getParameter( + mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); + + if (err != OK) { + return err; + } + + int32_t width, height, bitrate; + if (!msg->findInt32("width", &width) + || !msg->findInt32("height", &height) + || !msg->findInt32("bitrate", &bitrate)) { + return INVALID_OPERATION; + } + + video_def->nFrameWidth = width; + video_def->nFrameHeight = height; + + int32_t stride; + if (!msg->findInt32("stride", &stride)) { + stride = width; + } + + video_def->nStride = stride; + + int32_t sliceHeight; + if (!msg->findInt32("slice-height", &sliceHeight)) { + sliceHeight = height; + } + + video_def->nSliceHeight = sliceHeight; + + def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2; + + float frameRate; + if (!msg->findFloat("frame-rate", &frameRate)) { + int32_t tmp; + if (!msg->findInt32("frame-rate", &tmp)) { + return INVALID_OPERATION; + } + frameRate = (float)tmp; + } + + video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); + video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; + video_def->eColorFormat = colorFormat; + + err = mOMX->setParameter( + mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); + + if (err != OK) { + ALOGE("[%s] failed to set input port definition parameters.", + mComponentName.c_str()); + + return err; + } + + /* Output port configuration */ + + OMX_VIDEO_CODINGTYPE compressionFormat; + err = GetVideoCodingTypeFromMime(mime, &compressionFormat); + + if (err != OK) { + return err; + } + + err = setVideoPortFormatType( + kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused); + + if (err != OK) { + ALOGE("[%s] does not support compression format %d", + mComponentName.c_str(), compressionFormat); + + return err; + } + + def.nPortIndex = kPortIndexOutput; + + err = mOMX->getParameter( + mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); + + if (err != OK) { + return err; + } + + video_def->nFrameWidth = width; + video_def->nFrameHeight = height; + video_def->xFramerate = 0; + video_def->nBitrate = bitrate; + video_def->eCompressionFormat = compressionFormat; + video_def->eColorFormat = OMX_COLOR_FormatUnused; + + err = mOMX->setParameter( + mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); + + if (err != OK) { + ALOGE("[%s] failed to set output port definition parameters.", + mComponentName.c_str()); + + return err; + } + + switch (compressionFormat) { + case OMX_VIDEO_CodingMPEG4: + err = setupMPEG4EncoderParameters(msg); + break; + + case OMX_VIDEO_CodingH263: + err = setupH263EncoderParameters(msg); + break; + + case OMX_VIDEO_CodingAVC: + err = setupAVCEncoderParameters(msg); + break; + + default: + break; + } + + ALOGI("setupVideoEncoder succeeded"); + + return err; +} + +static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) { + if (iFramesInterval < 0) { + return 0xFFFFFFFF; + } else if (iFramesInterval == 0) { + return 0; + } + OMX_U32 ret = frameRate * iFramesInterval; + CHECK(ret > 1); + return ret; +} + +status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) { + int32_t bitrate, iFrameInterval; + if (!msg->findInt32("bitrate", &bitrate) + || !msg->findInt32("i-frame-interval", &iFrameInterval)) { + return INVALID_OPERATION; + } + + float frameRate; + if (!msg->findFloat("frame-rate", &frameRate)) { + int32_t tmp; + if (!msg->findInt32("frame-rate", &tmp)) { + return INVALID_OPERATION; + } + frameRate = (float)tmp; + } + + OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type; + InitOMXParams(&mpeg4type); + mpeg4type.nPortIndex = kPortIndexOutput; + + status_t err = mOMX->getParameter( + mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); + + if (err != OK) { + return err; + } + + mpeg4type.nSliceHeaderSpacing = 0; + mpeg4type.bSVH = OMX_FALSE; + mpeg4type.bGov = OMX_FALSE; + + mpeg4type.nAllowedPictureTypes = + OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; + + mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); + if (mpeg4type.nPFrames == 0) { + mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; + } + mpeg4type.nBFrames = 0; + mpeg4type.nIDCVLCThreshold = 0; + mpeg4type.bACPred = OMX_TRUE; + mpeg4type.nMaxPacketSize = 256; + mpeg4type.nTimeIncRes = 1000; + mpeg4type.nHeaderExtension = 0; + mpeg4type.bReversibleVLC = OMX_FALSE; + + int32_t profile; + if (msg->findInt32("profile", &profile)) { + int32_t level; + if (!msg->findInt32("level", &level)) { + return INVALID_OPERATION; + } + + err = verifySupportForProfileAndLevel(profile, level); + + if (err != OK) { + return err; + } + + mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile); + mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level); + } + + err = mOMX->setParameter( + mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); + + if (err != OK) { + return err; + } + + err = configureBitrate(bitrate); + + if (err != OK) { + return err; + } + + return setupErrorCorrectionParameters(); +} + +status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) { + int32_t bitrate, iFrameInterval; + if (!msg->findInt32("bitrate", &bitrate) + || !msg->findInt32("i-frame-interval", &iFrameInterval)) { + return INVALID_OPERATION; + } + + float frameRate; + if (!msg->findFloat("frame-rate", &frameRate)) { + int32_t tmp; + if (!msg->findInt32("frame-rate", &tmp)) { + return INVALID_OPERATION; + } + frameRate = (float)tmp; + } + + OMX_VIDEO_PARAM_H263TYPE h263type; + InitOMXParams(&h263type); + h263type.nPortIndex = kPortIndexOutput; + + status_t err = mOMX->getParameter( + mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); + + if (err != OK) { + return err; + } + + h263type.nAllowedPictureTypes = + OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; + + h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); + if (h263type.nPFrames == 0) { + h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; + } + h263type.nBFrames = 0; + + int32_t profile; + if (msg->findInt32("profile", &profile)) { + int32_t level; + if (!msg->findInt32("level", &level)) { + return INVALID_OPERATION; + } + + err = verifySupportForProfileAndLevel(profile, level); + + if (err != OK) { + return err; + } + + h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile); + h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level); + } + + h263type.bPLUSPTYPEAllowed = OMX_FALSE; + h263type.bForceRoundingTypeToZero = OMX_FALSE; + h263type.nPictureHeaderRepetition = 0; + h263type.nGOBHeaderInterval = 0; + + err = mOMX->setParameter( + mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); + + if (err != OK) { + return err; + } + + err = configureBitrate(bitrate); + + if (err != OK) { + return err; + } + + return setupErrorCorrectionParameters(); +} + +status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) { + int32_t bitrate, iFrameInterval; + if (!msg->findInt32("bitrate", &bitrate) + || !msg->findInt32("i-frame-interval", &iFrameInterval)) { + return INVALID_OPERATION; + } + + float frameRate; + if (!msg->findFloat("frame-rate", &frameRate)) { + int32_t tmp; + if (!msg->findInt32("frame-rate", &tmp)) { + return INVALID_OPERATION; + } + frameRate = (float)tmp; + } + + OMX_VIDEO_PARAM_AVCTYPE h264type; + InitOMXParams(&h264type); + h264type.nPortIndex = kPortIndexOutput; + + status_t err = mOMX->getParameter( + mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); + + if (err != OK) { + return err; + } + + h264type.nAllowedPictureTypes = + OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; + + int32_t profile; + if (msg->findInt32("profile", &profile)) { + int32_t level; + if (!msg->findInt32("level", &level)) { + return INVALID_OPERATION; + } + + err = verifySupportForProfileAndLevel(profile, level); + + if (err != OK) { + return err; + } + + h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile); + h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level); + } + + // XXX + if (!strncmp(mComponentName.c_str(), "OMX.TI.DUCATI1", 14)) { + h264type.eProfile = OMX_VIDEO_AVCProfileBaseline; + } + + if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { + h264type.nSliceHeaderSpacing = 0; + h264type.bUseHadamard = OMX_TRUE; + h264type.nRefFrames = 1; + h264type.nBFrames = 0; + h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); + if (h264type.nPFrames == 0) { + h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; + } + h264type.nRefIdx10ActiveMinus1 = 0; + h264type.nRefIdx11ActiveMinus1 = 0; + h264type.bEntropyCodingCABAC = OMX_FALSE; + h264type.bWeightedPPrediction = OMX_FALSE; + h264type.bconstIpred = OMX_FALSE; + h264type.bDirect8x8Inference = OMX_FALSE; + h264type.bDirectSpatialTemporal = OMX_FALSE; + h264type.nCabacInitIdc = 0; + } + + if (h264type.nBFrames != 0) { + h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; + } + + h264type.bEnableUEP = OMX_FALSE; + h264type.bEnableFMO = OMX_FALSE; + h264type.bEnableASO = OMX_FALSE; + h264type.bEnableRS = OMX_FALSE; + h264type.bFrameMBsOnly = OMX_TRUE; + h264type.bMBAFF = OMX_FALSE; + h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; + + if (!strcasecmp("OMX.Nvidia.h264.encoder", mComponentName.c_str())) { + h264type.eLevel = OMX_VIDEO_AVCLevelMax; + } + + err = mOMX->setParameter( + mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); + + if (err != OK) { + return err; + } + + return configureBitrate(bitrate); +} + +status_t ACodec::verifySupportForProfileAndLevel( + int32_t profile, int32_t level) { + OMX_VIDEO_PARAM_PROFILELEVELTYPE params; + InitOMXParams(¶ms); + params.nPortIndex = kPortIndexOutput; + + for (params.nProfileIndex = 0;; ++params.nProfileIndex) { + status_t err = mOMX->getParameter( + mNode, + OMX_IndexParamVideoProfileLevelQuerySupported, + ¶ms, + sizeof(params)); + + if (err != OK) { + return err; + } + + int32_t supportedProfile = static_cast<int32_t>(params.eProfile); + int32_t supportedLevel = static_cast<int32_t>(params.eLevel); + + if (profile == supportedProfile && level <= supportedLevel) { + return OK; + } + } +} + +status_t ACodec::configureBitrate(int32_t bitrate) { + OMX_VIDEO_PARAM_BITRATETYPE bitrateType; + InitOMXParams(&bitrateType); + bitrateType.nPortIndex = kPortIndexOutput; + + status_t err = mOMX->getParameter( + mNode, OMX_IndexParamVideoBitrate, + &bitrateType, sizeof(bitrateType)); + + if (err != OK) { + return err; + } + + bitrateType.eControlRate = OMX_Video_ControlRateVariable; + bitrateType.nTargetBitrate = bitrate; + + return mOMX->setParameter( + mNode, OMX_IndexParamVideoBitrate, + &bitrateType, sizeof(bitrateType)); +} + +status_t ACodec::setupErrorCorrectionParameters() { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType; + InitOMXParams(&errorCorrectionType); + errorCorrectionType.nPortIndex = kPortIndexOutput; + + status_t err = mOMX->getParameter( + mNode, OMX_IndexParamVideoErrorCorrection, + &errorCorrectionType, sizeof(errorCorrectionType)); + + if (err != OK) { + return OK; // Optional feature. Ignore this failure + } + + errorCorrectionType.bEnableHEC = OMX_FALSE; + errorCorrectionType.bEnableResync = OMX_TRUE; + errorCorrectionType.nResynchMarkerSpacing = 256; + errorCorrectionType.bEnableDataPartitioning = OMX_FALSE; + errorCorrectionType.bEnableRVLC = OMX_FALSE; + + return mOMX->setParameter( + mNode, OMX_IndexParamVideoErrorCorrection, + &errorCorrectionType, sizeof(errorCorrectionType)); +} + status_t ACodec::setVideoFormatOnPort( OMX_U32 portIndex, int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) { @@ -1166,6 +1884,9 @@ void ACodec::sendFormatChange() { notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); notify->setInt32("width", videoDef->nFrameWidth); notify->setInt32("height", videoDef->nFrameHeight); + notify->setInt32("stride", videoDef->nStride); + notify->setInt32("slice-height", videoDef->nSliceHeight); + notify->setInt32("color-format", videoDef->eColorFormat); OMX_CONFIG_RECTTYPE rect; InitOMXParams(&rect); @@ -1241,10 +1962,11 @@ void ACodec::sendFormatChange() { mSentFormat = true; } -void ACodec::signalError(OMX_ERRORTYPE error) { +void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) { sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", ACodec::kWhatError); notify->setInt32("omx-error", error); + notify->setInt32("err", internalError); notify->post(); } @@ -1417,7 +2139,7 @@ void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { notify->setPointer("buffer-id", info->mBufferID); info->mData->meta()->clear(); - notify->setObject("buffer", info->mData); + notify->setBuffer("buffer", info->mData); sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id()); reply->setPointer("buffer-id", info->mBufferID); @@ -1433,18 +2155,26 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { IOMX::buffer_id bufferID; CHECK(msg->findPointer("buffer-id", &bufferID)); - sp<RefBase> obj; + sp<ABuffer> buffer; int32_t err = OK; - if (!msg->findObject("buffer", &obj)) { + bool eos = false; + + if (!msg->findBuffer("buffer", &buffer)) { CHECK(msg->findInt32("err", &err)); ALOGV("[%s] saw error %d instead of an input buffer", mCodec->mComponentName.c_str(), err); - obj.clear(); + buffer.clear(); + + eos = true; } - sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); + int32_t tmp; + if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) { + eos = true; + err = ERROR_END_OF_STREAM; + } BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM); @@ -1456,7 +2186,7 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { switch (mode) { case KEEP_BUFFERS: { - if (buffer == NULL) { + if (eos) { if (!mCodec->mPortEOS[kPortIndexInput]) { mCodec->mPortEOS[kPortIndexInput] = true; mCodec->mInputEOSResult = err; @@ -1467,9 +2197,7 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { case RESUBMIT_BUFFERS: { - if (buffer != NULL) { - CHECK(!mCodec->mPortEOS[kPortIndexInput]); - + if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) { int64_t timeUs; CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); @@ -1480,6 +2208,10 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { flags |= OMX_BUFFERFLAG_CODECCONFIG; } + if (eos) { + flags |= OMX_BUFFERFLAG_EOS; + } + if (buffer != info->mData) { if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) { ALOGV("[%s] Needs to copy input data.", @@ -1493,6 +2225,9 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { if (flags & OMX_BUFFERFLAG_CODECCONFIG) { ALOGV("[%s] calling emptyBuffer %p w/ codec specific data", mCodec->mComponentName.c_str(), bufferID); + } else if (flags & OMX_BUFFERFLAG_EOS) { + ALOGV("[%s] calling emptyBuffer %p w/ EOS", + mCodec->mComponentName.c_str(), bufferID); } else { ALOGV("[%s] calling emptyBuffer %p w/ time %lld us", mCodec->mComponentName.c_str(), bufferID, timeUs); @@ -1509,7 +2244,15 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { info->mStatus = BufferInfo::OWNED_BY_COMPONENT; - getMoreInputDataIfPossible(); + if (!eos) { + getMoreInputDataIfPossible(); + } else { + ALOGV("[%s] Signalled EOS on the input port", + mCodec->mComponentName.c_str()); + + mCodec->mPortEOS[kPortIndexInput] = true; + mCodec->mInputEOSResult = err; + } } else if (!mCodec->mPortEOS[kPortIndexInput]) { if (err != ERROR_END_OF_STREAM) { ALOGV("[%s] Signalling EOS on the input port " @@ -1582,8 +2325,8 @@ bool ACodec::BaseState::onOMXFillBufferDone( int64_t timeUs, void *platformPrivate, void *dataPtr) { - ALOGV("[%s] onOMXFillBufferDone %p time %lld us", - mCodec->mComponentName.c_str(), bufferID, timeUs); + ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx", + mCodec->mComponentName.c_str(), bufferID, timeUs, flags); ssize_t index; BufferInfo *info = @@ -1601,46 +2344,48 @@ bool ACodec::BaseState::onOMXFillBufferDone( case RESUBMIT_BUFFERS: { - if (rangeLength == 0) { - if (!(flags & OMX_BUFFERFLAG_EOS)) { - ALOGV("[%s] calling fillBuffer %p", - mCodec->mComponentName.c_str(), info->mBufferID); + if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) { + ALOGV("[%s] calling fillBuffer %p", + mCodec->mComponentName.c_str(), info->mBufferID); - CHECK_EQ(mCodec->mOMX->fillBuffer( - mCodec->mNode, info->mBufferID), - (status_t)OK); + CHECK_EQ(mCodec->mOMX->fillBuffer( + mCodec->mNode, info->mBufferID), + (status_t)OK); - info->mStatus = BufferInfo::OWNED_BY_COMPONENT; - } - } else { - if (!mCodec->mSentFormat) { - mCodec->sendFormatChange(); - } + info->mStatus = BufferInfo::OWNED_BY_COMPONENT; + break; + } - if (mCodec->mNativeWindow == NULL) { - info->mData->setRange(rangeOffset, rangeLength); - } + if (!mCodec->mIsEncoder && !mCodec->mSentFormat) { + mCodec->sendFormatChange(); + } - info->mData->meta()->setInt64("timeUs", timeUs); + if (mCodec->mNativeWindow == NULL) { + info->mData->setRange(rangeOffset, rangeLength); + } - sp<AMessage> notify = mCodec->mNotify->dup(); - notify->setInt32("what", ACodec::kWhatDrainThisBuffer); - notify->setPointer("buffer-id", info->mBufferID); - notify->setObject("buffer", info->mData); + info->mData->meta()->setInt64("timeUs", timeUs); - sp<AMessage> reply = - new AMessage(kWhatOutputBufferDrained, mCodec->id()); + sp<AMessage> notify = mCodec->mNotify->dup(); + notify->setInt32("what", ACodec::kWhatDrainThisBuffer); + notify->setPointer("buffer-id", info->mBufferID); + notify->setBuffer("buffer", info->mData); + notify->setInt32("flags", flags); - reply->setPointer("buffer-id", info->mBufferID); + sp<AMessage> reply = + new AMessage(kWhatOutputBufferDrained, mCodec->id()); - notify->setMessage("reply", reply); + reply->setPointer("buffer-id", info->mBufferID); - notify->post(); + notify->setMessage("reply", reply); - info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; - } + notify->post(); + + info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; if (flags & OMX_BUFFERFLAG_EOS) { + ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str()); + sp<AMessage> notify = mCodec->mNotify->dup(); notify->setInt32("what", ACodec::kWhatEOS); notify->setInt32("err", mCodec->mInputEOSResult); @@ -1678,12 +2423,13 @@ void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { && msg->findInt32("render", &render) && render != 0) { // The client wants this buffer to be rendered. - if (mCodec->mNativeWindow->queueBuffer( + status_t err; + if ((err = mCodec->mNativeWindow->queueBuffer( mCodec->mNativeWindow.get(), - info->mGraphicBuffer.get()) == OK) { + info->mGraphicBuffer.get())) == OK) { info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; } else { - mCodec->signalError(); + mCodec->signalError(OMX_ErrorUndefined, err); info->mStatus = BufferInfo::OWNED_BY_US; } } else { @@ -1758,6 +2504,27 @@ bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { break; } + case ACodec::kWhatAllocateComponent: + { + onAllocateComponent(msg); + handled = true; + break; + } + + case ACodec::kWhatConfigureComponent: + { + onConfigureComponent(msg); + handled = true; + break; + } + + case ACodec::kWhatStart: + { + onStart(); + handled = true; + break; + } + case ACodec::kWhatShutdown: { sp<AMessage> notify = mCodec->mNotify->dup(); @@ -1787,27 +2554,54 @@ bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { void ACodec::UninitializedState::onSetup( const sp<AMessage> &msg) { + onAllocateComponent(msg); + onConfigureComponent(msg); + onStart(); +} + +void ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { + ALOGV("onAllocateComponent"); + + if (mCodec->mNode != NULL) { + CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK); + + mCodec->mNativeWindow.clear(); + mCodec->mNode = NULL; + mCodec->mOMX.clear(); + mCodec->mComponentName.clear(); + } + OMXClient client; CHECK_EQ(client.connect(), (status_t)OK); sp<IOMX> omx = client.interface(); + Vector<String8> matchingCodecs; + AString mime; - CHECK(msg->findString("mime", &mime)); - Vector<String8> matchingCodecs; - OMXCodec::findMatchingCodecs( - mime.c_str(), - false, // createEncoder - NULL, // matchComponentName - 0, // flags - &matchingCodecs); + AString componentName; + if (msg->findString("componentName", &componentName)) { + matchingCodecs.push_back(String8(componentName.c_str())); + } else { + CHECK(msg->findString("mime", &mime)); + + int32_t encoder; + if (!msg->findInt32("encoder", &encoder)) { + encoder = false; + } + + OMXCodec::findMatchingCodecs( + mime.c_str(), + encoder, // createEncoder + NULL, // matchComponentName + 0, // flags + &matchingCodecs); + } sp<CodecObserver> observer = new CodecObserver; IOMX::node_id node = NULL; - AString componentName; - for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); ++matchIndex) { componentName = matchingCodecs.itemAt(matchIndex).string(); @@ -1826,7 +2620,12 @@ void ACodec::UninitializedState::onSetup( } if (node == NULL) { - ALOGE("Unable to instantiate a decoder for type '%s'.", mime.c_str()); + if (!mime.empty()) { + ALOGE("Unable to instantiate a decoder for type '%s'.", + mime.c_str()); + } else { + ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str()); + } mCodec->signalError(OMX_ErrorComponentNotFound); return; @@ -1844,20 +2643,52 @@ void ACodec::UninitializedState::onSetup( mCodec->mInputEOSResult = OK; - mCodec->configureCodec(mime.c_str(), msg); + { + sp<AMessage> notify = mCodec->mNotify->dup(); + notify->setInt32("what", ACodec::kWhatComponentAllocated); + notify->setString("componentName", mCodec->mComponentName.c_str()); + notify->post(); + } +} + +void ACodec::UninitializedState::onConfigureComponent( + const sp<AMessage> &msg) { + ALOGV("onConfigureComponent"); + + CHECK(mCodec->mNode != NULL); + + AString mime; + CHECK(msg->findString("mime", &mime)); + + status_t err = mCodec->configureCodec(mime.c_str(), msg); + + if (err != OK) { + mCodec->signalError(OMX_ErrorUndefined, err); + return; + } sp<RefBase> obj; if (msg->findObject("native-window", &obj) - && strncmp("OMX.google.", componentName.c_str(), 11)) { + && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) { sp<NativeWindowWrapper> nativeWindow( static_cast<NativeWindowWrapper *>(obj.get())); CHECK(nativeWindow != NULL); mCodec->mNativeWindow = nativeWindow->getNativeWindow(); } - CHECK_EQ((status_t)OK, mCodec->initNativeWindow()); - CHECK_EQ(omx->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle), + { + sp<AMessage> notify = mCodec->mNotify->dup(); + notify->setInt32("what", ACodec::kWhatComponentConfigured); + notify->post(); + } +} + +void ACodec::UninitializedState::onStart() { + ALOGV("onStart"); + + CHECK_EQ(mCodec->mOMX->sendCommand( + mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), (status_t)OK); mCodec->changeState(mCodec->mLoadedToIdleState); @@ -1878,7 +2709,7 @@ void ACodec::LoadedToIdleState::stateEntered() { "(error 0x%08x)", err); - mCodec->signalError(); + mCodec->signalError(OMX_ErrorUndefined, err); } } @@ -2202,7 +3033,7 @@ bool ACodec::OutputPortSettingsChangedState::onOMXEvent( "port reconfiguration (error 0x%08x)", err); - mCodec->signalError(); + mCodec->signalError(OMX_ErrorUndefined, err); // This is technically not correct, since we were unable // to allocate output buffers and therefore the output port @@ -2240,7 +3071,8 @@ bool ACodec::OutputPortSettingsChangedState::onOMXEvent( //////////////////////////////////////////////////////////////////////////////// ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) - : BaseState(codec) { + : BaseState(codec), + mComponentNowIdle(false) { } bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { @@ -2274,6 +3106,7 @@ bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { void ACodec::ExecutingToIdleState::stateEntered() { ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); + mComponentNowIdle = false; mCodec->mSentFormat = false; } @@ -2285,6 +3118,8 @@ bool ACodec::ExecutingToIdleState::onOMXEvent( CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); + mComponentNowIdle = true; + changeStateIfWeOwnAllBuffers(); return true; @@ -2303,7 +3138,7 @@ bool ACodec::ExecutingToIdleState::onOMXEvent( } void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { - if (mCodec->allYourBuffersAreBelongToUs()) { + if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) { CHECK_EQ(mCodec->mOMX->sendCommand( mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded), (status_t)OK); diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index 3f9ba47..cfb1e29 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -29,12 +29,14 @@ LOCAL_SRC_FILES:= \ MPEG4Writer.cpp \ MediaBuffer.cpp \ MediaBufferGroup.cpp \ + MediaCodec.cpp \ MediaDefs.cpp \ MediaExtractor.cpp \ MediaSource.cpp \ MediaSourceSplitter.cpp \ MetaData.cpp \ NuCachedSource2.cpp \ + NuMediaExtractor.cpp \ OMXClient.cpp \ OMXCodec.cpp \ OggExtractor.cpp \ @@ -61,20 +63,26 @@ LOCAL_C_INCLUDES:= \ $(TOP)/external/openssl/include \ LOCAL_SHARED_LIBRARIES := \ - libbinder \ - libmedia \ - libutils \ - libcutils \ - libui \ - libsonivox \ - libvorbisidec \ + libbinder \ + libmedia \ + libutils \ + libcutils \ + libui \ + libsonivox \ + libvorbisidec \ libstagefright_yuv \ libcamera_client \ - libdrmframework \ - libcrypto \ - libssl \ - libgui \ + libdrmframework \ + libcrypto \ + libssl \ + libgui \ libstagefright_omx \ + liblog \ + libicuuc \ + libicui18n \ + libz \ + libdl \ + libchromium_net \ LOCAL_STATIC_LIBRARIES := \ libstagefright_color_conversion \ @@ -88,51 +96,14 @@ LOCAL_STATIC_LIBRARIES := \ libstagefright_httplive \ libstagefright_id3 \ libFLAC \ + libstagefright_chromium_http \ -################################################################################ - -# The following was shamelessly copied from external/webkit/Android.mk and -# currently must follow the same logic to determine how webkit was built and -# if it's safe to link against libchromium_net - -# See if the user has specified a stack they want to use -HTTP_STACK = $(HTTP) -# We default to the Chrome HTTP stack. -DEFAULT_HTTP = chrome -ALT_HTTP = android - -ifneq ($(HTTP_STACK),chrome) - ifneq ($(HTTP_STACK),android) - # No HTTP stack is specified, pickup the one we want as default. - ifeq ($(USE_ALT_HTTP),true) - HTTP_STACK = $(ALT_HTTP) - else - HTTP_STACK = $(DEFAULT_HTTP) - endif - endif -endif - -ifeq ($(HTTP_STACK),chrome) - -LOCAL_SHARED_LIBRARIES += \ - liblog \ - libicuuc \ - libicui18n \ - libz \ - libdl \ - -LOCAL_STATIC_LIBRARIES += \ - libstagefright_chromium_http - -LOCAL_SHARED_LIBRARIES += libstlport libchromium_net +LOCAL_SHARED_LIBRARIES += libstlport include external/stlport/libstlport.mk +# TODO: Chromium is always available, so this flag can be removed. LOCAL_CPPFLAGS += -DCHROMIUM_AVAILABLE=1 -endif # ifeq ($(HTTP_STACK),chrome) - -################################################################################ - LOCAL_SHARED_LIBRARIES += \ libstagefright_enc_common \ libstagefright_avc_common \ diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 70945e3..8cfb8d3 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -47,10 +47,8 @@ #include <media/stagefright/MetaData.h> #include <media/stagefright/OMXCodec.h> -#include <surfaceflinger/Surface.h> #include <gui/ISurfaceTexture.h> #include <gui/SurfaceTextureClient.h> -#include <surfaceflinger/ISurfaceComposer.h> #include <media/stagefright/foundation/AMessage.h> diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp index ed1d5f4..2df5528 100755 --- a/media/libstagefright/CameraSource.cpp +++ b/media/libstagefright/CameraSource.cpp @@ -27,7 +27,7 @@ #include <media/stagefright/MetaData.h> #include <camera/Camera.h> #include <camera/CameraParameters.h> -#include <surfaceflinger/Surface.h> +#include <gui/Surface.h> #include <utils/String8.h> #include <cutils/properties.h> diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp index 0b4ecbe..f702376 100644 --- a/media/libstagefright/MPEG2TSWriter.cpp +++ b/media/libstagefright/MPEG2TSWriter.cpp @@ -244,7 +244,7 @@ void MPEG2TSWriter::SourceInfo::extractCodecSpecificData() { sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", kNotifyBuffer); - notify->setObject("buffer", out); + notify->setBuffer("buffer", out); notify->setInt32("oob", true); notify->post(); } @@ -270,7 +270,7 @@ void MPEG2TSWriter::SourceInfo::postAVCFrame(MediaBuffer *buffer) { copy->meta()->setInt32("isSync", true); } - notify->setObject("buffer", copy); + notify->setBuffer("buffer", copy); notify->post(); } @@ -351,7 +351,7 @@ bool MPEG2TSWriter::SourceInfo::flushAACFrames() { sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", kNotifyBuffer); - notify->setObject("buffer", mAACBuffer); + notify->setBuffer("buffer", mAACBuffer); notify->post(); mAACBuffer.clear(); @@ -614,10 +614,8 @@ void MPEG2TSWriter::onMessageReceived(const sp<AMessage> &msg) { ++mNumSourcesDone; } else if (what == SourceInfo::kNotifyBuffer) { - sp<RefBase> obj; - CHECK(msg->findObject("buffer", &obj)); - - sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); + sp<ABuffer> buffer; + CHECK(msg->findBuffer("buffer", &buffer)); int32_t oob; if (msg->findInt32("oob", &oob) && oob) { diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp new file mode 100644 index 0000000..e14b1c4 --- /dev/null +++ b/media/libstagefright/MediaCodec.cpp @@ -0,0 +1,1179 @@ +/* + * Copyright 2012, 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 "MediaCodec" +#include <utils/Log.h> + +#include <media/stagefright/MediaCodec.h> + +#include "include/SoftwareRenderer.h" + +#include <gui/SurfaceTextureClient.h> +#include <media/stagefright/foundation/ABuffer.h> +#include <media/stagefright/foundation/ADebug.h> +#include <media/stagefright/foundation/AMessage.h> +#include <media/stagefright/ACodec.h> +#include <media/stagefright/MediaErrors.h> +#include <media/stagefright/MetaData.h> +#include <media/stagefright/NativeWindowWrapper.h> + +namespace android { + +// static +sp<MediaCodec> MediaCodec::CreateByType( + const sp<ALooper> &looper, const char *mime, bool encoder) { + sp<MediaCodec> codec = new MediaCodec(looper); + if (codec->init(mime, true /* nameIsType */, encoder) != OK) { + return NULL; + } + + return codec; +} + +// static +sp<MediaCodec> MediaCodec::CreateByComponentName( + const sp<ALooper> &looper, const char *name) { + sp<MediaCodec> codec = new MediaCodec(looper); + if (codec->init(name, false /* nameIsType */, false /* encoder */) != OK) { + return NULL; + } + + return codec; +} + +MediaCodec::MediaCodec(const sp<ALooper> &looper) + : mState(UNINITIALIZED), + mLooper(looper), + mCodec(new ACodec), + mFlags(0), + mSoftRenderer(NULL), + mDequeueInputTimeoutGeneration(0), + mDequeueInputReplyID(0), + mDequeueOutputTimeoutGeneration(0), + mDequeueOutputReplyID(0) { +} + +MediaCodec::~MediaCodec() { + CHECK_EQ(mState, UNINITIALIZED); +} + +// static +status_t MediaCodec::PostAndAwaitResponse( + const sp<AMessage> &msg, sp<AMessage> *response) { + status_t err = msg->postAndAwaitResponse(response); + + if (err != OK) { + return err; + } + + if (!(*response)->findInt32("err", &err)) { + err = OK; + } + + return err; +} + +status_t MediaCodec::init(const char *name, bool nameIsType, bool encoder) { + // Current video decoders do not return from OMX_FillThisBuffer + // quickly, violating the OpenMAX specs, until that is remedied + // we need to invest in an extra looper to free the main event + // queue. + bool needDedicatedLooper = false; + if (nameIsType && !strncasecmp(name, "video/", 6)) { + needDedicatedLooper = true; + } else if (!nameIsType && !strncmp(name, "OMX.TI.DUCATI1.VIDEO.", 21)) { + needDedicatedLooper = true; + } + + if (needDedicatedLooper) { + if (mCodecLooper == NULL) { + mCodecLooper = new ALooper; + mCodecLooper->setName("CodecLooper"); + mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO); + } + + mCodecLooper->registerHandler(mCodec); + } else { + mLooper->registerHandler(mCodec); + } + + mLooper->registerHandler(this); + + mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, id())); + + sp<AMessage> msg = new AMessage(kWhatInit, id()); + msg->setString("name", name); + msg->setInt32("nameIsType", nameIsType); + + if (nameIsType) { + msg->setInt32("encoder", encoder); + } + + sp<AMessage> response; + return PostAndAwaitResponse(msg, &response); +} + +status_t MediaCodec::configure( + const sp<AMessage> &format, + const sp<SurfaceTextureClient> &nativeWindow, + uint32_t flags) { + sp<AMessage> msg = new AMessage(kWhatConfigure, id()); + + msg->setMessage("format", format); + msg->setInt32("flags", flags); + + if (nativeWindow != NULL) { + if (!(mFlags & kFlagIsSoftwareCodec)) { + msg->setObject( + "native-window", + new NativeWindowWrapper(nativeWindow)); + } else { + mNativeWindow = nativeWindow; + } + } + + sp<AMessage> response; + return PostAndAwaitResponse(msg, &response); +} + +status_t MediaCodec::start() { + sp<AMessage> msg = new AMessage(kWhatStart, id()); + + sp<AMessage> response; + return PostAndAwaitResponse(msg, &response); +} + +status_t MediaCodec::stop() { + sp<AMessage> msg = new AMessage(kWhatStop, id()); + + sp<AMessage> response; + return PostAndAwaitResponse(msg, &response); +} + +status_t MediaCodec::queueInputBuffer( + size_t index, + size_t offset, + size_t size, + int64_t presentationTimeUs, + uint32_t flags) { + sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id()); + msg->setSize("index", index); + msg->setSize("offset", offset); + msg->setSize("size", size); + msg->setInt64("timeUs", presentationTimeUs); + msg->setInt32("flags", flags); + + sp<AMessage> response; + return PostAndAwaitResponse(msg, &response); +} + +status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) { + sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, id()); + msg->setInt64("timeoutUs", timeoutUs); + + sp<AMessage> response; + status_t err; + if ((err = PostAndAwaitResponse(msg, &response)) != OK) { + return err; + } + + CHECK(response->findSize("index", index)); + + return OK; +} + +status_t MediaCodec::dequeueOutputBuffer( + size_t *index, + size_t *offset, + size_t *size, + int64_t *presentationTimeUs, + uint32_t *flags, + int64_t timeoutUs) { + sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, id()); + msg->setInt64("timeoutUs", timeoutUs); + + sp<AMessage> response; + status_t err; + if ((err = PostAndAwaitResponse(msg, &response)) != OK) { + return err; + } + + CHECK(response->findSize("index", index)); + CHECK(response->findSize("offset", offset)); + CHECK(response->findSize("size", size)); + CHECK(response->findInt64("timeUs", presentationTimeUs)); + CHECK(response->findInt32("flags", (int32_t *)flags)); + + return OK; +} + +status_t MediaCodec::renderOutputBufferAndRelease(size_t index) { + sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id()); + msg->setSize("index", index); + msg->setInt32("render", true); + + sp<AMessage> response; + return PostAndAwaitResponse(msg, &response); +} + +status_t MediaCodec::releaseOutputBuffer(size_t index) { + sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id()); + msg->setSize("index", index); + + sp<AMessage> response; + return PostAndAwaitResponse(msg, &response); +} + +status_t MediaCodec::getOutputFormat(sp<AMessage> *format) const { + sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, id()); + + sp<AMessage> response; + status_t err; + if ((err = PostAndAwaitResponse(msg, &response)) != OK) { + return err; + } + + CHECK(response->findMessage("format", format)); + + return OK; +} + +status_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const { + sp<AMessage> msg = new AMessage(kWhatGetBuffers, id()); + msg->setInt32("portIndex", kPortIndexInput); + msg->setPointer("buffers", buffers); + + sp<AMessage> response; + return PostAndAwaitResponse(msg, &response); +} + +status_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const { + sp<AMessage> msg = new AMessage(kWhatGetBuffers, id()); + msg->setInt32("portIndex", kPortIndexOutput); + msg->setPointer("buffers", buffers); + + sp<AMessage> response; + return PostAndAwaitResponse(msg, &response); +} + +status_t MediaCodec::flush() { + sp<AMessage> msg = new AMessage(kWhatFlush, id()); + + sp<AMessage> response; + return PostAndAwaitResponse(msg, &response); +} + +//////////////////////////////////////////////////////////////////////////////// + +void MediaCodec::cancelPendingDequeueOperations() { + if (mFlags & kFlagDequeueInputPending) { + sp<AMessage> response = new AMessage; + response->setInt32("err", INVALID_OPERATION); + response->postReply(mDequeueInputReplyID); + + ++mDequeueInputTimeoutGeneration; + mDequeueInputReplyID = 0; + mFlags &= ~kFlagDequeueInputPending; + } + + if (mFlags & kFlagDequeueOutputPending) { + sp<AMessage> response = new AMessage; + response->setInt32("err", INVALID_OPERATION); + response->postReply(mDequeueOutputReplyID); + + ++mDequeueOutputTimeoutGeneration; + mDequeueOutputReplyID = 0; + mFlags &= ~kFlagDequeueOutputPending; + } +} + +bool MediaCodec::handleDequeueInputBuffer(uint32_t replyID, bool newRequest) { + if (mState != STARTED + || (mFlags & kFlagStickyError) + || (newRequest && (mFlags & kFlagDequeueInputPending))) { + sp<AMessage> response = new AMessage; + response->setInt32("err", INVALID_OPERATION); + + response->postReply(replyID); + + return true; + } + + ssize_t index = dequeuePortBuffer(kPortIndexInput); + + if (index < 0) { + CHECK_EQ(index, -EAGAIN); + return false; + } + + sp<AMessage> response = new AMessage; + response->setSize("index", index); + response->postReply(replyID); + + return true; +} + +bool MediaCodec::handleDequeueOutputBuffer(uint32_t replyID, bool newRequest) { + sp<AMessage> response = new AMessage; + + if (mState != STARTED + || (mFlags & kFlagStickyError) + || (newRequest && (mFlags & kFlagDequeueOutputPending))) { + response->setInt32("err", INVALID_OPERATION); + } else if (mFlags & kFlagOutputBuffersChanged) { + response->setInt32("err", INFO_OUTPUT_BUFFERS_CHANGED); + mFlags &= ~kFlagOutputBuffersChanged; + } else if (mFlags & kFlagOutputFormatChanged) { + response->setInt32("err", INFO_FORMAT_CHANGED); + mFlags &= ~kFlagOutputFormatChanged; + } else { + ssize_t index = dequeuePortBuffer(kPortIndexOutput); + + if (index < 0) { + CHECK_EQ(index, -EAGAIN); + return false; + } + + const sp<ABuffer> &buffer = + mPortBuffers[kPortIndexOutput].itemAt(index).mData; + + response->setSize("index", index); + response->setSize("offset", buffer->offset()); + response->setSize("size", buffer->size()); + + int64_t timeUs; + CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); + + response->setInt64("timeUs", timeUs); + + int32_t omxFlags; + CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags)); + + uint32_t flags = 0; + if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) { + flags |= BUFFER_FLAG_SYNCFRAME; + } + if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { + flags |= BUFFER_FLAG_CODECCONFIG; + } + if (omxFlags & OMX_BUFFERFLAG_EOS) { + flags |= BUFFER_FLAG_EOS; + } + + response->setInt32("flags", flags); + } + + response->postReply(replyID); + + return true; +} + +void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { + switch (msg->what()) { + case kWhatCodecNotify: + { + int32_t what; + CHECK(msg->findInt32("what", &what)); + + switch (what) { + case ACodec::kWhatError: + { + int32_t omxError, internalError; + CHECK(msg->findInt32("omx-error", &omxError)); + CHECK(msg->findInt32("err", &internalError)); + + ALOGE("Codec reported an error. " + "(omx error 0x%08x, internalError %d)", + omxError, internalError); + + bool sendErrorReponse = true; + + switch (mState) { + case INITIALIZING: + { + setState(UNINITIALIZED); + break; + } + + case CONFIGURING: + { + setState(INITIALIZED); + break; + } + + case STARTING: + { + setState(CONFIGURED); + break; + } + + case STOPPING: + { + // Ignore the error, assuming we'll still get + // the shutdown complete notification. + + sendErrorReponse = false; + break; + } + + case FLUSHING: + { + setState(STARTED); + break; + } + + case STARTED: + { + sendErrorReponse = false; + + mFlags |= kFlagStickyError; + + cancelPendingDequeueOperations(); + break; + } + + default: + { + sendErrorReponse = false; + + mFlags |= kFlagStickyError; + break; + } + } + + if (sendErrorReponse) { + sp<AMessage> response = new AMessage; + response->setInt32("err", UNKNOWN_ERROR); + + response->postReply(mReplyID); + } + break; + } + + case ACodec::kWhatComponentAllocated: + { + CHECK_EQ(mState, INITIALIZING); + setState(INITIALIZED); + + AString componentName; + CHECK(msg->findString("componentName", &componentName)); + + if (componentName.startsWith("OMX.google.")) { + mFlags |= kFlagIsSoftwareCodec; + } else { + mFlags &= ~kFlagIsSoftwareCodec; + } + + (new AMessage)->postReply(mReplyID); + break; + } + + case ACodec::kWhatComponentConfigured: + { + CHECK_EQ(mState, CONFIGURING); + setState(CONFIGURED); + + (new AMessage)->postReply(mReplyID); + break; + } + + case ACodec::kWhatBuffersAllocated: + { + int32_t portIndex; + CHECK(msg->findInt32("portIndex", &portIndex)); + + ALOGV("%s buffers allocated", + portIndex == kPortIndexInput ? "input" : "output"); + + CHECK(portIndex == kPortIndexInput + || portIndex == kPortIndexOutput); + + mPortBuffers[portIndex].clear(); + + Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; + for (size_t i = 0;; ++i) { + AString name = StringPrintf("buffer-id_%d", i); + + void *bufferID; + if (!msg->findPointer(name.c_str(), &bufferID)) { + break; + } + + name = StringPrintf("data_%d", i); + + BufferInfo info; + info.mBufferID = bufferID; + info.mOwnedByClient = false; + CHECK(msg->findBuffer(name.c_str(), &info.mData)); + + buffers->push_back(info); + } + + if (portIndex == kPortIndexOutput) { + if (mState == STARTING) { + // We're always allocating output buffers after + // allocating input buffers, so this is a good + // indication that now all buffers are allocated. + setState(STARTED); + (new AMessage)->postReply(mReplyID); + } else { + mFlags |= kFlagOutputBuffersChanged; + } + } + break; + } + + case ACodec::kWhatOutputFormatChanged: + { + ALOGV("codec output format changed"); + + if ((mFlags & kFlagIsSoftwareCodec) + && mNativeWindow != NULL) { + AString mime; + CHECK(msg->findString("mime", &mime)); + + if (!strncasecmp("video/", mime.c_str(), 6)) { + delete mSoftRenderer; + mSoftRenderer = NULL; + + int32_t width, height; + CHECK(msg->findInt32("width", &width)); + CHECK(msg->findInt32("height", &height)); + + int32_t colorFormat; + CHECK(msg->findInt32( + "color-format", &colorFormat)); + + sp<MetaData> meta = new MetaData; + meta->setInt32(kKeyWidth, width); + meta->setInt32(kKeyHeight, height); + meta->setInt32(kKeyColorFormat, colorFormat); + + mSoftRenderer = + new SoftwareRenderer(mNativeWindow, meta); + } + } + + mOutputFormat = msg; + mFlags |= kFlagOutputFormatChanged; + break; + } + + case ACodec::kWhatFillThisBuffer: + { + /* size_t index = */updateBuffers(kPortIndexInput, msg); + + if (mState == FLUSHING || mState == STOPPING) { + returnBuffersToCodecOnPort(kPortIndexInput); + break; + } + + if (mFlags & kFlagDequeueInputPending) { + CHECK(handleDequeueInputBuffer(mDequeueInputReplyID)); + + ++mDequeueInputTimeoutGeneration; + mFlags &= ~kFlagDequeueInputPending; + mDequeueInputReplyID = 0; + } + break; + } + + case ACodec::kWhatDrainThisBuffer: + { + /* size_t index = */updateBuffers(kPortIndexOutput, msg); + + if (mState == FLUSHING || mState == STOPPING) { + returnBuffersToCodecOnPort(kPortIndexOutput); + break; + } + + sp<ABuffer> buffer; + CHECK(msg->findBuffer("buffer", &buffer)); + + int32_t omxFlags; + CHECK(msg->findInt32("flags", &omxFlags)); + + buffer->meta()->setInt32("omxFlags", omxFlags); + + if (mFlags & kFlagDequeueOutputPending) { + CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID)); + + ++mDequeueOutputTimeoutGeneration; + mFlags &= ~kFlagDequeueOutputPending; + mDequeueOutputReplyID = 0; + } + break; + } + + case ACodec::kWhatEOS: + { + // We already notify the client of this by using the + // corresponding flag in "onOutputBufferReady". + break; + } + + case ACodec::kWhatShutdownCompleted: + { + CHECK_EQ(mState, STOPPING); + setState(UNINITIALIZED); + + (new AMessage)->postReply(mReplyID); + break; + } + + case ACodec::kWhatFlushCompleted: + { + CHECK_EQ(mState, FLUSHING); + setState(STARTED); + + mCodec->signalResume(); + + (new AMessage)->postReply(mReplyID); + break; + } + + default: + TRESPASS(); + } + break; + } + + case kWhatInit: + { + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + if (mState != UNINITIALIZED) { + sp<AMessage> response = new AMessage; + response->setInt32("err", INVALID_OPERATION); + + response->postReply(replyID); + break; + } + + mReplyID = replyID; + setState(INITIALIZING); + + AString name; + CHECK(msg->findString("name", &name)); + + int32_t nameIsType; + int32_t encoder = false; + CHECK(msg->findInt32("nameIsType", &nameIsType)); + if (nameIsType) { + CHECK(msg->findInt32("encoder", &encoder)); + } + + sp<AMessage> format = new AMessage; + + if (nameIsType) { + format->setString("mime", name.c_str()); + format->setInt32("encoder", encoder); + } else { + format->setString("componentName", name.c_str()); + } + + mCodec->initiateAllocateComponent(format); + break; + } + + case kWhatConfigure: + { + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + if (mState != INITIALIZED) { + sp<AMessage> response = new AMessage; + response->setInt32("err", INVALID_OPERATION); + + response->postReply(replyID); + break; + } + + mReplyID = replyID; + setState(CONFIGURING); + + sp<RefBase> obj; + if (!msg->findObject("native-window", &obj)) { + obj.clear(); + } + + sp<AMessage> format; + CHECK(msg->findMessage("format", &format)); + + if (obj != NULL) { + format->setObject("native-window", obj); + } + + uint32_t flags; + CHECK(msg->findInt32("flags", (int32_t *)&flags)); + + if (flags & CONFIGURE_FLAG_ENCODE) { + format->setInt32("encoder", true); + } + + mCodec->initiateConfigureComponent(format); + break; + } + + case kWhatStart: + { + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + if (mState != CONFIGURED) { + sp<AMessage> response = new AMessage; + response->setInt32("err", INVALID_OPERATION); + + response->postReply(replyID); + break; + } + + mReplyID = replyID; + setState(STARTING); + + mCodec->initiateStart(); + break; + } + + case kWhatStop: + { + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + if (mState != INITIALIZED + && mState != CONFIGURED && mState != STARTED) { + sp<AMessage> response = new AMessage; + response->setInt32("err", INVALID_OPERATION); + + response->postReply(replyID); + break; + } + + mReplyID = replyID; + setState(STOPPING); + + mCodec->initiateShutdown(); + returnBuffersToCodec(); + break; + } + + case kWhatDequeueInputBuffer: + { + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + if (handleDequeueInputBuffer(replyID, true /* new request */)) { + break; + } + + int64_t timeoutUs; + CHECK(msg->findInt64("timeoutUs", &timeoutUs)); + + if (timeoutUs == 0ll) { + sp<AMessage> response = new AMessage; + response->setInt32("err", -EAGAIN); + response->postReply(replyID); + break; + } + + mFlags |= kFlagDequeueInputPending; + mDequeueInputReplyID = replyID; + + if (timeoutUs > 0ll) { + sp<AMessage> timeoutMsg = + new AMessage(kWhatDequeueInputTimedOut, id()); + timeoutMsg->setInt32( + "generation", ++mDequeueInputTimeoutGeneration); + timeoutMsg->post(timeoutUs); + } + break; + } + + case kWhatDequeueInputTimedOut: + { + int32_t generation; + CHECK(msg->findInt32("generation", &generation)); + + if (generation != mDequeueInputTimeoutGeneration) { + // Obsolete + break; + } + + CHECK(mFlags & kFlagDequeueInputPending); + + sp<AMessage> response = new AMessage; + response->setInt32("err", -EAGAIN); + response->postReply(mDequeueInputReplyID); + + mFlags &= ~kFlagDequeueInputPending; + mDequeueInputReplyID = 0; + break; + } + + case kWhatQueueInputBuffer: + { + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + if (mState != STARTED || (mFlags & kFlagStickyError)) { + sp<AMessage> response = new AMessage; + response->setInt32("err", INVALID_OPERATION); + + response->postReply(replyID); + break; + } + + status_t err = onQueueInputBuffer(msg); + + sp<AMessage> response = new AMessage; + response->setInt32("err", err); + response->postReply(replyID); + break; + } + + case kWhatDequeueOutputBuffer: + { + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + if (handleDequeueOutputBuffer(replyID, true /* new request */)) { + break; + } + + int64_t timeoutUs; + CHECK(msg->findInt64("timeoutUs", &timeoutUs)); + + if (timeoutUs == 0ll) { + sp<AMessage> response = new AMessage; + response->setInt32("err", -EAGAIN); + response->postReply(replyID); + break; + } + + mFlags |= kFlagDequeueOutputPending; + mDequeueOutputReplyID = replyID; + + if (timeoutUs > 0ll) { + sp<AMessage> timeoutMsg = + new AMessage(kWhatDequeueOutputTimedOut, id()); + timeoutMsg->setInt32( + "generation", ++mDequeueOutputTimeoutGeneration); + timeoutMsg->post(timeoutUs); + } + break; + } + + case kWhatDequeueOutputTimedOut: + { + int32_t generation; + CHECK(msg->findInt32("generation", &generation)); + + if (generation != mDequeueOutputTimeoutGeneration) { + // Obsolete + break; + } + + CHECK(mFlags & kFlagDequeueOutputPending); + + sp<AMessage> response = new AMessage; + response->setInt32("err", -EAGAIN); + response->postReply(mDequeueOutputReplyID); + + mFlags &= ~kFlagDequeueOutputPending; + mDequeueOutputReplyID = 0; + break; + } + + case kWhatReleaseOutputBuffer: + { + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + if (mState != STARTED || (mFlags & kFlagStickyError)) { + sp<AMessage> response = new AMessage; + response->setInt32("err", INVALID_OPERATION); + + response->postReply(replyID); + break; + } + + status_t err = onReleaseOutputBuffer(msg); + + sp<AMessage> response = new AMessage; + response->setInt32("err", err); + response->postReply(replyID); + break; + } + + case kWhatGetBuffers: + { + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + if (mState != STARTED || (mFlags & kFlagStickyError)) { + sp<AMessage> response = new AMessage; + response->setInt32("err", INVALID_OPERATION); + + response->postReply(replyID); + break; + } + + int32_t portIndex; + CHECK(msg->findInt32("portIndex", &portIndex)); + + Vector<sp<ABuffer> > *dstBuffers; + CHECK(msg->findPointer("buffers", (void **)&dstBuffers)); + + dstBuffers->clear(); + const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex]; + + for (size_t i = 0; i < srcBuffers.size(); ++i) { + const BufferInfo &info = srcBuffers.itemAt(i); + + dstBuffers->push_back(info.mData); + } + + (new AMessage)->postReply(replyID); + break; + } + + case kWhatFlush: + { + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + if (mState != STARTED || (mFlags & kFlagStickyError)) { + sp<AMessage> response = new AMessage; + response->setInt32("err", INVALID_OPERATION); + + response->postReply(replyID); + break; + } + + mReplyID = replyID; + setState(FLUSHING); + + mCodec->signalFlush(); + returnBuffersToCodec(); + break; + } + + case kWhatGetOutputFormat: + { + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + if ((mState != STARTED && mState != FLUSHING) + || (mFlags & kFlagStickyError)) { + sp<AMessage> response = new AMessage; + response->setInt32("err", INVALID_OPERATION); + + response->postReply(replyID); + break; + } + + sp<AMessage> response = new AMessage; + response->setMessage("format", mOutputFormat); + response->postReply(replyID); + break; + } + + default: + TRESPASS(); + } +} + +void MediaCodec::setState(State newState) { + if (newState == UNINITIALIZED) { + delete mSoftRenderer; + mSoftRenderer = NULL; + + mNativeWindow.clear(); + + mOutputFormat.clear(); + mFlags &= ~kFlagOutputFormatChanged; + mFlags &= ~kFlagOutputBuffersChanged; + mFlags &= ~kFlagStickyError; + } + + mState = newState; + + cancelPendingDequeueOperations(); +} + +void MediaCodec::returnBuffersToCodec() { + returnBuffersToCodecOnPort(kPortIndexInput); + returnBuffersToCodecOnPort(kPortIndexOutput); +} + +void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) { + CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); + + Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; + + for (size_t i = 0; i < buffers->size(); ++i) { + BufferInfo *info = &buffers->editItemAt(i); + + if (info->mNotify != NULL) { + sp<AMessage> msg = info->mNotify; + info->mNotify = NULL; + info->mOwnedByClient = false; + + if (portIndex == kPortIndexInput) { + msg->setInt32("err", ERROR_END_OF_STREAM); + } + msg->post(); + } + } + + mAvailPortBuffers[portIndex].clear(); +} + +size_t MediaCodec::updateBuffers( + int32_t portIndex, const sp<AMessage> &msg) { + CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); + + void *bufferID; + CHECK(msg->findPointer("buffer-id", &bufferID)); + + Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; + + for (size_t i = 0; i < buffers->size(); ++i) { + BufferInfo *info = &buffers->editItemAt(i); + + if (info->mBufferID == bufferID) { + CHECK(info->mNotify == NULL); + CHECK(msg->findMessage("reply", &info->mNotify)); + + mAvailPortBuffers[portIndex].push_back(i); + + return i; + } + } + + TRESPASS(); + + return 0; +} + +status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) { + size_t index; + size_t offset; + size_t size; + int64_t timeUs; + uint32_t flags; + CHECK(msg->findSize("index", &index)); + CHECK(msg->findSize("offset", &offset)); + CHECK(msg->findSize("size", &size)); + CHECK(msg->findInt64("timeUs", &timeUs)); + CHECK(msg->findInt32("flags", (int32_t *)&flags)); + + if (index >= mPortBuffers[kPortIndexInput].size()) { + return -ERANGE; + } + + BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index); + + if (info->mNotify == NULL || !info->mOwnedByClient) { + return -EACCES; + } + + if (offset + size > info->mData->capacity()) { + return -EINVAL; + } + + sp<AMessage> reply = info->mNotify; + info->mNotify = NULL; + info->mOwnedByClient = false; + + info->mData->setRange(offset, size); + info->mData->meta()->setInt64("timeUs", timeUs); + + if (flags & BUFFER_FLAG_EOS) { + info->mData->meta()->setInt32("eos", true); + } + + if (flags & BUFFER_FLAG_CODECCONFIG) { + info->mData->meta()->setInt32("csd", true); + } + + reply->setBuffer("buffer", info->mData); + reply->post(); + + return OK; +} + +status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) { + size_t index; + CHECK(msg->findSize("index", &index)); + + int32_t render; + if (!msg->findInt32("render", &render)) { + render = 0; + } + + if (mState != STARTED) { + return -EINVAL; + } + + if (index >= mPortBuffers[kPortIndexOutput].size()) { + return -ERANGE; + } + + BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index); + + if (info->mNotify == NULL || !info->mOwnedByClient) { + return -EACCES; + } + + if (render) { + info->mNotify->setInt32("render", true); + + if (mSoftRenderer != NULL) { + mSoftRenderer->render( + info->mData->data(), info->mData->size(), NULL); + } + } + + info->mNotify->post(); + info->mNotify = NULL; + info->mOwnedByClient = false; + + return OK; +} + +ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) { + CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); + + List<size_t> *availBuffers = &mAvailPortBuffers[portIndex]; + + if (availBuffers->empty()) { + return -EAGAIN; + } + + size_t index = *availBuffers->begin(); + availBuffers->erase(availBuffers->begin()); + + BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index); + CHECK(!info->mOwnedByClient); + info->mOwnedByClient = true; + + return index; +} + +} // namespace android diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp new file mode 100644 index 0000000..afd4763 --- /dev/null +++ b/media/libstagefright/NuMediaExtractor.cpp @@ -0,0 +1,433 @@ +/* + * Copyright 2012, 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 "NuMediaExtractor" +#include <utils/Log.h> + +#include <media/stagefright/NuMediaExtractor.h> + +#include "include/ESDS.h" + +#include <media/stagefright/foundation/ABuffer.h> +#include <media/stagefright/foundation/ADebug.h> +#include <media/stagefright/foundation/AMessage.h> +#include <media/stagefright/DataSource.h> +#include <media/stagefright/MediaBuffer.h> +#include <media/stagefright/MediaDefs.h> +#include <media/stagefright/MediaErrors.h> +#include <media/stagefright/MediaExtractor.h> +#include <media/stagefright/MediaSource.h> +#include <media/stagefright/MetaData.h> +#include <media/stagefright/Utils.h> + +namespace android { + +NuMediaExtractor::NuMediaExtractor() { +} + +NuMediaExtractor::~NuMediaExtractor() { + releaseTrackSamples(); + + for (size_t i = 0; i < mSelectedTracks.size(); ++i) { + TrackInfo *info = &mSelectedTracks.editItemAt(i); + + CHECK_EQ((status_t)OK, info->mSource->stop()); + } + + mSelectedTracks.clear(); +} + +status_t NuMediaExtractor::setDataSource(const char *path) { + sp<DataSource> dataSource = DataSource::CreateFromURI(path); + + if (dataSource == NULL) { + return -ENOENT; + } + + mImpl = MediaExtractor::Create(dataSource); + + if (mImpl == NULL) { + return ERROR_UNSUPPORTED; + } + + return OK; +} + +size_t NuMediaExtractor::countTracks() const { + return mImpl == NULL ? 0 : mImpl->countTracks(); +} + +status_t NuMediaExtractor::getTrackFormat( + size_t index, sp<AMessage> *format) const { + *format = NULL; + + if (mImpl == NULL) { + return -EINVAL; + } + + if (index >= mImpl->countTracks()) { + return -ERANGE; + } + + sp<MetaData> meta = mImpl->getTrackMetaData(index); + + const char *mime; + CHECK(meta->findCString(kKeyMIMEType, &mime)); + + sp<AMessage> msg = new AMessage; + msg->setString("mime", mime); + + if (!strncasecmp("video/", mime, 6)) { + int32_t width, height; + CHECK(meta->findInt32(kKeyWidth, &width)); + CHECK(meta->findInt32(kKeyHeight, &height)); + + msg->setInt32("width", width); + msg->setInt32("height", height); + } else { + CHECK(!strncasecmp("audio/", mime, 6)); + + int32_t numChannels, sampleRate; + CHECK(meta->findInt32(kKeyChannelCount, &numChannels)); + CHECK(meta->findInt32(kKeySampleRate, &sampleRate)); + + msg->setInt32("channel-count", numChannels); + msg->setInt32("sample-rate", sampleRate); + } + + int32_t maxInputSize; + if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) { + msg->setInt32("max-input-size", maxInputSize); + } + + uint32_t type; + const void *data; + size_t size; + if (meta->findData(kKeyAVCC, &type, &data, &size)) { + // Parse the AVCDecoderConfigurationRecord + + const uint8_t *ptr = (const uint8_t *)data; + + CHECK(size >= 7); + CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1 + uint8_t profile = ptr[1]; + uint8_t level = ptr[3]; + + // There is decodable content out there that fails the following + // assertion, let's be lenient for now... + // CHECK((ptr[4] >> 2) == 0x3f); // reserved + + size_t lengthSize = 1 + (ptr[4] & 3); + + // commented out check below as H264_QVGA_500_NO_AUDIO.3gp + // violates it... + // CHECK((ptr[5] >> 5) == 7); // reserved + + size_t numSeqParameterSets = ptr[5] & 31; + + ptr += 6; + size -= 6; + + sp<ABuffer> buffer = new ABuffer(1024); + buffer->setRange(0, 0); + + for (size_t i = 0; i < numSeqParameterSets; ++i) { + CHECK(size >= 2); + size_t length = U16_AT(ptr); + + ptr += 2; + size -= 2; + + CHECK(size >= length); + + memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4); + memcpy(buffer->data() + buffer->size() + 4, ptr, length); + buffer->setRange(0, buffer->size() + 4 + length); + + ptr += length; + size -= length; + } + + buffer->meta()->setInt32("csd", true); + buffer->meta()->setInt64("timeUs", 0); + + msg->setBuffer("csd-0", buffer); + + buffer = new ABuffer(1024); + buffer->setRange(0, 0); + + CHECK(size >= 1); + size_t numPictureParameterSets = *ptr; + ++ptr; + --size; + + for (size_t i = 0; i < numPictureParameterSets; ++i) { + CHECK(size >= 2); + size_t length = U16_AT(ptr); + + ptr += 2; + size -= 2; + + CHECK(size >= length); + + memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4); + memcpy(buffer->data() + buffer->size() + 4, ptr, length); + buffer->setRange(0, buffer->size() + 4 + length); + + ptr += length; + size -= length; + } + + buffer->meta()->setInt32("csd", true); + buffer->meta()->setInt64("timeUs", 0); + msg->setBuffer("csd-1", buffer); + } else if (meta->findData(kKeyESDS, &type, &data, &size)) { + ESDS esds((const char *)data, size); + CHECK_EQ(esds.InitCheck(), (status_t)OK); + + const void *codec_specific_data; + size_t codec_specific_data_size; + esds.getCodecSpecificInfo( + &codec_specific_data, &codec_specific_data_size); + + sp<ABuffer> buffer = new ABuffer(codec_specific_data_size); + + memcpy(buffer->data(), codec_specific_data, + codec_specific_data_size); + + buffer->meta()->setInt32("csd", true); + buffer->meta()->setInt64("timeUs", 0); + msg->setBuffer("csd-0", buffer); + } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) { + sp<ABuffer> buffer = new ABuffer(size); + memcpy(buffer->data(), data, size); + + buffer->meta()->setInt32("csd", true); + buffer->meta()->setInt64("timeUs", 0); + msg->setBuffer("csd-0", buffer); + + if (!meta->findData(kKeyVorbisBooks, &type, &data, &size)) { + return -EINVAL; + } + + buffer = new ABuffer(size); + memcpy(buffer->data(), data, size); + + buffer->meta()->setInt32("csd", true); + buffer->meta()->setInt64("timeUs", 0); + msg->setBuffer("csd-1", buffer); + } + + *format = msg; + + return OK; +} + +status_t NuMediaExtractor::selectTrack(size_t index) { + if (mImpl == NULL) { + return -EINVAL; + } + + if (index >= mImpl->countTracks()) { + return -ERANGE; + } + + for (size_t i = 0; i < mSelectedTracks.size(); ++i) { + TrackInfo *info = &mSelectedTracks.editItemAt(i); + + if (info->mTrackIndex == index) { + // This track has already been selected. + return OK; + } + } + + sp<MediaSource> source = mImpl->getTrack(index); + + CHECK_EQ((status_t)OK, source->start()); + + mSelectedTracks.push(); + TrackInfo *info = &mSelectedTracks.editItemAt(mSelectedTracks.size() - 1); + + info->mSource = source; + info->mTrackIndex = index; + info->mFinalResult = OK; + info->mSample = NULL; + info->mSampleTimeUs = -1ll; + info->mFlags = 0; + + const char *mime; + CHECK(source->getFormat()->findCString(kKeyMIMEType, &mime)); + + if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) { + info->mFlags |= kIsVorbis; + } + + return OK; +} + +void NuMediaExtractor::releaseTrackSamples() { + for (size_t i = 0; i < mSelectedTracks.size(); ++i) { + TrackInfo *info = &mSelectedTracks.editItemAt(i); + + if (info->mSample != NULL) { + info->mSample->release(); + info->mSample = NULL; + + info->mSampleTimeUs = -1ll; + } + } +} + +ssize_t NuMediaExtractor::fetchTrackSamples(int64_t seekTimeUs) { + TrackInfo *minInfo = NULL; + ssize_t minIndex = -1; + + for (size_t i = 0; i < mSelectedTracks.size(); ++i) { + TrackInfo *info = &mSelectedTracks.editItemAt(i); + + if (seekTimeUs >= 0ll) { + info->mFinalResult = OK; + + if (info->mSample != NULL) { + info->mSample->release(); + info->mSample = NULL; + info->mSampleTimeUs = -1ll; + } + } else if (info->mFinalResult != OK) { + continue; + } + + if (info->mSample == NULL) { + MediaSource::ReadOptions options; + if (seekTimeUs >= 0ll) { + options.setSeekTo(seekTimeUs); + } + status_t err = info->mSource->read(&info->mSample, &options); + + if (err != OK) { + CHECK(info->mSample == NULL); + + info->mFinalResult = err; + info->mSampleTimeUs = -1ll; + continue; + } else { + CHECK(info->mSample != NULL); + CHECK(info->mSample->meta_data()->findInt64( + kKeyTime, &info->mSampleTimeUs)); + } + } + + if (minInfo == NULL || info->mSampleTimeUs < minInfo->mSampleTimeUs) { + minInfo = info; + minIndex = i; + } + } + + return minIndex; +} + +status_t NuMediaExtractor::seekTo(int64_t timeUs) { + return fetchTrackSamples(timeUs); +} + +status_t NuMediaExtractor::advance() { + ssize_t minIndex = fetchTrackSamples(); + + if (minIndex < 0) { + return ERROR_END_OF_STREAM; + } + + TrackInfo *info = &mSelectedTracks.editItemAt(minIndex); + + info->mSample->release(); + info->mSample = NULL; + info->mSampleTimeUs = -1ll; + + return OK; +} + +status_t NuMediaExtractor::readSampleData(const sp<ABuffer> &buffer) { + ssize_t minIndex = fetchTrackSamples(); + + if (minIndex < 0) { + return ERROR_END_OF_STREAM; + } + + TrackInfo *info = &mSelectedTracks.editItemAt(minIndex); + + size_t sampleSize = info->mSample->range_length(); + + if (info->mFlags & kIsVorbis) { + // Each sample's data is suffixed by the number of page samples + // or -1 if not available. + sampleSize += sizeof(int32_t); + } + + if (buffer->capacity() < sampleSize) { + return -ENOMEM; + } + + const uint8_t *src = + (const uint8_t *)info->mSample->data() + + info->mSample->range_offset(); + + memcpy((uint8_t *)buffer->data(), src, info->mSample->range_length()); + + if (info->mFlags & kIsVorbis) { + int32_t numPageSamples; + if (!info->mSample->meta_data()->findInt32( + kKeyValidSamples, &numPageSamples)) { + numPageSamples = -1; + } + + memcpy((uint8_t *)buffer->data() + info->mSample->range_length(), + &numPageSamples, + sizeof(numPageSamples)); + } + + buffer->setRange(0, sampleSize); + + return OK; +} + +status_t NuMediaExtractor::getSampleTrackIndex(size_t *trackIndex) { + ssize_t minIndex = fetchTrackSamples(); + + if (minIndex < 0) { + return ERROR_END_OF_STREAM; + } + + TrackInfo *info = &mSelectedTracks.editItemAt(minIndex); + *trackIndex = info->mTrackIndex; + + return OK; +} + +status_t NuMediaExtractor::getSampleTime(int64_t *sampleTimeUs) { + ssize_t minIndex = fetchTrackSamples(); + + if (minIndex < 0) { + return ERROR_END_OF_STREAM; + } + + TrackInfo *info = &mSelectedTracks.editItemAt(minIndex); + *sampleTimeUs = info->mSampleTimeUs; + + return OK; +} + +} // namespace android diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp index 7a805aa..7cdb793 100644 --- a/media/libstagefright/OMXClient.cpp +++ b/media/libstagefright/OMXClient.cpp @@ -335,6 +335,10 @@ status_t OMXClient::connect() { } void OMXClient::disconnect() { + if (mOMX.get() != NULL) { + mOMX.clear(); + mOMX = NULL; + } } } // namespace android diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 470f750..1325462 100755 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -1541,6 +1541,8 @@ void OMXCodec::setComponentRole( "video_decoder.mpeg4", "video_encoder.mpeg4" }, { MEDIA_MIMETYPE_VIDEO_H263, "video_decoder.h263", "video_encoder.h263" }, + { MEDIA_MIMETYPE_VIDEO_VPX, + "video_decoder.vpx", "video_encoder.vpx" }, }; static const size_t kNumMimeToRole = @@ -3556,6 +3558,7 @@ status_t OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t //////////////// output port //////////////////// // format OMX_AUDIO_PARAM_PORTFORMATTYPE format; + InitOMXParams(&format); format.nPortIndex = kPortIndexOutput; format.nIndex = 0; status_t err = OMX_ErrorNone; diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp index aa047d6..ab2cff0 100644 --- a/media/libstagefright/SurfaceMediaSource.cpp +++ b/media/libstagefright/SurfaceMediaSource.cpp @@ -24,9 +24,8 @@ #include <media/stagefright/MetadataBufferType.h> #include <ui/GraphicBuffer.h> -#include <surfaceflinger/ISurfaceComposer.h> -#include <surfaceflinger/SurfaceComposerClient.h> -#include <surfaceflinger/IGraphicBufferAlloc.h> +#include <gui/ISurfaceComposer.h> +#include <gui/IGraphicBufferAlloc.h> #include <OMX_Component.h> #include <utils/Log.h> diff --git a/media/libstagefright/codecs/aacenc/basic_op/basic_op.h b/media/libstagefright/codecs/aacenc/basic_op/basic_op.h index ef3c31b..e878bba 100644 --- a/media/libstagefright/codecs/aacenc/basic_op/basic_op.h +++ b/media/libstagefright/codecs/aacenc/basic_op/basic_op.h @@ -228,7 +228,7 @@ Word32 L_shr_r (Word32 L_var1, Word16 var2); __inline Word32 ASM_L_shr(Word32 L_var1, Word16 var2) { Word32 result; - asm volatile( + asm ( "MOV %[result], %[L_var1], ASR %[var2] \n" :[result]"=r"(result) :[L_var1]"r"(L_var1), [var2]"r"(var2) @@ -239,15 +239,12 @@ __inline Word32 ASM_L_shr(Word32 L_var1, Word16 var2) __inline Word32 ASM_L_shl(Word32 L_var1, Word16 var2) { Word32 result; - asm volatile( - "MOV r2, %[L_var1] \n" - "MOV r3, #0x7fffffff\n" + asm ( "MOV %[result], %[L_var1], ASL %[var2] \n" - "TEQ r2, %[result], ASR %[var2]\n" - "EORNE %[result],r3,r2,ASR#31\n" - :[result]"+r"(result) - :[L_var1]"r"(L_var1), [var2]"r"(var2) - :"r2", "r3" + "TEQ %[L_var1], %[result], ASR %[var2]\n" + "EORNE %[result], %[mask], %[L_var1], ASR #31\n" + :[result]"=&r"(result) + :[L_var1]"r"(L_var1), [var2]"r"(var2), [mask]"r"(0x7fffffff) ); return result; } @@ -255,10 +252,10 @@ __inline Word32 ASM_L_shl(Word32 L_var1, Word16 var2) __inline Word32 ASM_shr(Word32 L_var1, Word16 var2) { Word32 result; - asm volatile( + asm ( "CMP %[var2], #15\n" - "MOVGE %[var2], #15\n" - "MOV %[result], %[L_var1], ASR %[var2]\n" + "MOVLT %[result], %[L_var1], ASR %[var2]\n" + "MOVGE %[result], %[L_var1], ASR #15\n" :[result]"=r"(result) :[L_var1]"r"(L_var1), [var2]"r"(var2) ); @@ -268,18 +265,16 @@ __inline Word32 ASM_shr(Word32 L_var1, Word16 var2) __inline Word32 ASM_shl(Word32 L_var1, Word16 var2) { Word32 result; - asm volatile( + Word32 tmp; + asm ( "CMP %[var2], #16\n" - "MOVGE %[var2], #16\n" - "MOV %[result], %[L_var1], ASL %[var2]\n" - "MOV r3, #1\n" - "MOV r2, %[result], ASR #15\n" - "RSB r3,r3,r3,LSL #15 \n" - "TEQ r2, %[result], ASR #31 \n" - "EORNE %[result], r3, %[result],ASR #31" - :[result]"+r"(result) - :[L_var1]"r"(L_var1), [var2]"r"(var2) - :"r2", "r3" + "MOVLT %[result], %[L_var1], ASL %[var2]\n" + "MOVGE %[result], %[L_var1], ASL #16\n" + "MOV %[tmp], %[result], ASR #15\n" + "TEQ %[tmp], %[result], ASR #31 \n" + "EORNE %[result], %[mask], %[result],ASR #31" + :[result]"=&r"(result), [tmp]"=&r"(tmp) + :[L_var1]"r"(L_var1), [var2]"r"(var2), [mask]"r"(0x7fff) ); return result; } @@ -295,16 +290,14 @@ __inline Word16 saturate(Word32 L_var1) { #if ARMV5TE_SAT Word16 result; + Word32 tmp; asm volatile ( - "MOV %[result], %[L_var1]\n" - "MOV r3, #1\n" - "MOV r2,%[L_var1],ASR#15\n" - "RSB r3, r3, r3, LSL #15\n" - "TEQ r2,%[L_var1],ASR#31\n" - "EORNE %[result],r3,%[L_var1],ASR#31\n" - :[result]"+r"(result) - :[L_var1]"r"(L_var1) - :"r2", "r3" + "MOV %[tmp], %[L_var1],ASR#15\n" + "TEQ %[tmp], %[L_var1],ASR#31\n" + "EORNE %[result], %[mask],%[L_var1],ASR#31\n" + "MOVEQ %[result], %[L_var1]\n" + :[result]"=&r"(result), [tmp]"=&r"(tmp) + :[L_var1]"r"(L_var1), [mask]"r"(0x7fff) ); return result; @@ -420,10 +413,10 @@ __inline Word32 L_mult(Word16 var1, Word16 var2) { #if ARMV5TE_L_MULT Word32 result; - asm volatile( + asm ( "SMULBB %[result], %[var1], %[var2] \n" "QADD %[result], %[result], %[result] \n" - :[result]"+r"(result) + :[result]"=r"(result) :[var1]"r"(var1), [var2]"r"(var2) ); return result; @@ -450,11 +443,11 @@ __inline Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2) { #if ARMV5TE_L_MSU Word32 result; - asm volatile( + asm ( "SMULBB %[result], %[var1], %[var2] \n" "QADD %[result], %[result], %[result] \n" "QSUB %[result], %[L_var3], %[result]\n" - :[result]"+r"(result) + :[result]"=&r"(result) :[L_var3]"r"(L_var3), [var1]"r"(var1), [var2]"r"(var2) ); return result; @@ -474,9 +467,9 @@ __inline Word32 L_sub(Word32 L_var1, Word32 L_var2) { #if ARMV5TE_L_SUB Word32 result; - asm volatile( + asm ( "QSUB %[result], %[L_var1], %[L_var2]\n" - :[result]"+r"(result) + :[result]"=r"(result) :[L_var1]"r"(L_var1), [L_var2]"r"(L_var2) ); return result; @@ -589,16 +582,14 @@ __inline Word16 add (Word16 var1, Word16 var2) { #if ARMV5TE_ADD Word32 result; - asm volatile( + Word32 tmp; + asm ( "ADD %[result], %[var1], %[var2] \n" - "MOV r3, #0x1\n" - "MOV r2, %[result], ASR #15\n" - "RSB r3, r3, r3, LSL, #15\n" - "TEQ r2, %[result], ASR #31\n" - "EORNE %[result], r3, %[result], ASR #31" - :[result]"+r"(result) - :[var1]"r"(var1), [var2]"r"(var2) - :"r2", "r3" + "MOV %[tmp], %[result], ASR #15 \n" + "TEQ %[tmp], %[result], ASR #31 \n" + "EORNE %[result], %[mask], %[result], ASR #31" + :[result]"=&r"(result), [tmp]"=&r"(tmp) + :[var1]"r"(var1), [var2]"r"(var2), [mask]"r"(0x7fff) ); return result; #else @@ -619,16 +610,14 @@ __inline Word16 sub(Word16 var1, Word16 var2) { #if ARMV5TE_SUB Word32 result; - asm volatile( - "MOV r3, #1\n" + Word32 tmp; + asm ( "SUB %[result], %[var1], %[var2] \n" - "RSB r3,r3,r3,LSL#15\n" - "MOV r2, %[var1], ASR #15 \n" - "TEQ r2, %[var1], ASR #31 \n" - "EORNE %[result], r3, %[result], ASR #31 \n" - :[result]"+r"(result) - :[var1]"r"(var1), [var2]"r"(var2) - :"r2", "r3" + "MOV %[tmp], %[var1], ASR #15 \n" + "TEQ %[tmp], %[var1], ASR #31 \n" + "EORNE %[result], %[mask], %[result], ASR #31 \n" + :[result]"=&r"(result), [tmp]"=&r"(tmp) + :[var1]"r"(var1), [var2]"r"(var2), [mask]"r"(0x7fff) ); return result; #else @@ -683,18 +672,15 @@ __inline Word16 div_s (Word16 var1, Word16 var2) __inline Word16 mult (Word16 var1, Word16 var2) { #if ARMV5TE_MULT - Word32 result; - asm volatile( - "SMULBB r2, %[var1], %[var2] \n" - "MOV r3, #1\n" - "MOV %[result], r2, ASR #15\n" - "RSB r3, r3, r3, LSL #15\n" - "MOV r2, %[result], ASR #15\n" - "TEQ r2, %[result], ASR #31\n" - "EORNE %[result], r3, %[result], ASR #31 \n" - :[result]"+r"(result) - :[var1]"r"(var1), [var2]"r"(var2) - :"r2", "r3" + Word32 result, tmp; + asm ( + "SMULBB %[tmp], %[var1], %[var2] \n" + "MOV %[result], %[tmp], ASR #15\n" + "MOV %[tmp], %[result], ASR #15\n" + "TEQ %[tmp], %[result], ASR #31\n" + "EORNE %[result], %[mask], %[result], ASR #31 \n" + :[result]"=&r"(result), [tmp]"=&r"(tmp) + :[var1]"r"(var1), [var2]"r"(var2), [mask]"r"(0x7fff) ); return result; #else @@ -719,18 +705,17 @@ __inline Word16 norm_s (Word16 var1) { #if ARMV5TE_NORM_S Word16 result; - asm volatile( - "MOV r2,%[var1] \n" - "CMP r2, #0\n" - "RSBLT %[var1], %[var1], #0 \n" - "CLZNE %[result], %[var1]\n" + Word32 tmp; + asm ( + "RSBS %[tmp], %[var1], #0 \n" + "CLZLT %[result], %[var1]\n" + "CLZGT %[result], %[tmp]\n" "SUBNE %[result], %[result], #17\n" "MOVEQ %[result], #0\n" - "CMP r2, #-1\n" + "CMP %[var1], #-1\n" "MOVEQ %[result], #15\n" - :[result]"+r"(result) + :[result]"=&r"(result), [tmp]"=&r"(tmp) :[var1]"r"(var1) - :"r2" ); return result; #else @@ -774,7 +759,7 @@ __inline Word16 norm_l (Word32 L_var1) "CLZNE %[result], %[L_var1]\n" "SUBNE %[result], %[result], #1\n" "MOVEQ %[result], #0\n" - :[result]"+r"(result) + :[result]"=r"(result) :[L_var1]"r"(L_var1) ); return result; @@ -979,13 +964,11 @@ __inline Word16 round16(Word32 L_var1) { #if ARMV5TE_ROUND Word16 result; - asm volatile( - "MOV r1,#0x00008000\n" - "QADD %[result], %[L_var1], r1\n" + asm ( + "QADD %[result], %[L_var1], %[bias]\n" "MOV %[result], %[result], ASR #16 \n" - :[result]"+r"(result) - :[L_var1]"r"(L_var1) - :"r1" + :[result]"=r"(result) + :[L_var1]"r"(L_var1), [bias]"r"(0x8000) ); return result; #else @@ -1005,11 +988,11 @@ __inline Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2) { #if ARMV5TE_L_MAC Word32 result; - asm volatile( + asm ( "SMULBB %[result], %[var1], %[var2]\n" "QADD %[result], %[result], %[result]\n" "QADD %[result], %[result], %[L_var3]\n" - :[result]"+r"(result) + :[result]"=&r"(result) : [L_var3]"r"(L_var3), [var1]"r"(var1), [var2]"r"(var2) ); return result; @@ -1029,9 +1012,9 @@ __inline Word32 L_add (Word32 L_var1, Word32 L_var2) { #if ARMV5TE_L_ADD Word32 result; - asm volatile( + asm ( "QADD %[result], %[L_var1], %[L_var2]\n" - :[result]"+r"(result) + :[result]"=r"(result) :[L_var1]"r"(L_var1), [L_var2]"r"(L_var2) ); return result; diff --git a/media/libstagefright/codecs/aacenc/basic_op/oper_32b.h b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.h index 9ebd1c2..6e5844f 100644 --- a/media/libstagefright/codecs/aacenc/basic_op/oper_32b.h +++ b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.h @@ -63,7 +63,7 @@ __inline Word32 L_mpy_wx(Word32 L_var2, Word16 var1) Word32 result; asm volatile( "SMULWB %[result], %[L_var2], %[var1] \n" - :[result]"+r"(result) + :[result]"=r"(result) :[L_var2]"r"(L_var2), [var1]"r"(var1) ); return result; diff --git a/media/libstagefright/codecs/aacenc/basic_op/typedefs.h b/media/libstagefright/codecs/aacenc/basic_op/typedefs.h index 2d5d956..8ef43e2 100644 --- a/media/libstagefright/codecs/aacenc/basic_op/typedefs.h +++ b/media/libstagefright/codecs/aacenc/basic_op/typedefs.h @@ -48,9 +48,7 @@ #define assert(_Expression) ((void)0) #endif -#ifdef LINUX -#define __inline static __inline__ -#endif +#define __inline static __inline #define INT_BITS 32 /* diff --git a/media/libstagefright/codecs/aacenc/inc/aacenc_core.h b/media/libstagefright/codecs/aacenc/inc/aacenc_core.h index 1acdbbc..bb75b6d 100644 --- a/media/libstagefright/codecs/aacenc/inc/aacenc_core.h +++ b/media/libstagefright/codecs/aacenc/inc/aacenc_core.h @@ -102,7 +102,7 @@ Word16 AacEncEncode(AAC_ENCODER *hAacEnc, const UWord8 *ancBytes, /*!< pointer to ancillary data bytes */ Word16 *numAncBytes, /*!< number of ancillary Data Bytes, send as fill element */ UWord8 *outBytes, /*!< pointer to output buffer */ - Word32 *numOutBytes /*!< number of bytes in output buffer */ + VO_U32 *numOutBytes /*!< number of bytes in output buffer */ ); /*--------------------------------------------------------------------------- diff --git a/media/libstagefright/codecs/aacenc/inc/bitbuffer.h b/media/libstagefright/codecs/aacenc/inc/bitbuffer.h index e538064..7c79f07 100644 --- a/media/libstagefright/codecs/aacenc/inc/bitbuffer.h +++ b/media/libstagefright/codecs/aacenc/inc/bitbuffer.h @@ -76,7 +76,7 @@ Word16 GetBitsAvail(HANDLE_BIT_BUF hBitBuf); Word16 WriteBits(HANDLE_BIT_BUF hBitBuf, - Word32 writeValue, + UWord32 writeValue, Word16 noBitsToWrite); void ResetBitBuf(HANDLE_BIT_BUF hBitBuf, diff --git a/media/libstagefright/codecs/aacenc/inc/psy_configuration.h b/media/libstagefright/codecs/aacenc/inc/psy_configuration.h index 9abfc99..f6981fa 100644 --- a/media/libstagefright/codecs/aacenc/inc/psy_configuration.h +++ b/media/libstagefright/codecs/aacenc/inc/psy_configuration.h @@ -31,7 +31,7 @@ typedef struct{ Word16 sfbCnt; Word16 sfbActive; /* number of sf bands containing energy after lowpass */ - Word16 *sfbOffset; + const Word16 *sfbOffset; Word32 sfbThresholdQuiet[MAX_SFB_LONG]; @@ -61,7 +61,7 @@ typedef struct{ Word16 sfbCnt; Word16 sfbActive; /* number of sf bands containing energy after lowpass */ - Word16 *sfbOffset; + const Word16 *sfbOffset; Word32 sfbThresholdQuiet[MAX_SFB_SHORT]; diff --git a/media/libstagefright/codecs/aacenc/src/aacenc_core.c b/media/libstagefright/codecs/aacenc/src/aacenc_core.c index 2b3bd48..cecbc8f 100644 --- a/media/libstagefright/codecs/aacenc/src/aacenc_core.c +++ b/media/libstagefright/codecs/aacenc/src/aacenc_core.c @@ -146,7 +146,7 @@ Word16 AacEncEncode(AAC_ENCODER *aacEnc, /*!< an encoder handle */ const UWord8 *ancBytes, /*!< pointer to ancillary data bytes */ Word16 *numAncBytes, /*!< number of ancillary Data Bytes */ UWord8 *outBytes, /*!< pointer to output buffer (must be large MINBITS_COEF/8*MAX_CHANNELS bytes) */ - Word32 *numOutBytes /*!< number of bytes in output buffer after processing */ + VO_U32 *numOutBytes /*!< number of bytes in output buffer after processing */ ) { ELEMENT_INFO *elInfo = &aacEnc->elInfo; diff --git a/media/libstagefright/codecs/aacenc/src/adj_thr.c b/media/libstagefright/codecs/aacenc/src/adj_thr.c index a8ab809..373b063 100644 --- a/media/libstagefright/codecs/aacenc/src/adj_thr.c +++ b/media/libstagefright/codecs/aacenc/src/adj_thr.c @@ -26,6 +26,7 @@ #include "adj_thr.h" #include "qc_data.h" #include "line_pe.h" +#include <string.h> #define minSnrLimit 0x6666 /* 1 dB */ @@ -1138,6 +1139,7 @@ void AdjustThresholds(ADJ_THR_STATE *adjThrState, Word16 maxBitresBits = elBits->maxBits; Word16 sideInfoBits = (qcOE->staticBitsUsed + qcOE->ancBitsUsed); Word16 ch; + memset(&peData, 0, sizeof(peData)); prepareSfbPe(&peData, psyOutChannel, logSfbEnergy, sfbNRelevantLines, nChannels, AdjThrStateElement->peOffset); diff --git a/media/libstagefright/codecs/aacenc/src/bitbuffer.c b/media/libstagefright/codecs/aacenc/src/bitbuffer.c index 5615ac3..a706893 100644 --- a/media/libstagefright/codecs/aacenc/src/bitbuffer.c +++ b/media/libstagefright/codecs/aacenc/src/bitbuffer.c @@ -138,7 +138,7 @@ Word16 GetBitsAvail(HANDLE_BIT_BUF hBitBuf) * *****************************************************************************/ Word16 WriteBits(HANDLE_BIT_BUF hBitBuf, - Word32 writeValue, + UWord32 writeValue, Word16 noBitsToWrite) { Word16 wBitPos; diff --git a/media/libstagefright/codecs/aacenc/src/dyn_bits.c b/media/libstagefright/codecs/aacenc/src/dyn_bits.c index 3d2efdc..7769188 100644 --- a/media/libstagefright/codecs/aacenc/src/dyn_bits.c +++ b/media/libstagefright/codecs/aacenc/src/dyn_bits.c @@ -281,7 +281,7 @@ noiselessCounter(SECTION_DATA *sectionData, const Word32 blockType) { Word32 grpNdx, i; - Word16 *sideInfoTab = NULL; + const Word16 *sideInfoTab = NULL; SECTION_INFO *sectionInfo; /* diff --git a/media/libstagefright/codecs/aacenc/src/interface.c b/media/libstagefright/codecs/aacenc/src/interface.c index f2472d8..d0ad433 100644 --- a/media/libstagefright/codecs/aacenc/src/interface.c +++ b/media/libstagefright/codecs/aacenc/src/interface.c @@ -99,8 +99,8 @@ void BuildInterface(Word32 *groupedMdctSpectrum, Word32 i; Word32 accuSumMS=0; Word32 accuSumLR=0; - Word32 *pSumMS = sfbEnergySumMS.sfbShort; - Word32 *pSumLR = sfbEnergySumLR.sfbShort; + const Word32 *pSumMS = sfbEnergySumMS.sfbShort; + const Word32 *pSumLR = sfbEnergySumLR.sfbShort; for (i=TRANS_FAC; i; i--) { accuSumLR = L_add(accuSumLR, *pSumLR); pSumLR++; diff --git a/media/libstagefright/codecs/aacenc/src/psy_configuration.c b/media/libstagefright/codecs/aacenc/src/psy_configuration.c index 02d92ab..dd40f9b 100644 --- a/media/libstagefright/codecs/aacenc/src/psy_configuration.c +++ b/media/libstagefright/codecs/aacenc/src/psy_configuration.c @@ -139,7 +139,7 @@ static Word16 BarcLineValue(Word16 noOfLines, Word16 fftLine, Word32 samplingFre * *****************************************************************************/ static void initThrQuiet(Word16 numPb, - Word16 *pbOffset, + const Word16 *pbOffset, Word16 *pbBarcVal, Word32 *pbThresholdQuiet) { Word16 i; @@ -250,7 +250,7 @@ static void initSpreading(Word16 numPb, * *****************************************************************************/ static void initBarcValues(Word16 numPb, - Word16 *pbOffset, + const Word16 *pbOffset, Word16 numLines, Word32 samplingFrequency, Word16 *pbBval) diff --git a/media/libstagefright/codecs/aacenc/src/psy_main.c b/media/libstagefright/codecs/aacenc/src/psy_main.c index 085acb8..4e9218c 100644 --- a/media/libstagefright/codecs/aacenc/src/psy_main.c +++ b/media/libstagefright/codecs/aacenc/src/psy_main.c @@ -658,7 +658,8 @@ static Word16 advancePsychShort(PSY_DATA* psyData, Word32 normEnergyShift = (psyData->mdctScale + 1) << 1; /* in reference code, mdct spectrum must be multipied with 2, so +1 */ Word32 clipEnergy = hPsyConfShort->clipEnergy >> normEnergyShift; Word32 wOffset = 0; - Word32 *data0, *data1; + Word32 *data0; + const Word32 *data1; for(w = 0; w < TRANS_FAC; w++) { Word32 i, tdata; diff --git a/media/libstagefright/codecs/aacenc/src/qc_main.c b/media/libstagefright/codecs/aacenc/src/qc_main.c index df6d46e..48ff300 100644 --- a/media/libstagefright/codecs/aacenc/src/qc_main.c +++ b/media/libstagefright/codecs/aacenc/src/qc_main.c @@ -163,7 +163,7 @@ void QCOutDelete(QC_OUT* hQC, VO_MEM_OPERATOR *pMemOP) Word32 i; if(hQC) { - if(hQC->qcChannel[0].quantSpec); + if(hQC->qcChannel[0].quantSpec) mem_free(pMemOP, hQC->qcChannel[0].quantSpec, VO_INDEX_ENC_AAC); if(hQC->qcChannel[0].maxValueInSfb) diff --git a/media/libstagefright/codecs/aacenc/src/quantize.c b/media/libstagefright/codecs/aacenc/src/quantize.c index 54add2f..0d0f550 100644 --- a/media/libstagefright/codecs/aacenc/src/quantize.c +++ b/media/libstagefright/codecs/aacenc/src/quantize.c @@ -110,7 +110,7 @@ static void quantizeLines(const Word16 gain, Word32 m = gain&3; Word32 g = (gain >> 2) + 4; Word32 mdctSpeL; - Word16 *pquat; + const Word16 *pquat; /* gain&3 */ pquat = quantBorders[m]; @@ -333,7 +333,7 @@ Word32 calcSfbDist(const Word32 *spec, Word32 m = gain&3; Word32 g = (gain >> 2) + 4; Word32 g2 = (g << 1) + 1; - Word16 *pquat, *repquat; + const Word16 *pquat, *repquat; /* gain&3 */ pquat = quantBorders[m]; diff --git a/media/libstagefright/codecs/aacenc/src/sf_estim.c b/media/libstagefright/codecs/aacenc/src/sf_estim.c index fe40137..bc320ec 100644 --- a/media/libstagefright/codecs/aacenc/src/sf_estim.c +++ b/media/libstagefright/codecs/aacenc/src/sf_estim.c @@ -400,7 +400,7 @@ static void assimilateSingleScf(PSY_OUT_CHANNEL *psyOutChan, Word16 *minScfCalculated, Flag restartOnSuccess) { - Word32 sfbLast, sfbAct, sfbNext, scfAct, scfMin; + Word16 sfbLast, sfbAct, sfbNext, scfAct, scfMin; Word16 *scfLast, *scfNext; Word32 sfbPeOld, sfbPeNew; Word32 sfbDistNew; diff --git a/media/libstagefright/codecs/aacenc/src/transform.c b/media/libstagefright/codecs/aacenc/src/transform.c index a154a2f..a02336f 100644 --- a/media/libstagefright/codecs/aacenc/src/transform.c +++ b/media/libstagefright/codecs/aacenc/src/transform.c @@ -339,6 +339,12 @@ static void PostMDCT(int *buf0, int num, const int *csptr) *buf1-- = MULHIGH(cosb, tr2) + MULHIGH(sinb, ti2); } } +#else +void Radix4First(int *buf, int num); +void Radix8First(int *buf, int num); +void Radix4FFT(int *buf, int num, int bgn, int *twidTab); +void PreMDCT(int *buf0, int num, const int *csptr); +void PostMDCT(int *buf0, int num, const int *csptr); #endif diff --git a/media/libstagefright/codecs/amrnb/common/include/az_lsp.h b/media/libstagefright/codecs/amrnb/common/include/az_lsp.h index 3e15ba3..7c24ca9 100644 --- a/media/libstagefright/codecs/amrnb/common/include/az_lsp.h +++ b/media/libstagefright/codecs/amrnb/common/include/az_lsp.h @@ -83,7 +83,7 @@ extern "C" ; EXTERNAL VARIABLES REFERENCES ; Declare variables used in this module but defined elsewhere ----------------------------------------------------------------------------*/ - extern Word16 grid[]; + extern const Word16 grid[]; /*---------------------------------------------------------------------------- ; SIMPLE TYPEDEF'S diff --git a/media/libstagefright/codecs/amrnb/common/include/inv_sqrt.h b/media/libstagefright/codecs/amrnb/common/include/inv_sqrt.h index 4fb2b11..91ab3e4 100644 --- a/media/libstagefright/codecs/amrnb/common/include/inv_sqrt.h +++ b/media/libstagefright/codecs/amrnb/common/include/inv_sqrt.h @@ -85,7 +85,7 @@ extern "C" ; EXTERNAL VARIABLES REFERENCES ; Declare variables used in this module but defined elsewhere ----------------------------------------------------------------------------*/ - extern Word16 inv_sqrt_tbl[]; + extern const Word16 inv_sqrt_tbl[]; /*---------------------------------------------------------------------------- ; SIMPLE TYPEDEF'S ----------------------------------------------------------------------------*/ diff --git a/media/libstagefright/codecs/amrnb/common/include/log2_norm.h b/media/libstagefright/codecs/amrnb/common/include/log2_norm.h index b104a69..46b4e4d 100644 --- a/media/libstagefright/codecs/amrnb/common/include/log2_norm.h +++ b/media/libstagefright/codecs/amrnb/common/include/log2_norm.h @@ -85,7 +85,7 @@ extern "C" ; EXTERNAL VARIABLES REFERENCES ; Declare variables used in this module but defined elsewhere ----------------------------------------------------------------------------*/ - extern Word16 log2_tbl[]; + extern const Word16 log2_tbl[]; /*---------------------------------------------------------------------------- ; SIMPLE TYPEDEF'S ----------------------------------------------------------------------------*/ diff --git a/media/libstagefright/codecs/amrnb/common/include/pow2.h b/media/libstagefright/codecs/amrnb/common/include/pow2.h index c96fbdd..9b944eb 100644 --- a/media/libstagefright/codecs/amrnb/common/include/pow2.h +++ b/media/libstagefright/codecs/amrnb/common/include/pow2.h @@ -81,7 +81,7 @@ extern "C" ; EXTERNAL VARIABLES REFERENCES ; Declare variables used in this module but defined elsewhere ----------------------------------------------------------------------------*/ - extern Word16 pow2_tbl[]; + extern const Word16 pow2_tbl[]; /*---------------------------------------------------------------------------- ; SIMPLE TYPEDEF'S ----------------------------------------------------------------------------*/ diff --git a/media/libstagefright/codecs/amrnb/common/include/sqrt_l.h b/media/libstagefright/codecs/amrnb/common/include/sqrt_l.h index 86209bd..a6a2ee5 100644 --- a/media/libstagefright/codecs/amrnb/common/include/sqrt_l.h +++ b/media/libstagefright/codecs/amrnb/common/include/sqrt_l.h @@ -82,7 +82,7 @@ extern "C" ; EXTERNAL VARIABLES REFERENCES ; Declare variables used in this module but defined elsewhere ----------------------------------------------------------------------------*/ - extern Word16 sqrt_l_tbl[]; + extern const Word16 sqrt_l_tbl[]; /*---------------------------------------------------------------------------- ; SIMPLE TYPEDEF'S diff --git a/media/libstagefright/codecs/amrnb/common/src/az_lsp.cpp b/media/libstagefright/codecs/amrnb/common/src/az_lsp.cpp index bd99b30..4135f30 100644 --- a/media/libstagefright/codecs/amrnb/common/src/az_lsp.cpp +++ b/media/libstagefright/codecs/amrnb/common/src/az_lsp.cpp @@ -299,7 +299,7 @@ static Word16 Chebps(Word16 x, t0 += (Word32) * (p_f) << 13; - if ((UWord32)(t0 - 0xfe000000L) < 0x01ffffffL - 0xfe000000L) + if ((UWord32)(t0 - 0xfe000000L) < (UWord32)0x03ffffffL) { cheb = (Word16)(t0 >> 10); } diff --git a/media/libstagefright/codecs/amrnb/common/src/bitno_tab.cpp b/media/libstagefright/codecs/amrnb/common/src/bitno_tab.cpp index fed684d..4ee04a5 100644 --- a/media/libstagefright/codecs/amrnb/common/src/bitno_tab.cpp +++ b/media/libstagefright/codecs/amrnb/common/src/bitno_tab.cpp @@ -152,7 +152,7 @@ extern "C" ; Variable declaration - defined here and used outside this module ----------------------------------------------------------------------------*/ /* number of parameters per modes (values must be <= MAX_PRM_SIZE!) */ - extern const Word16 prmno[N_MODES] = + const Word16 prmno[N_MODES] = { PRMNO_MR475, PRMNO_MR515, @@ -166,7 +166,7 @@ extern "C" }; /* number of parameters to first subframe per modes */ - extern const Word16 prmnofsf[N_MODES - 1] = + const Word16 prmnofsf[N_MODES - 1] = { PRMNOFSF_MR475, PRMNOFSF_MR515, @@ -179,7 +179,7 @@ extern "C" }; /* parameter sizes (# of bits), one table per mode */ - extern const Word16 bitno_MR475[PRMNO_MR475] = + const Word16 bitno_MR475[PRMNO_MR475] = { 8, 8, 7, /* LSP VQ */ 8, 7, 2, 8, /* first subframe */ @@ -188,7 +188,7 @@ extern "C" 4, 7, 2, /* fourth subframe */ }; - extern const Word16 bitno_MR515[PRMNO_MR515] = + const Word16 bitno_MR515[PRMNO_MR515] = { 8, 8, 7, /* LSP VQ */ 8, 7, 2, 6, /* first subframe */ @@ -197,7 +197,7 @@ extern "C" 4, 7, 2, 6, /* fourth subframe */ }; - extern const Word16 bitno_MR59[PRMNO_MR59] = + const Word16 bitno_MR59[PRMNO_MR59] = { 8, 9, 9, /* LSP VQ */ 8, 9, 2, 6, /* first subframe */ @@ -206,7 +206,7 @@ extern "C" 4, 9, 2, 6, /* fourth subframe */ }; - extern const Word16 bitno_MR67[PRMNO_MR67] = + const Word16 bitno_MR67[PRMNO_MR67] = { 8, 9, 9, /* LSP VQ */ 8, 11, 3, 7, /* first subframe */ @@ -215,7 +215,7 @@ extern "C" 4, 11, 3, 7, /* fourth subframe */ }; - extern const Word16 bitno_MR74[PRMNO_MR74] = + const Word16 bitno_MR74[PRMNO_MR74] = { 8, 9, 9, /* LSP VQ */ 8, 13, 4, 7, /* first subframe */ @@ -224,7 +224,7 @@ extern "C" 5, 13, 4, 7, /* fourth subframe */ }; - extern const Word16 bitno_MR795[PRMNO_MR795] = + const Word16 bitno_MR795[PRMNO_MR795] = { 9, 9, 9, /* LSP VQ */ 8, 13, 4, 4, 5, /* first subframe */ @@ -233,7 +233,7 @@ extern "C" 6, 13, 4, 4, 5, /* fourth subframe */ }; - extern const Word16 bitno_MR102[PRMNO_MR102] = + const Word16 bitno_MR102[PRMNO_MR102] = { 8, 9, 9, /* LSP VQ */ 8, 1, 1, 1, 1, 10, 10, 7, 7, /* first subframe */ @@ -242,7 +242,7 @@ extern "C" 5, 1, 1, 1, 1, 10, 10, 7, 7, /* fourth subframe */ }; - extern const Word16 bitno_MR122[PRMNO_MR122] = + const Word16 bitno_MR122[PRMNO_MR122] = { 7, 8, 9, 8, 6, /* LSP VQ */ 9, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 5, /* first subframe */ @@ -251,7 +251,7 @@ extern "C" 6, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 5 /* fourth subframe */ }; - extern const Word16 bitno_MRDTX[PRMNO_MRDTX] = + const Word16 bitno_MRDTX[PRMNO_MRDTX] = { 3, 8, 9, 9, @@ -259,7 +259,7 @@ extern "C" }; /* overall table with all parameter sizes for all modes */ - extern const Word16 * const bitno[N_MODES] = + const Word16 * const bitno[N_MODES] = { bitno_MR475, bitno_MR515, diff --git a/media/libstagefright/codecs/amrnb/common/src/bitreorder_tab.cpp b/media/libstagefright/codecs/amrnb/common/src/bitreorder_tab.cpp index 69b20fb..e284bbc 100644 --- a/media/libstagefright/codecs/amrnb/common/src/bitreorder_tab.cpp +++ b/media/libstagefright/codecs/amrnb/common/src/bitreorder_tab.cpp @@ -123,6 +123,7 @@ terms listed above has been obtained from the copyright holder. ; INCLUDES ----------------------------------------------------------------------------*/ #include "typedef.h" +#include "bitreorder_tab.h" /*--------------------------------------------------------------------------*/ #ifdef __cplusplus @@ -171,7 +172,7 @@ extern "C" ; Variable declaration - defined here and used outside this module ----------------------------------------------------------------------------*/ /* number of parameters per modes (values must be <= MAX_PRM_SIZE!) */ - extern const Word16 numOfBits[NUM_MODES] = + const Word16 numOfBits[NUM_MODES] = { NUMBIT_MR475, NUMBIT_MR515, @@ -191,7 +192,7 @@ extern "C" NUMBIT_NO_DATA }; - extern const Word16 reorderBits_MR475[NUMBIT_MR475] = + const Word16 reorderBits_MR475[NUMBIT_MR475] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 23, 24, 25, 26, @@ -205,7 +206,7 @@ extern "C" 92, 31, 52, 65, 86 }; - extern const Word16 reorderBits_MR515[NUMBIT_MR515] = + const Word16 reorderBits_MR515[NUMBIT_MR515] = { 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 23, 24, 25, 26, @@ -220,7 +221,7 @@ extern "C" 53, 72, 91 }; - extern const Word16 reorderBits_MR59[NUMBIT_MR59] = + const Word16 reorderBits_MR59[NUMBIT_MR59] = { 0, 1, 4, 5, 3, 6, 7, 2, 13, 15, 8, 9, 11, 12, 14, 10, 16, 28, 74, 29, @@ -236,7 +237,7 @@ extern "C" 38, 59, 84, 105, 37, 58, 83, 104 }; - extern const Word16 reorderBits_MR67[NUMBIT_MR67] = + const Word16 reorderBits_MR67[NUMBIT_MR67] = { 0, 1, 4, 3, 5, 6, 13, 7, 2, 8, 9, 11, 15, 12, 14, 10, 28, 82, 29, 83, @@ -254,7 +255,7 @@ extern "C" 36, 61, 90, 115 }; - extern const Word16 reorderBits_MR74[NUMBIT_MR74] = + const Word16 reorderBits_MR74[NUMBIT_MR74] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 26, 87, 27, @@ -273,7 +274,7 @@ extern "C" 39, 68, 100, 129, 40, 69, 101, 130 }; - extern const Word16 reorderBits_MR795[NUMBIT_MR795] = + const Word16 reorderBits_MR795[NUMBIT_MR795] = { 8, 7, 6, 5, 4, 3, 2, 14, 16, 9, 10, 12, 13, 15, 11, 17, 20, 22, 24, 23, @@ -293,7 +294,7 @@ extern "C" 139, 37, 69, 103, 135, 38, 70, 104, 136 }; - extern const Word16 reorderBits_MR102[NUMBIT_MR102] = + const Word16 reorderBits_MR102[NUMBIT_MR102] = { 7, 6, 5, 4, 3, 2, 1, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 26, 27, 28, @@ -318,7 +319,7 @@ extern "C" 63, 46, 55, 56 }; - extern const Word16 reorderBits_MR122[NUMBIT_MR122] = + const Word16 reorderBits_MR122[NUMBIT_MR122] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 23, 15, 16, 17, 18, @@ -348,7 +349,7 @@ extern "C" }; /* overall table with all parameter sizes for all modes */ - extern const Word16 * const reorderBits[NUM_MODES-1] = + const Word16 * const reorderBits[NUM_MODES-1] = { reorderBits_MR475, reorderBits_MR515, @@ -361,7 +362,7 @@ extern "C" }; /* Number of Frames (16-bit segments sent for each mode */ - extern const Word16 numCompressedBytes[16] = + const Word16 numCompressedBytes[16] = { 13, /*4.75*/ 14, /*5.15*/ diff --git a/media/libstagefright/codecs/amrnb/common/src/bytesused.cpp b/media/libstagefright/codecs/amrnb/common/src/bytesused.cpp index 9552206..b61bac4 100644 --- a/media/libstagefright/codecs/amrnb/common/src/bytesused.cpp +++ b/media/libstagefright/codecs/amrnb/common/src/bytesused.cpp @@ -152,7 +152,7 @@ extern "C" ; LOCAL STORE/BUFFER/POINTER DEFINITIONS ; Variable declaration - defined here and used outside this module ----------------------------------------------------------------------------*/ - extern const short BytesUsed[16] = + const short BytesUsed[16] = { 13, /* 4.75 */ 14, /* 5.15 */ diff --git a/media/libstagefright/codecs/amrnb/common/src/c2_9pf_tab.cpp b/media/libstagefright/codecs/amrnb/common/src/c2_9pf_tab.cpp index 471bee8..20de9d6 100644 --- a/media/libstagefright/codecs/amrnb/common/src/c2_9pf_tab.cpp +++ b/media/libstagefright/codecs/amrnb/common/src/c2_9pf_tab.cpp @@ -86,7 +86,8 @@ extern "C" ; LOCAL VARIABLE DEFINITIONS ; [Variable declaration - defined here and used outside this module] ----------------------------------------------------------------------------*/ - extern const Word16 startPos[2*4*2] = {0, 2, 0, 3, + extern const Word16 startPos[]; + const Word16 startPos[2*4*2] = {0, 2, 0, 3, 0, 2, 0, 3, 1, 3, 2, 4, 1, 4, 1, 4 diff --git a/media/libstagefright/codecs/amrnb/common/src/gains_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/gains_tbl.cpp index a08dd2d..a7cd6fb 100644 --- a/media/libstagefright/codecs/amrnb/common/src/gains_tbl.cpp +++ b/media/libstagefright/codecs/amrnb/common/src/gains_tbl.cpp @@ -86,14 +86,16 @@ extern "C" ----------------------------------------------------------------------------*/ - extern const Word16 qua_gain_pitch[NB_QUA_PITCH] = + extern const Word16 qua_gain_pitch[]; + const Word16 qua_gain_pitch[NB_QUA_PITCH] = { 0, 3277, 6556, 8192, 9830, 11469, 12288, 13107, 13926, 14746, 15565, 16384, 17203, 18022, 18842, 19661 }; - extern const Word16 qua_gain_code[(NB_QUA_CODE+1)*3] = + extern const Word16 qua_gain_code[]; + const Word16 qua_gain_code[(NB_QUA_CODE+1)*3] = { /* gain factor (g_fac) and quantized energy error (qua_ener_MR122, qua_ener) * are stored: diff --git a/media/libstagefright/codecs/amrnb/common/src/gray_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/gray_tbl.cpp index 99073d9..c4b2dbc 100644 --- a/media/libstagefright/codecs/amrnb/common/src/gray_tbl.cpp +++ b/media/libstagefright/codecs/amrnb/common/src/gray_tbl.cpp @@ -83,8 +83,10 @@ extern "C" ; [Variable declaration - defined here and used outside this module] ----------------------------------------------------------------------------*/ - extern const Word16 gray[8] = {0, 1, 3, 2, 6, 4, 5, 7}; - extern const Word16 dgray[8] = {0, 1, 3, 2, 5, 6, 4, 7}; + extern const Word16 gray[]; + extern const Word16 dgray[]; + const Word16 gray[8] = {0, 1, 3, 2, 6, 4, 5, 7}; + const Word16 dgray[8] = {0, 1, 3, 2, 5, 6, 4, 7}; /*--------------------------------------------------------------------------*/ #ifdef __cplusplus diff --git a/media/libstagefright/codecs/amrnb/common/src/grid_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/grid_tbl.cpp index cd81566..48566cc 100644 --- a/media/libstagefright/codecs/amrnb/common/src/grid_tbl.cpp +++ b/media/libstagefright/codecs/amrnb/common/src/grid_tbl.cpp @@ -63,6 +63,7 @@ terms listed above has been obtained from the copyright holder. ; INCLUDES ----------------------------------------------------------------------------*/ #include "typedef.h" +#include "az_lsp.h" /*--------------------------------------------------------------------------*/ #ifdef __cplusplus @@ -91,7 +92,7 @@ extern "C" ; LOCAL VARIABLE DEFINITIONS ; [Variable declaration - defined here and used outside this module] ----------------------------------------------------------------------------*/ - extern const Word16 grid[grid_points + 1] = + const Word16 grid[grid_points + 1] = { 32760, 32723, 32588, 32364, 32051, 31651, 31164, 30591, 29935, 29196, 28377, 27481, diff --git a/media/libstagefright/codecs/amrnb/common/src/inv_sqrt_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/inv_sqrt_tbl.cpp index bde2c4e..13c3b24 100644 --- a/media/libstagefright/codecs/amrnb/common/src/inv_sqrt_tbl.cpp +++ b/media/libstagefright/codecs/amrnb/common/src/inv_sqrt_tbl.cpp @@ -55,6 +55,7 @@ terms listed above has been obtained from the copyright holder. ; INCLUDES ----------------------------------------------------------------------------*/ #include "typedef.h" +#include "inv_sqrt.h" /*--------------------------------------------------------------------------*/ #ifdef __cplusplus @@ -82,7 +83,7 @@ extern "C" ; LOCAL VARIABLE DEFINITIONS ; [Variable declaration - defined here and used outside this module] ----------------------------------------------------------------------------*/ - extern const Word16 inv_sqrt_tbl[49] = + const Word16 inv_sqrt_tbl[49] = { 32767, 31790, 30894, 30070, 29309, 28602, 27945, 27330, 26755, 26214, diff --git a/media/libstagefright/codecs/amrnb/common/src/log2_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/log2_tbl.cpp index 25d63b2..9b9b099 100644 --- a/media/libstagefright/codecs/amrnb/common/src/log2_tbl.cpp +++ b/media/libstagefright/codecs/amrnb/common/src/log2_tbl.cpp @@ -54,6 +54,7 @@ terms listed above has been obtained from the copyright holder. ; INCLUDES ----------------------------------------------------------------------------*/ #include "typedef.h" +#include "log2_norm.h" /*--------------------------------------------------------------------------*/ #ifdef __cplusplus @@ -82,7 +83,7 @@ extern "C" ; [Variable declaration - defined here and used outside this module] ----------------------------------------------------------------------------*/ - extern const Word16 log2_tbl[33] = + const Word16 log2_tbl[33] = { 0, 1455, 2866, 4236, 5568, 6863, 8124, 9352, 10549, 11716, 12855, 13967, 15054, 16117, 17156, 18172, 19167, 20142, 21097, 22033, diff --git a/media/libstagefright/codecs/amrnb/common/src/lsp_lsf_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/lsp_lsf_tbl.cpp index cee0f32..ddeeba4 100644 --- a/media/libstagefright/codecs/amrnb/common/src/lsp_lsf_tbl.cpp +++ b/media/libstagefright/codecs/amrnb/common/src/lsp_lsf_tbl.cpp @@ -77,7 +77,8 @@ extern "C" ; [Variable declaration - defined here and used outside this module] ----------------------------------------------------------------------------*/ - extern const Word16 table[65] = + extern const Word16 table[]; + const Word16 table[65] = { 32767, 32729, 32610, 32413, 32138, 31786, 31357, 30853, 30274, 29622, 28899, 28106, 27246, 26320, 25330, 24279, @@ -94,7 +95,8 @@ extern "C" /* slope used to compute y = acos(x) */ - extern const Word16 slope[64] = + extern const Word16 slope[]; + const Word16 slope[64] = { -26887, -8812, -5323, -3813, -2979, -2444, -2081, -1811, -1608, -1450, -1322, -1219, -1132, -1059, -998, -946, diff --git a/media/libstagefright/codecs/amrnb/common/src/lsp_tab.cpp b/media/libstagefright/codecs/amrnb/common/src/lsp_tab.cpp index deded93..0a32dd7 100644 --- a/media/libstagefright/codecs/amrnb/common/src/lsp_tab.cpp +++ b/media/libstagefright/codecs/amrnb/common/src/lsp_tab.cpp @@ -117,6 +117,7 @@ terms listed above has been obtained from the copyright holder. ----------------------------------------------------------------------------*/ #include "typedef.h" #include "cnst.h" +#include "lsp_tab.h" /*--------------------------------------------------------------------------*/ #ifdef __cplusplus @@ -146,7 +147,7 @@ extern "C" ; LOCAL STORE/BUFFER/POINTER DEFINITIONS ; Variable declaration - defined here and used outside this module ----------------------------------------------------------------------------*/ - extern const Word16 lsp_init_data[M] = {30000, 26000, 21000, 15000, 8000, + const Word16 lsp_init_data[M] = {30000, 26000, 21000, 15000, 8000, 0, -8000, -15000, -21000, -26000 }; diff --git a/media/libstagefright/codecs/amrnb/common/src/overflow_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/overflow_tbl.cpp index e5d42d6..c4a016d 100644 --- a/media/libstagefright/codecs/amrnb/common/src/overflow_tbl.cpp +++ b/media/libstagefright/codecs/amrnb/common/src/overflow_tbl.cpp @@ -81,7 +81,7 @@ extern "C" ; LOCAL VARIABLE DEFINITIONS ; [Variable declaration - defined here and used outside this module] ----------------------------------------------------------------------------*/ - extern const Word32 overflow_tbl [32] = {0x7fffffffL, 0x3fffffffL, + const Word32 overflow_tbl [32] = {0x7fffffffL, 0x3fffffffL, 0x1fffffffL, 0x0fffffffL, 0x07ffffffL, 0x03ffffffL, 0x01ffffffL, 0x00ffffffL, diff --git a/media/libstagefright/codecs/amrnb/common/src/ph_disp_tab.cpp b/media/libstagefright/codecs/amrnb/common/src/ph_disp_tab.cpp index 99725df..d568b78 100644 --- a/media/libstagefright/codecs/amrnb/common/src/ph_disp_tab.cpp +++ b/media/libstagefright/codecs/amrnb/common/src/ph_disp_tab.cpp @@ -81,14 +81,16 @@ extern "C" ; LOCAL VARIABLE DEFINITIONS ; [Variable declaration - defined here and used outside this module] ----------------------------------------------------------------------------*/ - extern const Word16 ph_imp_low_MR795[40] = + extern const Word16 ph_imp_low_MR795[]; + const Word16 ph_imp_low_MR795[40] = { 26777, 801, 2505, -683, -1382, 582, 604, -1274, 3511, -5894, 4534, -499, -1940, 3011, -5058, 5614, -1990, -1061, -1459, 4442, -700, -5335, 4609, 452, -589, -3352, 2953, 1267, -1212, -2590, 1731, 3670, -4475, -975, 4391, -2537, 949, -1363, -979, 5734 }; - extern const Word16 ph_imp_mid_MR795[40] = + extern const Word16 ph_imp_mid_MR795[]; + const Word16 ph_imp_mid_MR795[40] = { 30274, 3831, -4036, 2972, -1048, -1002, 2477, -3043, 2815, -2231, 1753, -1611, 1714, -1775, 1543, -1008, 429, -169, 472, -1264, @@ -96,14 +98,16 @@ extern "C" -2063, 2644, -3060, 2897, -1978, 557, 780, -1369, 842, 655 }; - extern const Word16 ph_imp_low[40] = + extern const Word16 ph_imp_low[]; + const Word16 ph_imp_low[40] = { 14690, 11518, 1268, -2761, -5671, 7514, -35, -2807, -3040, 4823, 2952, -8424, 3785, 1455, 2179, -8637, 8051, -2103, -1454, 777, 1108, -2385, 2254, -363, -674, -2103, 6046, -5681, 1072, 3123, -5058, 5312, -2329, -3728, 6924, -3889, 675, -1775, 29, 10145 }; - extern const Word16 ph_imp_mid[40] = + extern const Word16 ph_imp_mid[]; + const Word16 ph_imp_mid[40] = { 30274, 3831, -4036, 2972, -1048, -1002, 2477, -3043, 2815, -2231, 1753, -1611, 1714, -1775, 1543, -1008, 429, -169, 472, -1264, diff --git a/media/libstagefright/codecs/amrnb/common/src/pow2_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/pow2_tbl.cpp index e0183a6..902ea0f 100644 --- a/media/libstagefright/codecs/amrnb/common/src/pow2_tbl.cpp +++ b/media/libstagefright/codecs/amrnb/common/src/pow2_tbl.cpp @@ -53,6 +53,7 @@ terms listed above has been obtained from the copyright holder. ; INCLUDES ----------------------------------------------------------------------------*/ #include "typedef.h" +#include "pow2.h" /*--------------------------------------------------------------------------*/ #ifdef __cplusplus @@ -81,7 +82,7 @@ extern "C" ; [Variable declaration - defined here and used outside this module] ----------------------------------------------------------------------------*/ - extern const Word16 pow2_tbl[33] = + const Word16 pow2_tbl[33] = { 16384, 16743, 17109, 17484, 17867, 18258, 18658, 19066, 19484, 19911, 20347, 20792, 21247, 21713, 22188, 22674, 23170, 23678, 24196, 24726, diff --git a/media/libstagefright/codecs/amrnb/common/src/q_plsf_5_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/q_plsf_5_tbl.cpp index ceb1e1e..caa81cb 100644 --- a/media/libstagefright/codecs/amrnb/common/src/q_plsf_5_tbl.cpp +++ b/media/libstagefright/codecs/amrnb/common/src/q_plsf_5_tbl.cpp @@ -56,6 +56,7 @@ terms listed above has been obtained from the copyright holder. ; INCLUDES ----------------------------------------------------------------------------*/ #include "typedef.h" +#include "q_plsf_5_tbl.h" /*--------------------------------------------------------------------------*/ #ifdef __cplusplus @@ -94,7 +95,7 @@ extern "C" ----------------------------------------------------------------------------*/ /* LSF means ->normalize frequency domain */ - extern const Word16 mean_lsf_5[10] = + const Word16 mean_lsf_5[10] = { 1384, 2077, @@ -108,7 +109,7 @@ extern "C" 13701 }; - extern const Word16 dico1_lsf_5[DICO1_5_SIZE * 4] = + const Word16 dico1_lsf_5[DICO1_5_SIZE * 4] = { -451, -1065, -529, -1305, -450, -756, -497, -863, @@ -240,7 +241,7 @@ extern "C" 1469, 2181, 1443, 2016 }; - extern const Word16 dico2_lsf_5[DICO2_5_SIZE * 4] = + const Word16 dico2_lsf_5[DICO2_5_SIZE * 4] = { -1631, -1600, -1796, -2290, -1027, -1770, -1100, -2025, @@ -500,7 +501,7 @@ extern "C" 2374, 2787, 1821, 2788 }; - extern const Word16 dico3_lsf_5[DICO3_5_SIZE * 4] = + const Word16 dico3_lsf_5[DICO3_5_SIZE * 4] = { -1812, -2275, -1879, -2537, -1640, -1848, -1695, -2004, @@ -760,7 +761,7 @@ extern "C" 2180, 1975, 2326, 2020 }; - extern const Word16 dico4_lsf_5[DICO4_5_SIZE * 4] = + const Word16 dico4_lsf_5[DICO4_5_SIZE * 4] = { -1857, -1681, -1857, -1755, -2056, -1150, -2134, -1654, @@ -1020,7 +1021,7 @@ extern "C" 1716, 1376, 1948, 1465 }; - extern const Word16 dico5_lsf_5[DICO5_5_SIZE * 4] = + const Word16 dico5_lsf_5[DICO5_5_SIZE * 4] = { -1002, -929, -1096, -1203, -641, -931, -604, -961, diff --git a/media/libstagefright/codecs/amrnb/common/src/qua_gain_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/qua_gain_tbl.cpp index 52f77e9..2d913b8 100644 --- a/media/libstagefright/codecs/amrnb/common/src/qua_gain_tbl.cpp +++ b/media/libstagefright/codecs/amrnb/common/src/qua_gain_tbl.cpp @@ -54,6 +54,7 @@ terms listed above has been obtained from the copyright holder. ----------------------------------------------------------------------------*/ #include "typedef.h" #include "qua_gain.h" +#include "qua_gain_tbl.h" /*--------------------------------------------------------------------------*/ #ifdef __cplusplus @@ -96,7 +97,7 @@ extern "C" /* table used in 'high' rates: MR67 MR74 */ - extern const Word16 table_gain_highrates[VQ_SIZE_HIGHRATES*4] = + const Word16 table_gain_highrates[VQ_SIZE_HIGHRATES*4] = { /* @@ -240,7 +241,7 @@ extern "C" /* table used in 'low' rates: MR475, MR515, MR59 */ - extern const Word16 table_gain_lowrates[VQ_SIZE_LOWRATES*4] = + const Word16 table_gain_lowrates[VQ_SIZE_LOWRATES*4] = { /*g_pit, g_fac, qua_ener_MR122, qua_ener */ 10813, 28753, 2879, 17333, diff --git a/media/libstagefright/codecs/amrnb/common/src/sqrt_l_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/sqrt_l_tbl.cpp index 5e9898c..5a84b63 100644 --- a/media/libstagefright/codecs/amrnb/common/src/sqrt_l_tbl.cpp +++ b/media/libstagefright/codecs/amrnb/common/src/sqrt_l_tbl.cpp @@ -58,6 +58,7 @@ terms listed above has been obtained from the copyright holder. ; INCLUDES ----------------------------------------------------------------------------*/ #include "typedef.h" +#include "sqrt_l.h" /*--------------------------------------------------------------------------*/ #ifdef __cplusplus @@ -85,7 +86,7 @@ extern "C" ; LOCAL VARIABLE DEFINITIONS ; [Variable declaration - defined here and used outside this module] ----------------------------------------------------------------------------*/ - extern const Word16 sqrt_l_tbl[50] = + const Word16 sqrt_l_tbl[50] = { 16384, 16888, 17378, 17854, 18318, 18770, 19212, 19644, 20066, 20480, 20886, 21283, 21674, 22058, 22435, 22806, 23170, 23530, 23884, 24232, diff --git a/media/libstagefright/codecs/amrnb/common/src/window_tab.cpp b/media/libstagefright/codecs/amrnb/common/src/window_tab.cpp index fa5faa6..d8fc8cc 100644 --- a/media/libstagefright/codecs/amrnb/common/src/window_tab.cpp +++ b/media/libstagefright/codecs/amrnb/common/src/window_tab.cpp @@ -117,6 +117,7 @@ terms listed above has been obtained from the copyright holder. ----------------------------------------------------------------------------*/ #include "typedef.h" #include "cnst.h" +#include "window_tab.h" /*--------------------------------------------------------------------------*/ #ifdef __cplusplus @@ -154,7 +155,7 @@ extern "C" /* window for non-EFR modesm; uses 40 samples lookahead */ - extern const Word16 window_200_40[L_WINDOW] = + const Word16 window_200_40[L_WINDOW] = { 2621, 2623, 2629, 2638, 2651, 2668, 2689, 2713, 2741, 2772, 2808, 2847, 2890, 2936, 2986, 3040, 3097, 3158, 3223, 3291, @@ -185,7 +186,7 @@ extern "C" /* window for EFR, first two subframes, no lookahead */ - extern const Word16 window_160_80[L_WINDOW] = + const Word16 window_160_80[L_WINDOW] = { 2621, 2624, 2633, 2648, 2668, 2695, 2727, 2765, 2809, 2859, 2915, 2976, 3043, 3116, 3194, 3279, 3368, 3464, 3565, 3671, @@ -215,7 +216,7 @@ extern "C" /* window for EFR, last two subframes, no lookahead */ - extern const Word16 window_232_8[L_WINDOW] = + const Word16 window_232_8[L_WINDOW] = { 2621, 2623, 2627, 2634, 2644, 2656, 2671, 2689, 2710, 2734, 2760, 2789, 2821, 2855, 2893, 2933, 2975, 3021, 3069, 3120, diff --git a/media/libstagefright/codecs/amrnb/dec/src/dec_input_format_tab.cpp b/media/libstagefright/codecs/amrnb/dec/src/dec_input_format_tab.cpp index a59f5fa..fffbbfd 100644 --- a/media/libstagefright/codecs/amrnb/dec/src/dec_input_format_tab.cpp +++ b/media/libstagefright/codecs/amrnb/dec/src/dec_input_format_tab.cpp @@ -121,6 +121,7 @@ terms listed above has been obtained from the copyright holder. ; INCLUDES ----------------------------------------------------------------------------*/ #include "typedef.h" +#include "amrdecode.h" /*--------------------------------------------------------------------------*/ #ifdef __cplusplus @@ -152,7 +153,7 @@ extern "C" ----------------------------------------------------------------------------*/ /* Table containing the number of core AMR data bytes for */ /* each codec mode for WMF input format(number excludes frame type byte) */ - extern const Word16 WmfDecBytesPerFrame[16] = + const Word16 WmfDecBytesPerFrame[16] = { 12, /* 4.75 */ 13, /* 5.15 */ @@ -174,7 +175,7 @@ extern "C" /* Table containing the number of core AMR data bytes for */ /* each codec mode for IF2 input format. */ - extern const Word16 If2DecBytesPerFrame[16] = + const Word16 If2DecBytesPerFrame[16] = { 13, /* 4.75 */ 14, /* 5.15 */ diff --git a/media/libstagefright/codecs/amrnb/dec/src/qgain475_tab.cpp b/media/libstagefright/codecs/amrnb/dec/src/qgain475_tab.cpp index fbcd412..1a08efa 100644 --- a/media/libstagefright/codecs/amrnb/dec/src/qgain475_tab.cpp +++ b/media/libstagefright/codecs/amrnb/dec/src/qgain475_tab.cpp @@ -92,7 +92,7 @@ extern "C" * g_fac(2) (Q12) // frame 1 and 3 * */ - extern const Word16 table_gain_MR475[MR475_VQ_SIZE*4] = + const Word16 table_gain_MR475[MR475_VQ_SIZE*4] = { /*g_pit(0), g_fac(0), g_pit(1), g_fac(1) */ 812, 128, 542, 140, diff --git a/media/libstagefright/codecs/amrnb/enc/src/corrwght_tab.cpp b/media/libstagefright/codecs/amrnb/enc/src/corrwght_tab.cpp index 769e7ba..b3ed02d 100644 --- a/media/libstagefright/codecs/amrnb/enc/src/corrwght_tab.cpp +++ b/media/libstagefright/codecs/amrnb/enc/src/corrwght_tab.cpp @@ -57,6 +57,7 @@ terms listed above has been obtained from the copyright holder. ; INCLUDES ----------------------------------------------------------------------------*/ #include "typedef.h" +#include "p_ol_wgh.h" /*--------------------------------------------------------------------------*/ #ifdef __cplusplus @@ -84,7 +85,7 @@ extern "C" ; LOCAL VARIABLE DEFINITIONS ; [Variable declaration - defined here and used outside this module] ----------------------------------------------------------------------------*/ - extern const Word16 corrweight[251] = + const Word16 corrweight[251] = { 20473, 20506, 20539, 20572, 20605, 20644, 20677, 20716, 20749, 20788, 20821, 20860, 20893, 20932, diff --git a/media/libstagefright/codecs/amrnb/enc/src/enc_output_format_tab.cpp b/media/libstagefright/codecs/amrnb/enc/src/enc_output_format_tab.cpp index 147989f..4551fd7 100644 --- a/media/libstagefright/codecs/amrnb/enc/src/enc_output_format_tab.cpp +++ b/media/libstagefright/codecs/amrnb/enc/src/enc_output_format_tab.cpp @@ -117,6 +117,7 @@ terms listed above has been obtained from the copyright holder. ; INCLUDES ----------------------------------------------------------------------------*/ #include "typedef.h" +#include "amrencode.h" /*--------------------------------------------------------------------------*/ #ifdef __cplusplus @@ -150,7 +151,7 @@ extern "C" /* for WMF output format. */ /* Each entry is the sum of the 3GPP frame type byte and the */ /* number of packed core AMR data bytes */ - extern const Word16 WmfEncBytesPerFrame[16] = + const Word16 WmfEncBytesPerFrame[16] = { 13, /* 4.75 */ 14, /* 5.15 */ @@ -173,7 +174,7 @@ extern "C" /* Number of data bytes in an encoder frame for each codec mode */ /* for IF2 output format */ - extern const Word16 If2EncBytesPerFrame[16] = + const Word16 If2EncBytesPerFrame[16] = { 13, /* 4.75 */ 14, /* 5.15 */ diff --git a/media/libstagefright/codecs/amrnb/enc/src/inter_36_tab.cpp b/media/libstagefright/codecs/amrnb/enc/src/inter_36_tab.cpp index 27f33e9..c8d7b13 100644 --- a/media/libstagefright/codecs/amrnb/enc/src/inter_36_tab.cpp +++ b/media/libstagefright/codecs/amrnb/enc/src/inter_36_tab.cpp @@ -123,6 +123,7 @@ terms listed above has been obtained from the copyright holder. ----------------------------------------------------------------------------*/ #include "typedef.h" #include "cnst.h" +#include "inter_36_tab.h" /*--------------------------------------------------------------------------*/ #ifdef __cplusplus @@ -162,7 +163,7 @@ extern "C" inter_3[k] = inter_6[2*k], 0 <= k <= 3*L_INTER_SRCH */ - extern const Word16 inter_6[FIR_SIZE] = + const Word16 inter_6[FIR_SIZE] = { 29519, 28316, 24906, 19838, 13896, 7945, 2755, diff --git a/media/libstagefright/codecs/amrnb/enc/src/lag_wind_tab.cpp b/media/libstagefright/codecs/amrnb/enc/src/lag_wind_tab.cpp index 53889bb..b0f5b3a 100644 --- a/media/libstagefright/codecs/amrnb/enc/src/lag_wind_tab.cpp +++ b/media/libstagefright/codecs/amrnb/enc/src/lag_wind_tab.cpp @@ -138,6 +138,7 @@ terms listed above has been obtained from the copyright holder. ; INCLUDES ----------------------------------------------------------------------------*/ #include "typedef.h" +#include "lag_wind_tab.h" /*--------------------------------------------------------------------------*/ #ifdef __cplusplus @@ -167,7 +168,7 @@ extern "C" ; LOCAL STORE/BUFFER/POINTER DEFINITIONS ; Variable declaration - defined here and used outside this module ----------------------------------------------------------------------------*/ - extern const Word16 lag_h[10] = + const Word16 lag_h[10] = { 32728, 32619, @@ -181,7 +182,7 @@ extern "C" 29321 }; - extern const Word16 lag_l[10] = + const Word16 lag_l[10] = { 11904, 17280, diff --git a/media/libstagefright/codecs/amrnb/enc/src/set_sign.cpp b/media/libstagefright/codecs/amrnb/enc/src/set_sign.cpp index dedf91a..d626de3 100644 --- a/media/libstagefright/codecs/amrnb/enc/src/set_sign.cpp +++ b/media/libstagefright/codecs/amrnb/enc/src/set_sign.cpp @@ -552,10 +552,10 @@ void set_sign12k2( else { *(p_sign--) = -32767; /* sign = -1 */ - cor = - (cor); + cor = negate(cor); /* modify dn[] according to the fixed sign */ - dn[i] = - val; + dn[i] = negate(val); } *(p_en--) = cor; diff --git a/media/libstagefright/codecs/amrwb/include/pvamrwbdecoder_api.h b/media/libstagefright/codecs/amrwb/include/pvamrwbdecoder_api.h index 457c21f..eca5ae0 100644 --- a/media/libstagefright/codecs/amrwb/include/pvamrwbdecoder_api.h +++ b/media/libstagefright/codecs/amrwb/include/pvamrwbdecoder_api.h @@ -106,7 +106,7 @@ extern "C" #define NUM_OF_MODES 10 - const int16 AMR_WB_COMPRESSED[NUM_OF_MODES] = + static const int16 AMR_WB_COMPRESSED[NUM_OF_MODES] = { NBBITS_7k, NBBITS_9k, diff --git a/media/libstagefright/codecs/amrwb/src/homing_amr_wb_dec.cpp b/media/libstagefright/codecs/amrwb/src/homing_amr_wb_dec.cpp index 59c6c0a..f032a08 100644 --- a/media/libstagefright/codecs/amrwb/src/homing_amr_wb_dec.cpp +++ b/media/libstagefright/codecs/amrwb/src/homing_amr_wb_dec.cpp @@ -134,7 +134,7 @@ extern "C" ; LOCAL STORE/BUFFER/POINTER DEFINITIONS ; Variable declaration - defined here and used outside this module ----------------------------------------------------------------------------*/ -const int16 prmnofsf[NUM_OF_SPMODES] = +static const int16 prmnofsf[NUM_OF_SPMODES] = { 63, 81, 100, 108, 116, 128, @@ -142,21 +142,21 @@ const int16 prmnofsf[NUM_OF_SPMODES] = }; -const int16 dfh_M7k[PRMN_7k] = +static const int16 dfh_M7k[PRMN_7k] = { 3168, 29954, 29213, 16121, 64, 13440, 30624, 16430, 19008 }; -const int16 dfh_M9k[PRMN_9k] = +static const int16 dfh_M9k[PRMN_9k] = { 3168, 31665, 9943, 9123, 15599, 4358, 20248, 2048, 17040, 27787, 16816, 13888 }; -const int16 dfh_M12k[PRMN_12k] = +static const int16 dfh_M12k[PRMN_12k] = { 3168, 31665, 9943, 9128, 3647, 8129, 30930, 27926, @@ -165,7 +165,7 @@ const int16 dfh_M12k[PRMN_12k] = 13948 }; -const int16 dfh_M14k[PRMN_14k] = +static const int16 dfh_M14k[PRMN_14k] = { 3168, 31665, 9943, 9131, 24815, 655, 26616, 26764, @@ -174,7 +174,7 @@ const int16 dfh_M14k[PRMN_14k] = 221, 20321, 17823 }; -const int16 dfh_M16k[PRMN_16k] = +static const int16 dfh_M16k[PRMN_16k] = { 3168, 31665, 9943, 9131, 24815, 700, 3824, 7271, @@ -184,7 +184,7 @@ const int16 dfh_M16k[PRMN_16k] = 6759, 24576 }; -const int16 dfh_M18k[PRMN_18k] = +static const int16 dfh_M18k[PRMN_18k] = { 3168, 31665, 9943, 9135, 14787, 14423, 30477, 24927, @@ -195,7 +195,7 @@ const int16 dfh_M18k[PRMN_18k] = 0 }; -const int16 dfh_M20k[PRMN_20k] = +static const int16 dfh_M20k[PRMN_20k] = { 3168, 31665, 9943, 9129, 8637, 31807, 24646, 736, @@ -206,7 +206,7 @@ const int16 dfh_M20k[PRMN_20k] = 30249, 29123, 0 }; -const int16 dfh_M23k[PRMN_23k] = +static const int16 dfh_M23k[PRMN_23k] = { 3168, 31665, 9943, 9132, 16748, 3202, 28179, 16317, @@ -218,7 +218,7 @@ const int16 dfh_M23k[PRMN_23k] = 23392, 26053, 31216 }; -const int16 dfh_M24k[PRMN_24k] = +static const int16 dfh_M24k[PRMN_24k] = { 3168, 31665, 9943, 9134, 24776, 5857, 18475, 28535, diff --git a/media/libstagefright/codecs/amrwb/src/isp_isf.cpp b/media/libstagefright/codecs/amrwb/src/isp_isf.cpp index 41db7e3..0552733 100644 --- a/media/libstagefright/codecs/amrwb/src/isp_isf.cpp +++ b/media/libstagefright/codecs/amrwb/src/isp_isf.cpp @@ -108,7 +108,7 @@ terms listed above has been obtained from the copyright holder. /* table of cos(x) in Q15 */ -const int16 table[129] = +static const int16 table[129] = { 32767, 32758, 32729, 32679, 32610, 32522, 32413, 32286, 32138, diff --git a/media/libstagefright/codecs/amrwb/src/oversamp_12k8_to_16k.cpp b/media/libstagefright/codecs/amrwb/src/oversamp_12k8_to_16k.cpp index 143c26e..f2ad333 100644 --- a/media/libstagefright/codecs/amrwb/src/oversamp_12k8_to_16k.cpp +++ b/media/libstagefright/codecs/amrwb/src/oversamp_12k8_to_16k.cpp @@ -337,6 +337,6 @@ int16 AmrWbInterpol( /* return result of interpolation */ L_sum = shl_int32(L_sum, 2); /* saturation can occur here */ - return ((int16(L_sum >> 16))); + return ((int16)(L_sum >> 16)); } diff --git a/media/libstagefright/codecs/amrwb/src/phase_dispersion.cpp b/media/libstagefright/codecs/amrwb/src/phase_dispersion.cpp index f90a534..7b08a40 100644 --- a/media/libstagefright/codecs/amrwb/src/phase_dispersion.cpp +++ b/media/libstagefright/codecs/amrwb/src/phase_dispersion.cpp @@ -109,7 +109,7 @@ terms listed above has been obtained from the copyright holder. /* impulse response with phase dispersion */ /* 2.0 - 6.4 kHz phase dispersion */ -const int16 ph_imp_low[L_SUBFR] = +static const int16 ph_imp_low[L_SUBFR] = { 20182, 9693, 3270, -3437, 2864, -5240, 1589, -1357, 600, 3893, -1497, -698, 1203, -5249, 1199, 5371, @@ -122,7 +122,7 @@ const int16 ph_imp_low[L_SUBFR] = }; /* 3.2 - 6.4 kHz phase dispersion */ -const int16 ph_imp_mid[L_SUBFR] = +static const int16 ph_imp_mid[L_SUBFR] = { 24098, 10460, -5263, -763, 2048, -927, 1753, -3323, 2212, 652, -2146, 2487, -3539, 4109, -2107, -374, diff --git a/media/libstagefright/codecs/amrwbenc/inc/isp_isf.tab b/media/libstagefright/codecs/amrwbenc/inc/isp_isf.tab index 97c3b68..865eea0 100644 --- a/media/libstagefright/codecs/amrwbenc/inc/isp_isf.tab +++ b/media/libstagefright/codecs/amrwbenc/inc/isp_isf.tab @@ -21,7 +21,7 @@ /* table of cos(x) in Q15 */ -const static Word16 table[129] = { +static const Word16 table[129] = { 32767, 32758, 32729, 32679, 32610, 32522, 32413, 32286, 32138, 31972, 31786, 31581, 31357, 31114, 30853, 30572, 30274, @@ -42,7 +42,7 @@ const static Word16 table[129] = { /* slope in Q11 used to compute y = acos(x) */ -const static Word16 slope[128] = { +static const Word16 slope[128] = { -26214, -9039, -5243, -3799, -2979, -2405, -2064, -1771, -1579, -1409, -1279, -1170, -1079, -1004, -933, -880, -827, -783, -743, -708, -676, -647, -621, -599, diff --git a/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c b/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c index 0f4d689..ea9da52 100644 --- a/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c +++ b/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c @@ -1702,7 +1702,7 @@ VO_U32 VO_API voAMRWB_SetInputData( gData = (Coder_State *)hCodec; stream = gData->stream; - if(NULL == pInput || NULL == pInput->Buffer || 0 > pInput->Length) + if(NULL == pInput || NULL == pInput->Buffer) { return VO_ERR_INVALID_ARG; } diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp index e892f92..b8516af 100644 --- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp +++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp @@ -23,8 +23,7 @@ #include <binder/MemoryHeapPmem.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/MetaData.h> -#include <surfaceflinger/Surface.h> -#include <ui/android_native_buffer.h> +#include <system/window.h> #include <ui/GraphicBufferMapper.h> #include <gui/ISurfaceTexture.h> diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp index 0a6776e..9a00186 100644 --- a/media/libstagefright/foundation/AMessage.cpp +++ b/media/libstagefright/foundation/AMessage.cpp @@ -19,6 +19,7 @@ #include <ctype.h> #include "AAtomizer.h" +#include "ABuffer.h" #include "ADebug.h" #include "ALooperRoster.h" #include "AString.h" @@ -157,14 +158,23 @@ void AMessage::setString( item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len); } -void AMessage::setObject(const char *name, const sp<RefBase> &obj) { +void AMessage::setObjectInternal( + const char *name, const sp<RefBase> &obj, Type type) { Item *item = allocateItem(name); - item->mType = kTypeObject; + item->mType = type; if (obj != NULL) { obj->incStrong(this); } item->u.refValue = obj.get(); } +void AMessage::setObject(const char *name, const sp<RefBase> &obj) { + setObjectInternal(name, obj, kTypeObject); +} + +void AMessage::setBuffer(const char *name, const sp<ABuffer> &buffer) { + setObjectInternal(name, sp<RefBase>(buffer), kTypeBuffer); +} + void AMessage::setMessage(const char *name, const sp<AMessage> &obj) { Item *item = allocateItem(name); item->mType = kTypeMessage; @@ -203,6 +213,15 @@ bool AMessage::findObject(const char *name, sp<RefBase> *obj) const { return false; } +bool AMessage::findBuffer(const char *name, sp<ABuffer> *buf) const { + const Item *item = findItem(name, kTypeBuffer); + if (item) { + *buf = (ABuffer *)(item->u.refValue); + return true; + } + return false; +} + bool AMessage::findMessage(const char *name, sp<AMessage> *obj) const { const Item *item = findItem(name, kTypeMessage); if (item) { @@ -542,4 +561,20 @@ void AMessage::writeToParcel(Parcel *parcel) const { } } +size_t AMessage::countEntries() const { + return mNumItems; +} + +const char *AMessage::getEntryNameAt(size_t index, Type *type) const { + if (index >= mNumItems) { + *type = kTypeInt32; + + return NULL; + } + + *type = mItems[index].mType; + + return mItems[index].mName; +} + } // namespace android diff --git a/media/libstagefright/include/SoftwareRenderer.h b/media/libstagefright/include/SoftwareRenderer.h index 8f2ea95..7ab0042 100644 --- a/media/libstagefright/include/SoftwareRenderer.h +++ b/media/libstagefright/include/SoftwareRenderer.h @@ -20,7 +20,7 @@ #include <media/stagefright/ColorConverter.h> #include <utils/RefBase.h> -#include <ui/android_native_buffer.h> +#include <system/window.h> namespace android { diff --git a/media/libstagefright/rtsp/AAMRAssembler.cpp b/media/libstagefright/rtsp/AAMRAssembler.cpp index 9d72b1f..fb8abc5 100644 --- a/media/libstagefright/rtsp/AAMRAssembler.cpp +++ b/media/libstagefright/rtsp/AAMRAssembler.cpp @@ -211,7 +211,7 @@ ARTPAssembler::AssemblyStatus AAMRAssembler::addPacket( } sp<AMessage> msg = mNotifyMsg->dup(); - msg->setObject("access-unit", accessUnit); + msg->setBuffer("access-unit", accessUnit); msg->post(); queue->erase(queue->begin()); diff --git a/media/libstagefright/rtsp/AAVCAssembler.cpp b/media/libstagefright/rtsp/AAVCAssembler.cpp index ed8b1df..7ea132e 100644 --- a/media/libstagefright/rtsp/AAVCAssembler.cpp +++ b/media/libstagefright/rtsp/AAVCAssembler.cpp @@ -345,7 +345,7 @@ void AAVCAssembler::submitAccessUnit() { mAccessUnitDamaged = false; sp<AMessage> msg = mNotifyMsg->dup(); - msg->setObject("access-unit", accessUnit); + msg->setBuffer("access-unit", accessUnit); msg->post(); } diff --git a/media/libstagefright/rtsp/AH263Assembler.cpp b/media/libstagefright/rtsp/AH263Assembler.cpp index 498295c..ded70fa 100644 --- a/media/libstagefright/rtsp/AH263Assembler.cpp +++ b/media/libstagefright/rtsp/AH263Assembler.cpp @@ -166,7 +166,7 @@ void AH263Assembler::submitAccessUnit() { mAccessUnitDamaged = false; sp<AMessage> msg = mNotifyMsg->dup(); - msg->setObject("access-unit", accessUnit); + msg->setBuffer("access-unit", accessUnit); msg->post(); } diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp index b0c7007..24c2f30 100644 --- a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp +++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp @@ -571,7 +571,7 @@ void AMPEG4AudioAssembler::submitAccessUnit() { mAccessUnitDamaged = false; sp<AMessage> msg = mNotifyMsg->dup(); - msg->setObject("access-unit", accessUnit); + msg->setBuffer("access-unit", accessUnit); msg->post(); } diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp index 2f2e2c2..687d72b 100644 --- a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp +++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp @@ -368,7 +368,7 @@ void AMPEG4ElementaryAssembler::submitAccessUnit() { mAccessUnitDamaged = false; sp<AMessage> msg = mNotifyMsg->dup(); - msg->setObject("access-unit", accessUnit); + msg->setBuffer("access-unit", accessUnit); msg->post(); } diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp index 8c9dd8d..44988a3 100644 --- a/media/libstagefright/rtsp/ARTPConnection.cpp +++ b/media/libstagefright/rtsp/ARTPConnection.cpp @@ -639,7 +639,7 @@ sp<ARTPSource> ARTPConnection::findSource(StreamInfo *info, uint32_t srcId) { void ARTPConnection::injectPacket(int index, const sp<ABuffer> &buffer) { sp<AMessage> msg = new AMessage(kWhatInjectPacket, id()); msg->setInt32("index", index); - msg->setObject("buffer", buffer); + msg->setBuffer("buffer", buffer); msg->post(); } @@ -647,10 +647,8 @@ void ARTPConnection::onInjectPacket(const sp<AMessage> &msg) { int32_t index; CHECK(msg->findInt32("index", &index)); - sp<RefBase> obj; - CHECK(msg->findObject("buffer", &obj)); - - sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); + sp<ABuffer> buffer; + CHECK(msg->findBuffer("buffer", &buffer)); List<StreamInfo>::iterator it = mStreams.begin(); while (it != mStreams.end() diff --git a/media/libstagefright/rtsp/ARTPSession.cpp b/media/libstagefright/rtsp/ARTPSession.cpp index 7a05b88..ba4e33c 100644 --- a/media/libstagefright/rtsp/ARTPSession.cpp +++ b/media/libstagefright/rtsp/ARTPSession.cpp @@ -145,10 +145,8 @@ void ARTPSession::onMessageReceived(const sp<AMessage> &msg) { break; } - sp<RefBase> obj; - CHECK(msg->findObject("access-unit", &obj)); - - sp<ABuffer> accessUnit = static_cast<ABuffer *>(obj.get()); + sp<ABuffer> accessUnit; + CHECK(msg->findBuffer("access-unit", &accessUnit)); uint64_t ntpTime; CHECK(accessUnit->meta()->findInt64( diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp index 80a010e..539a888 100644 --- a/media/libstagefright/rtsp/ARTSPConnection.cpp +++ b/media/libstagefright/rtsp/ARTSPConnection.cpp @@ -612,7 +612,7 @@ bool ARTSPConnection::receiveRTSPReponse() { if (mObserveBinaryMessage != NULL) { sp<AMessage> notify = mObserveBinaryMessage->dup(); - notify->setObject("buffer", buffer); + notify->setBuffer("buffer", buffer); notify->post(); } else { ALOGW("received binary data, but no one cares."); diff --git a/media/libstagefright/rtsp/ARawAudioAssembler.cpp b/media/libstagefright/rtsp/ARawAudioAssembler.cpp index 98bee82..0da5dd2 100644 --- a/media/libstagefright/rtsp/ARawAudioAssembler.cpp +++ b/media/libstagefright/rtsp/ARawAudioAssembler.cpp @@ -94,7 +94,7 @@ ARTPAssembler::AssemblyStatus ARawAudioAssembler::addPacket( } sp<AMessage> msg = mNotifyMsg->dup(); - msg->setObject("access-unit", buffer); + msg->setBuffer("access-unit", buffer); msg->post(); queue->erase(queue->begin()); diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h index 9a7dd70..deee30f 100644 --- a/media/libstagefright/rtsp/MyHandler.h +++ b/media/libstagefright/rtsp/MyHandler.h @@ -857,10 +857,8 @@ struct MyHandler : public AHandler { return; } - sp<RefBase> obj; - CHECK(msg->findObject("access-unit", &obj)); - - sp<ABuffer> accessUnit = static_cast<ABuffer *>(obj.get()); + sp<ABuffer> accessUnit; + CHECK(msg->findBuffer("access-unit", &accessUnit)); uint32_t seqNum = (uint32_t)accessUnit->int32Data(); @@ -1005,9 +1003,8 @@ struct MyHandler : public AHandler { case 'biny': { - sp<RefBase> obj; - CHECK(msg->findObject("buffer", &obj)); - sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); + sp<ABuffer> buffer; + CHECK(msg->findBuffer("buffer", &buffer)); int32_t index; CHECK(buffer->meta()->findInt32("index", &index)); @@ -1488,7 +1485,7 @@ private: sp<AMessage> msg = mNotify->dup(); msg->setInt32("what", kWhatAccessUnit); msg->setSize("trackIndex", trackIndex); - msg->setObject("accessUnit", accessUnit); + msg->setBuffer("accessUnit", accessUnit); msg->post(); } diff --git a/media/libstagefright/tests/SurfaceMediaSource_test.cpp b/media/libstagefright/tests/SurfaceMediaSource_test.cpp index d7cec04..3dcd9fc 100644 --- a/media/libstagefright/tests/SurfaceMediaSource_test.cpp +++ b/media/libstagefright/tests/SurfaceMediaSource_test.cpp @@ -26,11 +26,11 @@ #include <media/stagefright/SurfaceMediaSource.h> #include <media/mediarecorder.h> -#include <gui/SurfaceTextureClient.h> #include <ui/GraphicBuffer.h> -#include <surfaceflinger/ISurfaceComposer.h> -#include <surfaceflinger/Surface.h> -#include <surfaceflinger/SurfaceComposerClient.h> +#include <gui/SurfaceTextureClient.h> +#include <gui/ISurfaceComposer.h> +#include <gui/Surface.h> +#include <gui/SurfaceComposerClient.h> #include <binder/ProcessState.h> #include <ui/FramebufferNativeWindow.h> diff --git a/media/libstagefright/timedtext/Android.mk b/media/libstagefright/timedtext/Android.mk index 8b23dee..dde2066 100644 --- a/media/libstagefright/timedtext/Android.mk +++ b/media/libstagefright/timedtext/Android.mk @@ -4,7 +4,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ TextDescriptions.cpp \ TimedTextDriver.cpp \ - TimedTextInBandSource.cpp \ + TimedText3GPPSource.cpp \ TimedTextSource.cpp \ TimedTextSRTSource.cpp \ TimedTextPlayer.cpp @@ -12,8 +12,7 @@ LOCAL_SRC_FILES:= \ LOCAL_CFLAGS += -Wno-multichar LOCAL_C_INCLUDES:= \ $(JNI_H_INCLUDE) \ - $(TOP)/frameworks/base/media/libstagefright \ - $(TOP)/frameworks/base/include/media/stagefright/openmax + $(TOP)/frameworks/base/media/libstagefright LOCAL_MODULE:= libstagefright_timedtext diff --git a/media/libstagefright/timedtext/TimedTextInBandSource.cpp b/media/libstagefright/timedtext/TimedText3GPPSource.cpp index afb73fb..4a3bfd3 100644 --- a/media/libstagefright/timedtext/TimedTextInBandSource.cpp +++ b/media/libstagefright/timedtext/TimedText3GPPSource.cpp @@ -15,7 +15,7 @@ */ //#define LOG_NDEBUG 0 -#define LOG_TAG "TimedTextInBandSource" +#define LOG_TAG "TimedText3GPPSource" #include <utils/Log.h> #include <binder/Parcel.h> @@ -26,19 +26,19 @@ #include <media/stagefright/MediaSource.h> #include <media/stagefright/MetaData.h> -#include "TimedTextInBandSource.h" +#include "TimedText3GPPSource.h" #include "TextDescriptions.h" namespace android { -TimedTextInBandSource::TimedTextInBandSource(const sp<MediaSource>& mediaSource) +TimedText3GPPSource::TimedText3GPPSource(const sp<MediaSource>& mediaSource) : mSource(mediaSource) { } -TimedTextInBandSource::~TimedTextInBandSource() { +TimedText3GPPSource::~TimedText3GPPSource() { } -status_t TimedTextInBandSource::read( +status_t TimedText3GPPSource::read( int64_t *timeUs, Parcel *parcel, const MediaSource::ReadOptions *options) { MediaBuffer *textBuffer = NULL; status_t err = mSource->read(&textBuffer, options); @@ -60,7 +60,7 @@ status_t TimedTextInBandSource::read( // text style for the string of text. These descriptions are present only // if they are needed. This method is used to extract the modifier // description and append it at the end of the text. -status_t TimedTextInBandSource::extractAndAppendLocalDescriptions( +status_t TimedText3GPPSource::extractAndAppendLocalDescriptions( int64_t timeUs, const MediaBuffer *textBuffer, Parcel *parcel) { const void *data; size_t size = 0; @@ -68,51 +68,46 @@ status_t TimedTextInBandSource::extractAndAppendLocalDescriptions( const char *mime; CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime)); + CHECK(strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) == 0); - if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) == 0) { - data = textBuffer->data(); - size = textBuffer->size(); - - if (size > 0) { - parcel->freeData(); - flag |= TextDescriptions::IN_BAND_TEXT_3GPP; - return TextDescriptions::getParcelOfDescriptions( - (const uint8_t *)data, size, flag, timeUs / 1000, parcel); - } - return OK; + data = textBuffer->data(); + size = textBuffer->size(); + + if (size > 0) { + parcel->freeData(); + flag |= TextDescriptions::IN_BAND_TEXT_3GPP; + return TextDescriptions::getParcelOfDescriptions( + (const uint8_t *)data, size, flag, timeUs / 1000, parcel); } - return ERROR_UNSUPPORTED; + return OK; } // To extract and send the global text descriptions for all the text samples // in the text track or text file. // TODO: send error message to application via notifyListener()...? -status_t TimedTextInBandSource::extractGlobalDescriptions(Parcel *parcel) { +status_t TimedText3GPPSource::extractGlobalDescriptions(Parcel *parcel) { const void *data; size_t size = 0; int32_t flag = TextDescriptions::GLOBAL_DESCRIPTIONS; const char *mime; CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime)); + CHECK(strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) == 0); + + uint32_t type; + // get the 'tx3g' box content. This box contains the text descriptions + // used to render the text track + if (!mSource->getFormat()->findData( + kKeyTextFormatData, &type, &data, &size)) { + return ERROR_MALFORMED; + } - // support 3GPP only for now - if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) == 0) { - uint32_t type; - // get the 'tx3g' box content. This box contains the text descriptions - // used to render the text track - if (!mSource->getFormat()->findData( - kKeyTextFormatData, &type, &data, &size)) { - return ERROR_MALFORMED; - } - - if (size > 0) { - flag |= TextDescriptions::IN_BAND_TEXT_3GPP; - return TextDescriptions::getParcelOfDescriptions( - (const uint8_t *)data, size, flag, 0, parcel); - } - return OK; + if (size > 0) { + flag |= TextDescriptions::IN_BAND_TEXT_3GPP; + return TextDescriptions::getParcelOfDescriptions( + (const uint8_t *)data, size, flag, 0, parcel); } - return ERROR_UNSUPPORTED; + return OK; } } // namespace android diff --git a/media/libstagefright/timedtext/TimedTextInBandSource.h b/media/libstagefright/timedtext/TimedText3GPPSource.h index 26e5737..cb7e47c 100644 --- a/media/libstagefright/timedtext/TimedTextInBandSource.h +++ b/media/libstagefright/timedtext/TimedText3GPPSource.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TIMED_TEXT_IN_BAND_SOURCE_H_ -#define TIMED_TEXT_IN_BAND_SOURCE_H_ +#ifndef TIMED_TEXT_3GPP_SOURCE_H_ +#define TIMED_TEXT_3GPP_SOURCE_H_ #include <media/stagefright/MediaErrors.h> #include <media/stagefright/MediaSource.h> @@ -27,9 +27,9 @@ namespace android { class MediaBuffer; class Parcel; -class TimedTextInBandSource : public TimedTextSource { +class TimedText3GPPSource : public TimedTextSource { public: - TimedTextInBandSource(const sp<MediaSource>& mediaSource); + TimedText3GPPSource(const sp<MediaSource>& mediaSource); virtual status_t start() { return mSource->start(); } virtual status_t stop() { return mSource->stop(); } virtual status_t read( @@ -39,7 +39,7 @@ class TimedTextInBandSource : public TimedTextSource { virtual status_t extractGlobalDescriptions(Parcel *parcel); protected: - virtual ~TimedTextInBandSource(); + virtual ~TimedText3GPPSource(); private: sp<MediaSource> mSource; @@ -47,9 +47,9 @@ class TimedTextInBandSource : public TimedTextSource { status_t extractAndAppendLocalDescriptions( int64_t timeUs, const MediaBuffer *textBuffer, Parcel *parcel); - DISALLOW_EVIL_CONSTRUCTORS(TimedTextInBandSource); + DISALLOW_EVIL_CONSTRUCTORS(TimedText3GPPSource); }; } // namespace android -#endif // TIMED_TEXT_IN_BAND_SOURCE_H_ +#endif // TIMED_TEXT_3GPP_SOURCE_H_ diff --git a/media/libstagefright/timedtext/TimedTextSource.cpp b/media/libstagefright/timedtext/TimedTextSource.cpp index 9efe67c..ffbe1c3 100644 --- a/media/libstagefright/timedtext/TimedTextSource.cpp +++ b/media/libstagefright/timedtext/TimedTextSource.cpp @@ -18,12 +18,15 @@ #define LOG_TAG "TimedTextSource" #include <utils/Log.h> +#include <media/stagefright/foundation/ADebug.h> // CHECK_XX macro #include <media/stagefright/DataSource.h> +#include <media/stagefright/MediaDefs.h> // for MEDIA_MIMETYPE_xxx #include <media/stagefright/MediaSource.h> +#include <media/stagefright/MetaData.h> #include "TimedTextSource.h" -#include "TimedTextInBandSource.h" +#include "TimedText3GPPSource.h" #include "TimedTextSRTSource.h" namespace android { @@ -31,7 +34,13 @@ namespace android { // static sp<TimedTextSource> TimedTextSource::CreateTimedTextSource( const sp<MediaSource>& mediaSource) { - return new TimedTextInBandSource(mediaSource); + const char *mime; + CHECK(mediaSource->getFormat()->findCString(kKeyMIMEType, &mime)); + if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) == 0) { + return new TimedText3GPPSource(mediaSource); + } + ALOGE("Unsupported mime type for subtitle. : %s", mime); + return NULL; } // static diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 4446681..30ed41d 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -432,6 +432,7 @@ sp<IAudioTrack> AudioFlinger::createTrack( audio_format_t format, uint32_t channelMask, int frameCount, + // FIXME dead, remove from IAudioFlinger uint32_t flags, const sp<IMemory>& sharedBuffer, audio_io_handle_t output, @@ -1938,10 +1939,66 @@ AudioFlinger::MixerThread::~MixerThread() delete mAudioMixer; } +class CpuStats { +public: + void sample(); +#ifdef DEBUG_CPU_USAGE +private: + ThreadCpuUsage mCpu; +#endif +}; + +void CpuStats::sample() { +#ifdef DEBUG_CPU_USAGE + const CentralTendencyStatistics& stats = mCpu.statistics(); + mCpu.sampleAndEnable(); + unsigned n = stats.n(); + // mCpu.elapsed() is expensive, so don't call it every loop + if ((n & 127) == 1) { + long long elapsed = mCpu.elapsed(); + if (elapsed >= DEBUG_CPU_USAGE * 1000000000LL) { + double perLoop = elapsed / (double) n; + double perLoop100 = perLoop * 0.01; + double mean = stats.mean(); + double stddev = stats.stddev(); + double minimum = stats.minimum(); + double maximum = stats.maximum(); + mCpu.resetStatistics(); + ALOGI("CPU usage over past %.1f secs (%u mixer loops at %.1f mean ms per loop):\n us per mix loop: mean=%.0f stddev=%.0f min=%.0f max=%.0f\n %% of wall: mean=%.1f stddev=%.1f min=%.1f max=%.1f", + elapsed * .000000001, n, perLoop * .000001, + mean * .001, + stddev * .001, + minimum * .001, + maximum * .001, + mean / perLoop100, + stddev / perLoop100, + minimum / perLoop100, + maximum / perLoop100); + } + } +#endif +}; + +void AudioFlinger::PlaybackThread::checkSilentMode_l() +{ + if (!mMasterMute) { + char value[PROPERTY_VALUE_MAX]; + if (property_get("ro.audio.silent", value, "0") > 0) { + char *endptr; + unsigned long ul = strtoul(value, &endptr, 0); + if (*endptr == '\0' && ul != 0) { + ALOGD("Silence is golden"); + // The setprop command will not allow a property to be changed after + // the first time it is set, so we don't have to worry about un-muting. + setMasterMute_l(true); + } + } + } +} + bool AudioFlinger::MixerThread::threadLoop() { Vector< sp<Track> > tracksToRemove; - mixer_state mixerStatus = MIXER_IDLE; nsecs_t standbyTime = systemTime(); size_t mixBufferSize = mFrameCount * mFrameSize; // FIXME: Relaxed timing because of a certain device that can't meet latency @@ -1956,45 +2013,16 @@ bool AudioFlinger::MixerThread::threadLoop() uint32_t sleepTime = idleSleepTime; uint32_t sleepTimeShift = 0; Vector< sp<EffectChain> > effectChains; -#ifdef DEBUG_CPU_USAGE - ThreadCpuUsage cpu; - const CentralTendencyStatistics& stats = cpu.statistics(); -#endif + CpuStats cpuStats; acquireWakeLock(); while (!exitPending()) { -#ifdef DEBUG_CPU_USAGE - cpu.sampleAndEnable(); - unsigned n = stats.n(); - // cpu.elapsed() is expensive, so don't call it every loop - if ((n & 127) == 1) { - long long elapsed = cpu.elapsed(); - if (elapsed >= DEBUG_CPU_USAGE * 1000000000LL) { - double perLoop = elapsed / (double) n; - double perLoop100 = perLoop * 0.01; - double mean = stats.mean(); - double stddev = stats.stddev(); - double minimum = stats.minimum(); - double maximum = stats.maximum(); - cpu.resetStatistics(); - ALOGI("CPU usage over past %.1f secs (%u mixer loops at %.1f mean ms per loop):\n us per mix loop: mean=%.0f stddev=%.0f min=%.0f max=%.0f\n %% of wall: mean=%.1f stddev=%.1f min=%.1f max=%.1f", - elapsed * .000000001, n, perLoop * .000001, - mean * .001, - stddev * .001, - minimum * .001, - maximum * .001, - mean / perLoop100, - stddev / perLoop100, - minimum / perLoop100, - maximum / perLoop100); - } - } -#endif + cpuStats.sample(); processConfigEvents(); - mixerStatus = MIXER_IDLE; + mixer_state mixerStatus = MIXER_IDLE; { // scope for mLock Mutex::Autolock _l(mLock); @@ -2030,20 +2058,13 @@ bool AudioFlinger::MixerThread::threadLoop() releaseWakeLock_l(); // wait until we have something to do... - ALOGV("MixerThread %p TID %d going to sleep", this, gettid()); + ALOGV("Thread %p type %d TID %d going to sleep", this, mType, gettid()); mWaitWorkCV.wait(mLock); - ALOGV("MixerThread %p TID %d waking up", this, gettid()); + ALOGV("Thread %p type %d TID %d waking up", this, mType, gettid()); acquireWakeLock_l(); mPrevMixerStatus = MIXER_IDLE; - if (!mMasterMute) { - char value[PROPERTY_VALUE_MAX]; - property_get("ro.audio.silent", value, "0"); - if (atoi(value)) { - ALOGD("Silence is golden"); - setMasterMute_l(true); - } - } + checkSilentMode_l(); standbyTime = systemTime() + mStandbyTimeInNsecs; sleepTime = idleSleepTime; @@ -2168,7 +2189,7 @@ bool AudioFlinger::MixerThread::threadLoop() releaseWakeLock(); - ALOGV("MixerThread %p exiting", this); + ALOGV("Thread %p type %d exiting", this, mType); return false; } @@ -2686,7 +2707,6 @@ void AudioFlinger::DirectOutputThread::applyVolume(uint16_t leftVol, uint16_t ri bool AudioFlinger::DirectOutputThread::threadLoop() { - mixer_state mixerStatus = MIXER_IDLE; sp<Track> trackToRemove; sp<Track> activeTrack; nsecs_t standbyTime = systemTime(); @@ -2709,8 +2729,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop() processConfigEvents(); - mixerStatus = MIXER_IDLE; - + mixer_state mixerStatus = MIXER_IDLE; { // scope for the mLock Mutex::Autolock _l(mLock); @@ -2727,7 +2746,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop() mSuspended)) { // wait until we have something to do... if (!mStandby) { - ALOGV("Audio hardware entering standby, mixer %p", this); + ALOGV("Audio hardware entering standby, mixer %p, mSuspended %d", this, mSuspended); mOutput->stream->common.standby(&mOutput->stream->common); mStandby = true; mBytesWritten = 0; @@ -2740,19 +2759,12 @@ bool AudioFlinger::DirectOutputThread::threadLoop() if (exitPending()) break; releaseWakeLock_l(); - ALOGV("DirectOutputThread %p TID %d going to sleep", this, gettid()); + ALOGV("Thread %p type %d TID %d going to sleep", this, mType, gettid()); mWaitWorkCV.wait(mLock); - ALOGV("DirectOutputThread %p TID %d waking up in active mode", this, gettid()); + ALOGV("Thread %p type %d TID %d waking up", this, mType, gettid()); acquireWakeLock_l(); - if (!mMasterMute) { - char value[PROPERTY_VALUE_MAX]; - property_get("ro.audio.silent", value, "0"); - if (atoi(value)) { - ALOGD("Silence is golden"); - setMasterMute_l(true); - } - } + checkSilentMode_l(); standbyTime = systemTime() + standbyDelay; sleepTime = idleSleepTime; @@ -2966,7 +2978,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop() releaseWakeLock(); - ALOGV("DirectOutputThread %p exiting", this); + ALOGV("Thread %p type %d exiting", this, mType); return false; } @@ -3083,7 +3095,6 @@ AudioFlinger::DuplicatingThread::~DuplicatingThread() bool AudioFlinger::DuplicatingThread::threadLoop() { Vector< sp<Track> > tracksToRemove; - mixer_state mixerStatus = MIXER_IDLE; nsecs_t standbyTime = systemTime(); size_t mixBufferSize = mFrameCount*mFrameSize; SortedVector< sp<OutputTrack> > outputTracks; @@ -3099,7 +3110,7 @@ bool AudioFlinger::DuplicatingThread::threadLoop() { processConfigEvents(); - mixerStatus = MIXER_IDLE; + mixer_state mixerStatus = MIXER_IDLE; { // scope for the mLock Mutex::Autolock _l(mLock); @@ -3136,20 +3147,13 @@ bool AudioFlinger::DuplicatingThread::threadLoop() if (exitPending()) break; releaseWakeLock_l(); - ALOGV("DuplicatingThread %p TID %d going to sleep", this, gettid()); + // wait until we have something to do... + ALOGV("Thread %p type %d TID %d going to sleep", this, mType, gettid()); mWaitWorkCV.wait(mLock); - ALOGV("DuplicatingThread %p TID %d waking up", this, gettid()); + ALOGV("Thread %p type %d TID %d waking up", this, mType, gettid()); acquireWakeLock_l(); - mPrevMixerStatus = MIXER_IDLE; - if (!mMasterMute) { - char value[PROPERTY_VALUE_MAX]; - property_get("ro.audio.silent", value, "0"); - if (atoi(value)) { - ALOGD("Silence is golden"); - setMasterMute_l(true); - } - } + checkSilentMode_l(); standbyTime = systemTime() + mStandbyTimeInNsecs; sleepTime = idleSleepTime; @@ -3230,6 +3234,7 @@ bool AudioFlinger::DuplicatingThread::threadLoop() releaseWakeLock(); + ALOGV("Thread %p type %d exiting", this, mType); return false; } @@ -3312,7 +3317,6 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( audio_format_t format, uint32_t channelMask, int frameCount, - uint32_t flags, const sp<IMemory>& sharedBuffer, int sessionId) : RefBase(), @@ -3324,7 +3328,7 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( mFrameCount(0), mState(IDLE), mFormat(format), - mFlags(flags & ~SYSTEM_FLAGS_MASK), + mStepServerFailed(false), mSessionId(sessionId) // mChannelCount // mChannelMask @@ -3419,7 +3423,7 @@ bool AudioFlinger::ThreadBase::TrackBase::step() { result = cblk->stepServer(mFrameCount); if (!result) { ALOGV("stepServer failed acquiring cblk mutex"); - mFlags |= STEPSERVER_FAILED; + mStepServerFailed = true; } return result; } @@ -3431,7 +3435,7 @@ void AudioFlinger::ThreadBase::TrackBase::reset() { cblk->server = 0; cblk->userBase = 0; cblk->serverBase = 0; - mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK); + mStepServerFailed = false; ALOGV("TrackBase::reset"); } @@ -3471,7 +3475,7 @@ AudioFlinger::PlaybackThread::Track::Track( int frameCount, const sp<IMemory>& sharedBuffer, int sessionId) - : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, 0, sharedBuffer, sessionId), + : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer, sessionId), mMute(false), mSharedBuffer(sharedBuffer), mName(-1), mMainBuffer(NULL), mAuxBuffer(NULL), mAuxEffectId(0), mHasVolumeController(false) { @@ -3562,10 +3566,10 @@ status_t AudioFlinger::PlaybackThread::Track::getNextBuffer( uint32_t framesReq = buffer->frameCount; // Check if last stepServer failed, try to step now - if (mFlags & TrackBase::STEPSERVER_FAILED) { + if (mStepServerFailed) { if (!step()) goto getNextBuffer_exit; ALOGV("stepServer recovered"); - mFlags &= ~TrackBase::STEPSERVER_FAILED; + mStepServerFailed = false; } framesReady = cblk->framesReady(); @@ -4161,10 +4165,9 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( audio_format_t format, uint32_t channelMask, int frameCount, - uint32_t flags, int sessionId) : TrackBase(thread, client, sampleRate, format, - channelMask, frameCount, flags, 0, sessionId), + channelMask, frameCount, 0 /*sharedBuffer*/, sessionId), mOverflow(false) { if (mCblk != NULL) { @@ -4194,10 +4197,10 @@ status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvi uint32_t framesReq = buffer->frameCount; // Check if last stepServer failed, try to step now - if (mFlags & TrackBase::STEPSERVER_FAILED) { + if (mStepServerFailed) { if (!step()) goto getNextBuffer_exit; ALOGV("stepServer recovered"); - mFlags &= ~TrackBase::STEPSERVER_FAILED; + mStepServerFailed = false; } framesAvail = cblk->framesAvailable_l(); @@ -4660,6 +4663,7 @@ sp<IAudioRecord> AudioFlinger::openRecord( audio_format_t format, uint32_t channelMask, int frameCount, + // FIXME dead, remove from IAudioFlinger uint32_t flags, int *sessionId, status_t *status) @@ -4704,7 +4708,6 @@ sp<IAudioRecord> AudioFlinger::openRecord( format, channelMask, frameCount, - flags, lSessionId, &lStatus); } @@ -4998,7 +5001,6 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createR audio_format_t format, int channelMask, int frameCount, - uint32_t flags, int sessionId, status_t *status) { @@ -5015,7 +5017,7 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createR Mutex::Autolock _l(mLock); track = new RecordTrack(this, client, sampleRate, - format, channelMask, frameCount, flags, sessionId); + format, channelMask, frameCount, sessionId); if (track->getCblk() == 0) { lStatus = NO_MEMORY; diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index 71afc3c..6665bd7 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -312,19 +312,12 @@ private: PAUSED }; - enum track_flags { - STEPSERVER_FAILED = 0x01, // StepServer could not acquire cblk->lock mutex - SYSTEM_FLAGS_MASK = 0x0000ffffUL, - // The upper 16 bits are used for track-specific flags. - }; - TrackBase(ThreadBase *thread, const sp<Client>& client, uint32_t sampleRate, audio_format_t format, uint32_t channelMask, int frameCount, - uint32_t flags, const sp<IMemory>& sharedBuffer, int sessionId); virtual ~TrackBase(); @@ -384,7 +377,7 @@ private: // we don't really need a lock for these track_state mState; const audio_format_t mFormat; - uint32_t mFlags; + bool mStepServerFailed; const int mSessionId; uint8_t mChannelCount; uint32_t mChannelMask; @@ -866,6 +859,9 @@ private: virtual uint32_t idleSleepTimeUs() = 0; virtual uint32_t suspendSleepTimeUs() = 0; + // Code snippets that are temporarily lifted up out of threadLoop() until the merge + void checkSilentMode_l(); + private: friend class AudioFlinger; @@ -1048,7 +1044,6 @@ private: audio_format_t format, uint32_t channelMask, int frameCount, - uint32_t flags, int sessionId); virtual ~RecordTrack(); @@ -1094,7 +1089,6 @@ private: audio_format_t format, int channelMask, int frameCount, - uint32_t flags, int sessionId, status_t *status); diff --git a/services/camera/libcameraservice/CameraHardwareInterface.h b/services/camera/libcameraservice/CameraHardwareInterface.h index 2ac69f78..87a0802 100644 --- a/services/camera/libcameraservice/CameraHardwareInterface.h +++ b/services/camera/libcameraservice/CameraHardwareInterface.h @@ -21,8 +21,6 @@ #include <binder/MemoryBase.h> #include <binder/MemoryHeapBase.h> #include <utils/RefBase.h> -#include <surfaceflinger/ISurface.h> -#include <ui/android_native_buffer.h> #include <ui/GraphicBuffer.h> #include <camera/Camera.h> #include <camera/CameraParameters.h> diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 06fc708..adf1d49 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -29,10 +29,10 @@ #include <cutils/atomic.h> #include <cutils/properties.h> #include <gui/SurfaceTextureClient.h> +#include <gui/Surface.h> #include <hardware/hardware.h> #include <media/AudioSystem.h> #include <media/mediaplayer.h> -#include <surfaceflinger/ISurface.h> #include <utils/Errors.h> #include <utils/Log.h> #include <utils/String16.h> diff --git a/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp b/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp index 1055538..e417b79 100644 --- a/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp +++ b/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp @@ -22,7 +22,6 @@ #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> -#include <surfaceflinger/ISurface.h> #include <camera/Camera.h> #include <camera/CameraParameters.h> #include <ui/GraphicBuffer.h> |