Merge "Various fixes and improvements in audio effects implementation" into gingerbread
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 80d0d2b..33696f4 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -1,5 +1,3 @@
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -72,5 +70,3 @@
LOCAL_MODULE:= audioloop
include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 9e606d9..3662983 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -39,7 +39,6 @@
enum player_type {
PV_PLAYER = 1,
SONIVOX_PLAYER = 2,
- VORBIS_PLAYER = 3,
STAGEFRIGHT_PLAYER = 4,
// Test players are available only in the 'test' and 'eng' builds.
// The shared library with the test player is passed passed as an
diff --git a/include/media/stagefright/AMRWriter.h b/include/media/stagefright/AMRWriter.h
index b0eaba4..813dd43 100644
--- a/include/media/stagefright/AMRWriter.h
+++ b/include/media/stagefright/AMRWriter.h
@@ -26,6 +26,7 @@
namespace android {
struct MediaSource;
+struct MetaData;
struct AMRWriter : public MediaWriter {
AMRWriter(const char *filename);
@@ -35,7 +36,7 @@
virtual status_t addSource(const sp<MediaSource> &source);
virtual bool reachedEOS();
- virtual status_t start();
+ virtual status_t start(MetaData *params = NULL);
virtual void stop();
virtual void pause();
diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h
index f2001e1..628200d 100644
--- a/include/media/stagefright/AudioSource.h
+++ b/include/media/stagefright/AudioSource.h
@@ -39,6 +39,9 @@
virtual status_t stop();
virtual sp<MetaData> getFormat();
+ // Returns the maximum amplitude since last call.
+ int16_t getMaxAmplitude();
+
virtual status_t read(
MediaBuffer **buffer, const ReadOptions *options = NULL);
@@ -53,13 +56,17 @@
bool mStarted;
bool mCollectStats;
+ bool mTrackMaxAmplitude;
int64_t mTotalReadTimeUs;
int64_t mTotalReadBytes;
int64_t mTotalReads;
int64_t mStartTimeUs;
+ int16_t mMaxAmplitude;
MediaBufferGroup *mGroup;
+ void trackMaxAmplitude(int16_t *data, int nSamples);
+
AudioSource(const AudioSource &);
AudioSource &operator=(const AudioSource &);
};
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 39d0ea1..7a2de1e 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -36,7 +36,7 @@
MPEG4Writer(int fd);
virtual status_t addSource(const sp<MediaSource> &source);
- virtual status_t start();
+ virtual status_t start(MetaData *param = NULL);
virtual bool reachedEOS();
virtual void stop();
virtual void pause();
@@ -83,6 +83,7 @@
int64_t getStartTimestampUs(); // Not const
status_t startTracks();
size_t numTracks();
+ int64_t estimateMoovBoxSize(int32_t bitRate);
void lock();
void unlock();
diff --git a/include/media/stagefright/MediaWriter.h b/include/media/stagefright/MediaWriter.h
index 8528203..46aaf7c 100644
--- a/include/media/stagefright/MediaWriter.h
+++ b/include/media/stagefright/MediaWriter.h
@@ -24,13 +24,14 @@
namespace android {
struct MediaSource;
+struct MetaData;
struct MediaWriter : public RefBase {
MediaWriter() {}
virtual status_t addSource(const sp<MediaSource> &source) = 0;
virtual bool reachedEOS() = 0;
- virtual status_t start() = 0;
+ virtual status_t start(MetaData *params = NULL) = 0;
virtual void stop() = 0;
virtual void pause() = 0;
virtual void setMaxFileSize(int64_t bytes) { mMaxFileSizeLimitBytes = bytes; }
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 6a20602..d28d1ca 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -36,13 +36,14 @@
kKeyStride = 'strd', // int32_t
kKeySliceHeight = 'slht', // int32_t
kKeyChannelCount = '#chn', // int32_t
- kKeySampleRate = 'srte', // int32_t
+ kKeySampleRate = 'srte', // int32_t (also video frame rate)
kKeyBitRate = 'brte', // int32_t (bps)
kKeyESDS = 'esds', // raw data
kKeyAVCC = 'avcc', // raw data
kKeyVorbisInfo = 'vinf', // raw data
kKeyVorbisBooks = 'vboo', // raw data
kKeyWantsNALFragments = 'NALf',
+ kKey64BitFileOffset = 'fobt', // int32_t (bool)
kKeyIsSyncFrame = 'sync', // int32_t (bool)
kKeyIsCodecConfig = 'conf', // int32_t (bool)
kKeyTime = 'time', // int64_t (usecs)
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index 3b678cb..8f010c9 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -11,21 +11,11 @@
MediaPlayerService.cpp \
MetadataRetrieverClient.cpp \
TestPlayerStub.cpp \
- VorbisPlayer.cpp \
- VorbisMetadataRetriever.cpp \
- MidiMetadataRetriever.cpp \
- MidiFile.cpp
-
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
-LOCAL_SRC_FILES += \
- StagefrightPlayer.cpp \
+ MidiMetadataRetriever.cpp \
+ MidiFile.cpp \
+ StagefrightPlayer.cpp \
StagefrightRecorder.cpp
-LOCAL_CFLAGS += -DBUILD_WITH_FULL_STAGEFRIGHT=1
-
-endif
-
ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
LOCAL_LDLIBS += -ldl -lpthread
endif
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index d45c17b..82d5c14 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -56,7 +56,6 @@
#include "MetadataRetrieverClient.h"
#include "MidiFile.h"
-#include "VorbisPlayer.h"
#include <media/PVPlayer.h>
#include "TestPlayerStub.h"
#include "StagefrightPlayer.h"
@@ -197,8 +196,6 @@
{".rtttl", SONIVOX_PLAYER},
{".rtx", SONIVOX_PLAYER},
{".ota", SONIVOX_PLAYER},
- {".ogg", VORBIS_PLAYER},
- {".oga", VORBIS_PLAYER},
#ifndef NO_OPENCORE
{".wma", PV_PLAYER},
{".wmv", PV_PLAYER},
@@ -666,37 +663,9 @@
}
static player_type getDefaultPlayerType() {
-#if BUILD_WITH_FULL_STAGEFRIGHT
- char value[PROPERTY_VALUE_MAX];
- if (property_get("media.stagefright.enable-player", value, NULL)
- && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
- return STAGEFRIGHT_PLAYER;
- }
-#endif
-
- return PV_PLAYER;
+ return STAGEFRIGHT_PLAYER;
}
-// By default we use the VORBIS_PLAYER for vorbis playback (duh!),
-// but if the magic property is set we will use our new experimental
-// stagefright code instead.
-static player_type OverrideStagefrightForVorbis(player_type player) {
- if (player != VORBIS_PLAYER) {
- return player;
- }
-
-#if BUILD_WITH_FULL_STAGEFRIGHT
- char value[PROPERTY_VALUE_MAX];
- if (property_get("media.stagefright.enable-vorbis", value, NULL)
- && (!strcmp(value, "1") || !strcmp(value, "true"))) {
- return STAGEFRIGHT_PLAYER;
- }
-#endif
-
- return VORBIS_PLAYER;
-}
-
-
player_type getPlayerType(int fd, int64_t offset, int64_t length)
{
char buf[20];
@@ -708,7 +677,7 @@
// Ogg vorbis?
if (ident == 0x5367674f) // 'OggS'
- return OverrideStagefrightForVorbis(VORBIS_PLAYER);
+ return STAGEFRIGHT_PLAYER;
#ifndef NO_OPENCORE
if (ident == 0x75b22630) {
@@ -744,13 +713,6 @@
return TEST_PLAYER;
}
- bool useStagefrightForHTTP = false;
- char value[PROPERTY_VALUE_MAX];
- if (property_get("media.stagefright.enable-http", value, NULL)
- && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
- useStagefrightForHTTP = true;
- }
-
// use MidiFile for MIDI extensions
int lenURL = strlen(url);
for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
@@ -758,22 +720,11 @@
int start = lenURL - len;
if (start > 0) {
if (!strncasecmp(url + start, FILE_EXTS[i].extension, len)) {
- if (FILE_EXTS[i].playertype == VORBIS_PLAYER
- && !strncasecmp(url, "http://", 7)
- && useStagefrightForHTTP) {
- return STAGEFRIGHT_PLAYER;
- }
- return OverrideStagefrightForVorbis(FILE_EXTS[i].playertype);
+ return FILE_EXTS[i].playertype;
}
}
}
- if (!strncasecmp(url, "http://", 7)) {
- if (!useStagefrightForHTTP) {
- return PV_PLAYER;
- }
- }
-
if (!strncasecmp(url, "rtsp://", 7)) {
char value[PROPERTY_VALUE_MAX];
if (!property_get("media.stagefright.enable-rtsp", value, NULL)
@@ -802,16 +753,10 @@
LOGV(" create MidiFile");
p = new MidiFile();
break;
- case VORBIS_PLAYER:
- LOGV(" create VorbisPlayer");
- p = new VorbisPlayer();
- break;
-#if BUILD_WITH_FULL_STAGEFRIGHT
case STAGEFRIGHT_PLAYER:
LOGV(" create StagefrightPlayer");
p = new StagefrightPlayer;
break;
-#endif
case TEST_PLAYER:
LOGV("Create Test Player stub");
p = new TestPlayerStub();
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index c507669..084f039 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -294,13 +294,11 @@
LOGV("Client constructor");
mPid = pid;
-#if BUILD_WITH_FULL_STAGEFRIGHT
char value[PROPERTY_VALUE_MAX];
if (property_get("media.stagefright.enable-record", value, NULL)
&& (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
mRecorder = new StagefrightRecorder;
} else
-#endif
#ifndef NO_OPENCORE
{
mRecorder = new PVMediaRecorder();
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 550b84d..ca229fa 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -37,7 +37,6 @@
#include <media/MediaPlayerInterface.h>
#include <media/PVMetadataRetriever.h>
#include <private/media/VideoFrame.h>
-#include "VorbisMetadataRetriever.h"
#include "MidiMetadataRetriever.h"
#include "MetadataRetrieverClient.h"
#include "StagefrightMetadataRetriever.h"
@@ -103,30 +102,17 @@
{
sp<MediaMetadataRetrieverBase> p;
switch (playerType) {
-#if BUILD_WITH_FULL_STAGEFRIGHT
case STAGEFRIGHT_PLAYER:
{
- char value[PROPERTY_VALUE_MAX];
- if (property_get("media.stagefright.enable-meta", value, NULL)
- && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
- LOGV("create StagefrightMetadataRetriever");
- p = new StagefrightMetadataRetriever;
- break;
- }
-
- // fall through
+ p = new StagefrightMetadataRetriever;
+ break;
}
-#endif
#ifndef NO_OPENCORE
case PV_PLAYER:
LOGV("create pv metadata retriever");
p = new PVMetadataRetriever();
break;
#endif
- case VORBIS_PLAYER:
- LOGV("create vorbis metadata retriever");
- p = new VorbisMetadataRetriever();
- break;
case SONIVOX_PLAYER:
LOGV("create midi metadata retriever");
p = new MidiMetadataRetriever();
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index d49c4e0..6834491 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -316,6 +316,13 @@
return OK;
}
+status_t StagefrightRecorder::setParam64BitFileOffset(bool use64Bit) {
+ LOGV("setParam64BitFileOffset: %s",
+ use64Bit? "use 64 bit file offset": "use 32 bit file offset");
+ mUse64BitFileOffset = use64Bit;
+ return OK;
+}
+
status_t StagefrightRecorder::setParameter(
const String8 &key, const String8 &value) {
LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
@@ -361,6 +368,11 @@
if (safe_strtoi32(value.string(), &interval)) {
return setParamIFramesInterval(interval);
}
+ } else if (key == "param-use-64bit-offset") {
+ int32_t use64BitOffset;
+ if (safe_strtoi32(value.string(), &use64BitOffset)) {
+ return setParam64BitFileOffset(use64BitOffset != 0);
+ }
} else {
LOGE("setParameter: failed to find key %s", key.string());
}
@@ -484,6 +496,7 @@
sp<MediaSource> audioEncoder =
OMXCodec::Create(client.interface(), encMeta,
true /* createEncoder */, audioSource);
+ mAudioSourceNode = audioSource;
return audioEncoder;
}
@@ -632,6 +645,7 @@
status_t StagefrightRecorder::startMPEG4Recording() {
mWriter = new MPEG4Writer(dup(mOutputFd));
+ int32_t totalBitRate = 0;
// Add audio source first if it exists
if (mAudioSource != AUDIO_SOURCE_LIST_END) {
@@ -650,7 +664,7 @@
if (audioEncoder == NULL) {
return UNKNOWN_ERROR;
}
-
+ totalBitRate += mAudioBitRate;
mWriter->addSource(audioEncoder);
}
if (mVideoSource == VIDEO_SOURCE_DEFAULT
@@ -703,7 +717,7 @@
sp<MetaData> enc_meta = new MetaData;
enc_meta->setInt32(kKeyBitRate, mVideoBitRate);
- enc_meta->setInt32(kKeySampleRate, mFrameRate); // XXX: kKeySampleRate?
+ enc_meta->setInt32(kKeySampleRate, mFrameRate);
switch (mVideoEncoder) {
case VIDEO_ENCODER_H263:
@@ -746,12 +760,13 @@
true /* createEncoder */, cameraSource);
CHECK(mOutputFd >= 0);
+ totalBitRate += mVideoBitRate;
mWriter->addSource(encoder);
}
{
// MPEGWriter specific handling
- MPEG4Writer *writer = ((MPEG4Writer *) mWriter.get()); // mWriter is an MPEGWriter
+ MPEG4Writer *writer = ((MPEG4Writer *) mWriter.get());
writer->setInterleaveDuration(mInterleaveDurationUs);
}
@@ -762,7 +777,10 @@
mWriter->setMaxFileSize(mMaxFileSizeBytes);
}
mWriter->setListener(mListener);
- mWriter->start();
+ sp<MetaData> meta = new MetaData;
+ meta->setInt32(kKeyBitRate, totalBitRate);
+ meta->setInt32(kKey64BitFileOffset, mUse64BitFileOffset);
+ mWriter->start(meta.get());
return OK;
}
@@ -822,6 +840,8 @@
mAudioBitRate = 12200;
mInterleaveDurationUs = 0;
mIFramesInterval = 1;
+ mAudioSourceNode = 0;
+ mUse64BitFileOffset = false;
mEncoderProfiles = MediaProfiles::getInstance();
mOutputFd = -1;
@@ -831,7 +851,11 @@
}
status_t StagefrightRecorder::getMaxAmplitude(int *max) {
- *max = 0;
+ if (mAudioSourceNode != 0) {
+ *max = mAudioSourceNode->getMaxAmplitude();
+ } else {
+ *max = 0;
+ }
return OK;
}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 7de96f6..2943e97 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -26,6 +26,7 @@
class Camera;
struct MediaSource;
struct MediaWriter;
+struct AudioSource;
class MediaProfiles;
struct StagefrightRecorder : public MediaRecorderBase {
@@ -64,12 +65,14 @@
sp<ISurface> mPreviewSurface;
sp<IMediaPlayerClient> mListener;
sp<MediaWriter> mWriter;
+ sp<AudioSource> mAudioSourceNode;
audio_source mAudioSource;
video_source mVideoSource;
output_format mOutputFormat;
audio_encoder mAudioEncoder;
video_encoder mVideoEncoder;
+ bool mUse64BitFileOffset;
int32_t mVideoWidth, mVideoHeight;
int32_t mFrameRate;
int32_t mVideoBitRate;
@@ -98,6 +101,7 @@
status_t setParamAudioSamplingRate(int32_t sampleRate);
status_t setParamInterleaveDuration(int32_t durationUs);
status_t setParamIFramesInterval(int32_t interval);
+ status_t setParam64BitFileOffset(bool use64BitFileOffset);
status_t setParamMaxDurationOrFileSize(int64_t limit, bool limit_is_duration);
void clipVideoBitRate();
void clipVideoFrameRate();
diff --git a/media/libmediaplayerservice/VorbisMetadataRetriever.cpp b/media/libmediaplayerservice/VorbisMetadataRetriever.cpp
deleted file mode 100644
index eac74fc..0000000
--- a/media/libmediaplayerservice/VorbisMetadataRetriever.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-**
-** Copyright 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.
-*/
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "VorbisMetadataRetriever"
-#include <utils/Log.h>
-
-#include "VorbisMetadataRetriever.h"
-#include <media/mediametadataretriever.h>
-#
-
-namespace android {
-
-void VorbisMetadataRetriever::clearMetadataValues()
-{
- LOGV("cleearMetadataValues");
- mMetadataValues[0][0] = '\0';
-}
-
-status_t VorbisMetadataRetriever::setDataSource(const char *url)
-{
- LOGV("setDataSource: url(%s)", url? url: "NULL pointer");
- Mutex::Autolock lock(mLock);
- clearMetadataValues();
- if (mVorbisPlayer == 0) {
- mVorbisPlayer = new VorbisPlayer();
- }
- // TODO: support headers in MetadataRetriever interface!
- return mVorbisPlayer->setDataSource(url, NULL /* headers */);
-}
-
-status_t VorbisMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length)
-{
- LOGV("setDataSource: fd(%d), offset(%lld), and length(%lld)", fd, offset, length);
- Mutex::Autolock lock(mLock);
- clearMetadataValues();
- if (mVorbisPlayer == 0) {
- mVorbisPlayer = new VorbisPlayer();
- }
- return mVorbisPlayer->setDataSource(fd, offset, length);
-}
-
-const char* VorbisMetadataRetriever::extractMetadata(int keyCode)
-{
- LOGV("extractMetadata: key(%d)", keyCode);
- Mutex::Autolock lock(mLock);
- if (mVorbisPlayer == 0 || mVorbisPlayer->initCheck() != NO_ERROR) {
- LOGE("no vorbis player is initialized yet");
- return NULL;
- }
- switch (keyCode) {
- case METADATA_KEY_DURATION:
- {
- if (mMetadataValues[0][0] == '\0') {
- int duration = -1;
- if (mVorbisPlayer->getDuration(&duration) != NO_ERROR) {
- LOGE("failed to get duration");
- return NULL;
- }
- snprintf(mMetadataValues[0], MAX_METADATA_STRING_LENGTH, "%d", duration);
- }
- LOGV("duration: %s ms", mMetadataValues[0]);
- return mMetadataValues[0];
- }
- default:
- LOGE("Unsupported key code (%d)", keyCode);
- return NULL;
- }
- return NULL;
-}
-
-};
-
diff --git a/media/libmediaplayerservice/VorbisMetadataRetriever.h b/media/libmediaplayerservice/VorbisMetadataRetriever.h
deleted file mode 100644
index 1c57fe3..0000000
--- a/media/libmediaplayerservice/VorbisMetadataRetriever.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_VORBISMETADATARETRIEVER_H
-#define ANDROID_VORBISMETADATARETRIEVER_H
-
-#include <utils/threads.h>
-#include <utils/Errors.h>
-#include <media/MediaMetadataRetrieverInterface.h>
-
-#include "VorbisPlayer.h"
-
-namespace android {
-
-class VorbisMetadataRetriever : public MediaMetadataRetrieverInterface {
-public:
- VorbisMetadataRetriever() {}
- ~VorbisMetadataRetriever() {}
-
- virtual status_t setDataSource(const char *url);
- virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
- virtual const char* extractMetadata(int keyCode);
-
-private:
- static const uint32_t MAX_METADATA_STRING_LENGTH = 128;
- void clearMetadataValues();
-
- Mutex mLock;
- sp<VorbisPlayer> mVorbisPlayer;
- char mMetadataValues[1][MAX_METADATA_STRING_LENGTH];
-};
-
-}; // namespace android
-
-#endif // ANDROID_VORBISMETADATARETRIEVER_H
diff --git a/media/libmediaplayerservice/VorbisPlayer.cpp b/media/libmediaplayerservice/VorbisPlayer.cpp
deleted file mode 100644
index 8181999..0000000
--- a/media/libmediaplayerservice/VorbisPlayer.cpp
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
-** Copyright 2007, 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 "VorbisPlayer"
-#include "utils/Log.h"
-
-#include <stdio.h>
-#include <assert.h>
-#include <limits.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sched.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-
-#include "VorbisPlayer.h"
-
-#ifdef HAVE_GETTID
-static pid_t myTid() { return gettid(); }
-#else
-static pid_t myTid() { return getpid(); }
-#endif
-
-// ----------------------------------------------------------------------------
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-// TODO: Determine appropriate return codes
-static status_t ERROR_NOT_OPEN = -1;
-static status_t ERROR_OPEN_FAILED = -2;
-static status_t ERROR_ALLOCATE_FAILED = -4;
-static status_t ERROR_NOT_SUPPORTED = -8;
-static status_t ERROR_NOT_READY = -16;
-static status_t STATE_INIT = 0;
-static status_t STATE_ERROR = 1;
-static status_t STATE_OPEN = 2;
-
-
-VorbisPlayer::VorbisPlayer() :
- mAudioBuffer(NULL), mPlayTime(-1), mDuration(-1), mState(STATE_ERROR),
- mStreamType(AudioSystem::MUSIC), mLoop(false), mAndroidLoop(false),
- mExit(false), mPaused(false), mRender(false), mRenderTid(-1)
-{
- LOGV("constructor\n");
- memset(&mVorbisFile, 0, sizeof mVorbisFile);
-}
-
-void VorbisPlayer::onFirstRef()
-{
- LOGV("onFirstRef");
- // create playback thread
- Mutex::Autolock l(mMutex);
- createThreadEtc(renderThread, this, "vorbis decoder", ANDROID_PRIORITY_AUDIO);
- mCondition.wait(mMutex);
- if (mRenderTid > 0) {
- LOGV("render thread(%d) started", mRenderTid);
- mState = STATE_INIT;
- }
-}
-
-status_t VorbisPlayer::initCheck()
-{
- if (mState != STATE_ERROR) return NO_ERROR;
- return ERROR_NOT_READY;
-}
-
-VorbisPlayer::~VorbisPlayer() {
- LOGV("VorbisPlayer destructor\n");
- release();
-}
-
-status_t VorbisPlayer::setDataSource(
- const char *uri, const KeyedVector<String8, String8> *headers) {
- return setdatasource(uri, -1, 0, 0x7ffffffffffffffLL); // intentionally less than LONG_MAX
-}
-
-status_t VorbisPlayer::setDataSource(int fd, int64_t offset, int64_t length)
-{
- return setdatasource(NULL, fd, offset, length);
-}
-
-size_t VorbisPlayer::vp_fread(void *buf, size_t size, size_t nmemb, void *me) {
- VorbisPlayer *self = (VorbisPlayer*) me;
-
- long curpos = vp_ftell(me);
- while (nmemb != 0 && (curpos + size * nmemb) > self->mLength) {
- nmemb--;
- }
- return fread(buf, size, nmemb, self->mFile);
-}
-
-int VorbisPlayer::vp_fseek(void *me, ogg_int64_t off, int whence) {
- VorbisPlayer *self = (VorbisPlayer*) me;
- if (whence == SEEK_SET)
- return fseek(self->mFile, off + self->mOffset, whence);
- else if (whence == SEEK_CUR)
- return fseek(self->mFile, off, whence);
- else if (whence == SEEK_END)
- return fseek(self->mFile, self->mOffset + self->mLength + off, SEEK_SET);
- return -1;
-}
-
-int VorbisPlayer::vp_fclose(void *me) {
- LOGV("vp_fclose");
- VorbisPlayer *self = (VorbisPlayer*) me;
- int ret = fclose (self->mFile);
- self->mFile = NULL;
- return ret;
-}
-
-long VorbisPlayer::vp_ftell(void *me) {
- VorbisPlayer *self = (VorbisPlayer*) me;
- return ftell(self->mFile) - self->mOffset;
-}
-
-status_t VorbisPlayer::setdatasource(const char *path, int fd, int64_t offset, int64_t length)
-{
- LOGV("setDataSource url=%s, fd=%d\n", path, fd);
-
- // file still open?
- Mutex::Autolock l(mMutex);
- if (mState == STATE_OPEN) {
- reset_nosync();
- }
-
- // open file and set paused state
- if (path) {
- mFile = fopen(path, "r");
- } else {
- mFile = fdopen(dup(fd), "r");
- }
- if (mFile == NULL) {
- return ERROR_OPEN_FAILED;
- }
-
- struct stat sb;
- int ret;
- if (path) {
- ret = stat(path, &sb);
- } else {
- ret = fstat(fd, &sb);
- }
- if (ret != 0) {
- mState = STATE_ERROR;
- fclose(mFile);
- return ERROR_OPEN_FAILED;
- }
- if (sb.st_size > (length + offset)) {
- mLength = length;
- } else {
- mLength = sb.st_size - offset;
- }
-
- ov_callbacks callbacks = {
- (size_t (*)(void *, size_t, size_t, void *)) vp_fread,
- (int (*)(void *, ogg_int64_t, int)) vp_fseek,
- (int (*)(void *)) vp_fclose,
- (long (*)(void *)) vp_ftell
- };
-
- mOffset = offset;
- fseek(mFile, offset, SEEK_SET);
-
- int result = ov_open_callbacks(this, &mVorbisFile, NULL, 0, callbacks);
- if (result < 0) {
- LOGE("ov_open() failed: [%d]\n", (int)result);
- mState = STATE_ERROR;
- fclose(mFile);
- return ERROR_OPEN_FAILED;
- }
-
- // look for the android loop tag (for ringtones)
- char **ptr = ov_comment(&mVorbisFile,-1)->user_comments;
- while(*ptr) {
- // does the comment start with ANDROID_LOOP_TAG
- if(strncmp(*ptr, ANDROID_LOOP_TAG, strlen(ANDROID_LOOP_TAG)) == 0) {
- // read the value of the tag
- char *val = *ptr + strlen(ANDROID_LOOP_TAG) + 1;
- mAndroidLoop = (strncmp(val, "true", 4) == 0);
- }
- // we keep parsing even after finding one occurence of ANDROID_LOOP_TAG,
- // as we could find another one (the tag might have been appended more than once).
- ++ptr;
- }
- LOGV_IF(mAndroidLoop, "looped sound");
-
- mState = STATE_OPEN;
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::prepare()
-{
- LOGV("prepare\n");
- if (mState != STATE_OPEN ) {
- return ERROR_NOT_OPEN;
- }
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::prepareAsync() {
- LOGV("prepareAsync\n");
- // can't hold the lock here because of the callback
- // it's safe because we don't change state
- if (mState != STATE_OPEN ) {
- sendEvent(MEDIA_ERROR);
- return NO_ERROR;
- }
- sendEvent(MEDIA_PREPARED);
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::start()
-{
- LOGV("start\n");
- Mutex::Autolock l(mMutex);
- if (mState != STATE_OPEN) {
- return ERROR_NOT_OPEN;
- }
-
- mPaused = false;
- mRender = true;
-
- // wake up render thread
- LOGV(" wakeup render thread\n");
- mCondition.signal();
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::stop()
-{
- LOGV("stop\n");
- Mutex::Autolock l(mMutex);
- if (mState != STATE_OPEN) {
- return ERROR_NOT_OPEN;
- }
- mPaused = true;
- mRender = false;
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::seekTo(int position)
-{
- LOGV("seekTo %d\n", position);
- Mutex::Autolock l(mMutex);
- if (mState != STATE_OPEN) {
- return ERROR_NOT_OPEN;
- }
-
- int result = ov_time_seek(&mVorbisFile, position);
- if (result != 0) {
- LOGE("ov_time_seek() returned %d\n", result);
- return result;
- }
- sendEvent(MEDIA_SEEK_COMPLETE);
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::pause()
-{
- LOGV("pause\n");
- Mutex::Autolock l(mMutex);
- if (mState != STATE_OPEN) {
- return ERROR_NOT_OPEN;
- }
- mPaused = true;
- return NO_ERROR;
-}
-
-bool VorbisPlayer::isPlaying()
-{
- LOGV("isPlaying\n");
- if (mState == STATE_OPEN) {
- return mRender;
- }
- return false;
-}
-
-status_t VorbisPlayer::getCurrentPosition(int* position)
-{
- LOGV("getCurrentPosition\n");
- Mutex::Autolock l(mMutex);
- if (mState != STATE_OPEN) {
- LOGE("getCurrentPosition(): file not open");
- return ERROR_NOT_OPEN;
- }
- *position = ov_time_tell(&mVorbisFile);
- if (*position < 0) {
- LOGE("getCurrentPosition(): ov_time_tell returned %d", *position);
- return *position;
- }
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::getDuration(int* duration)
-{
- LOGV("getDuration\n");
- Mutex::Autolock l(mMutex);
- if (mState != STATE_OPEN) {
- return ERROR_NOT_OPEN;
- }
-
- int ret = ov_time_total(&mVorbisFile, -1);
- if (ret == OV_EINVAL) {
- return -1;
- }
-
- *duration = ret;
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::release()
-{
- LOGV("release\n");
- Mutex::Autolock l(mMutex);
- reset_nosync();
-
- // TODO: timeout when thread won't exit
- // wait for render thread to exit
- if (mRenderTid > 0) {
- mExit = true;
- mCondition.signal();
- mCondition.wait(mMutex);
- }
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::reset()
-{
- LOGV("reset\n");
- Mutex::Autolock l(mMutex);
- return reset_nosync();
-}
-
-// always call with lock held
-status_t VorbisPlayer::reset_nosync()
-{
- // close file
- if (mFile != NULL) {
- ov_clear(&mVorbisFile); // this also closes the FILE
- if (mFile != NULL) {
- LOGV("OOPS! Vorbis didn't close the file");
- fclose(mFile);
- mFile = NULL;
- }
- }
- mState = STATE_ERROR;
-
- mPlayTime = -1;
- mDuration = -1;
- mLoop = false;
- mAndroidLoop = false;
- mPaused = false;
- mRender = false;
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::setLooping(int loop)
-{
- LOGV("setLooping\n");
- Mutex::Autolock l(mMutex);
- mLoop = (loop != 0);
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::createOutputTrack() {
- // open audio track
- vorbis_info *vi = ov_info(&mVorbisFile, -1);
-
- LOGV("Create AudioTrack object: rate=%ld, channels=%d\n",
- vi->rate, vi->channels);
- if (mAudioSink->open(vi->rate, vi->channels, AudioSystem::PCM_16_BIT, DEFAULT_AUDIOSINK_BUFFERCOUNT) != NO_ERROR) {
- LOGE("mAudioSink open failed");
- return ERROR_OPEN_FAILED;
- }
- return NO_ERROR;
-}
-
-int VorbisPlayer::renderThread(void* p) {
- return ((VorbisPlayer*)p)->render();
-}
-
-#define AUDIOBUFFER_SIZE 4096
-
-int VorbisPlayer::render() {
- int result = -1;
- int temp;
- int current_section = 0;
- bool audioStarted = false;
-
- LOGV("render\n");
-
- // allocate render buffer
- mAudioBuffer = new char[AUDIOBUFFER_SIZE];
- if (!mAudioBuffer) {
- LOGE("mAudioBuffer allocate failed\n");
- goto threadExit;
- }
-
- // let main thread know we're ready
- {
- Mutex::Autolock l(mMutex);
- mRenderTid = myTid();
- mCondition.signal();
- }
-
- while (1) {
- long numread = 0;
- {
- Mutex::Autolock l(mMutex);
-
- // pausing?
- if (mPaused) {
- if (mAudioSink->ready()) mAudioSink->pause();
- mRender = false;
- audioStarted = false;
- }
-
- // nothing to render, wait for client thread to wake us up
- if (!mExit && !mRender) {
- LOGV("render - signal wait\n");
- mCondition.wait(mMutex);
- LOGV("render - signal rx'd\n");
- }
- if (mExit) break;
-
- // We could end up here if start() is called, and before we get a
- // chance to run, the app calls stop() or reset(). Re-check render
- // flag so we don't try to render in stop or reset state.
- if (!mRender) continue;
-
- // render vorbis data into the input buffer
- numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, ¤t_section);
- if (numread == 0) {
- // end of file, do we need to loop?
- // ...
- if (mLoop || mAndroidLoop) {
- ov_time_seek(&mVorbisFile, 0);
- current_section = 0;
- numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, ¤t_section);
- } else {
- mAudioSink->stop();
- audioStarted = false;
- mRender = false;
- mPaused = true;
- int endpos = ov_time_tell(&mVorbisFile);
-
- LOGV("send MEDIA_PLAYBACK_COMPLETE");
- sendEvent(MEDIA_PLAYBACK_COMPLETE);
-
- // wait until we're started again
- LOGV("playback complete - wait for signal");
- mCondition.wait(mMutex);
- LOGV("playback complete - signal rx'd");
- if (mExit) break;
-
- // if we're still at the end, restart from the beginning
- if (mState == STATE_OPEN) {
- int curpos = ov_time_tell(&mVorbisFile);
- if (curpos == endpos) {
- ov_time_seek(&mVorbisFile, 0);
- }
- current_section = 0;
- numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, ¤t_section);
- }
- }
- }
- }
-
- // codec returns negative number on error
- if (numread < 0) {
- LOGE("Error in Vorbis decoder");
- sendEvent(MEDIA_ERROR);
- break;
- }
-
- // create audio output track if necessary
- if (!mAudioSink->ready()) {
- LOGV("render - create output track\n");
- if (createOutputTrack() != NO_ERROR)
- break;
- }
-
- // Write data to the audio hardware
- if ((temp = mAudioSink->write(mAudioBuffer, numread)) < 0) {
- LOGE("Error in writing:%d",temp);
- result = temp;
- break;
- }
-
- // start audio output if necessary
- if (!audioStarted && !mPaused && !mExit) {
- LOGV("render - starting audio\n");
- mAudioSink->start();
- audioStarted = true;
- }
- }
-
-threadExit:
- mAudioSink.clear();
- if (mAudioBuffer) {
- delete [] mAudioBuffer;
- mAudioBuffer = NULL;
- }
-
- // tell main thread goodbye
- Mutex::Autolock l(mMutex);
- mRenderTid = -1;
- mCondition.signal();
- return result;
-}
-
-} // end namespace android
diff --git a/media/libmediaplayerservice/VorbisPlayer.h b/media/libmediaplayerservice/VorbisPlayer.h
deleted file mode 100644
index 4a50835..0000000
--- a/media/libmediaplayerservice/VorbisPlayer.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-**
-** Copyright 2008, 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_VORBISPLAYER_H
-#define ANDROID_VORBISPLAYER_H
-
-#include <utils/threads.h>
-
-#include <media/MediaPlayerInterface.h>
-#include <media/AudioTrack.h>
-
-#include "ivorbiscodec.h"
-#include "ivorbisfile.h"
-
-#define ANDROID_LOOP_TAG "ANDROID_LOOP"
-
-namespace android {
-
-class VorbisPlayer : public MediaPlayerInterface {
-public:
- VorbisPlayer();
- ~VorbisPlayer();
-
- virtual void onFirstRef();
- virtual status_t initCheck();
-
- virtual status_t setDataSource(
- const char *uri, const KeyedVector<String8, String8> *headers);
-
- virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
- virtual status_t setVideoSurface(const sp<ISurface>& surface) { return UNKNOWN_ERROR; }
- virtual status_t prepare();
- virtual status_t prepareAsync();
- virtual status_t start();
- virtual status_t stop();
- virtual status_t seekTo(int msec);
- virtual status_t pause();
- virtual bool isPlaying();
- virtual status_t getCurrentPosition(int* msec);
- virtual status_t getDuration(int* msec);
- virtual status_t release();
- virtual status_t reset();
- virtual status_t setLooping(int loop);
- virtual player_type playerType() { return VORBIS_PLAYER; }
- virtual status_t invoke(const Parcel& request, Parcel *reply) {return INVALID_OPERATION;}
-
-private:
- status_t setdatasource(const char *path, int fd, int64_t offset, int64_t length);
- status_t reset_nosync();
- status_t createOutputTrack();
- static int renderThread(void*);
- int render();
-
- static size_t vp_fread(void *, size_t, size_t, void *);
- static int vp_fseek(void *, ogg_int64_t, int);
- static int vp_fclose(void *);
- static long vp_ftell(void *);
-
- Mutex mMutex;
- Condition mCondition;
- FILE* mFile;
- int64_t mOffset;
- int64_t mLength;
- OggVorbis_File mVorbisFile;
- char* mAudioBuffer;
- int mPlayTime;
- int mDuration;
- status_t mState;
- int mStreamType;
- bool mLoop;
- bool mAndroidLoop;
- volatile bool mExit;
- bool mPaused;
- volatile bool mRender;
- pid_t mRenderTid;
-};
-
-}; // namespace android
-
-#endif // ANDROID_VORBISPLAYER_H
diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp
index 8951f5b..6d1dd16 100644
--- a/media/libstagefright/AMRWriter.cpp
+++ b/media/libstagefright/AMRWriter.cpp
@@ -97,7 +97,7 @@
return OK;
}
-status_t AMRWriter::start() {
+status_t AMRWriter::start(MetaData *params) {
if (mInitCheck != OK) {
return mInitCheck;
}
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 00a6995..60d0233 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -3,51 +3,44 @@
include frameworks/base/media/libstagefright/codecs/common/Config.mk
-LOCAL_SRC_FILES:= \
- ESDS.cpp \
- MediaBuffer.cpp \
- MediaBufferGroup.cpp \
- MediaDefs.cpp \
- MediaSource.cpp \
- MetaData.cpp \
- OMXCodec.cpp \
- Utils.cpp \
- OMXClient.cpp
-
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
-LOCAL_SRC_FILES += \
- AMRExtractor.cpp \
- AMRWriter.cpp \
- AudioPlayer.cpp \
- AudioSource.cpp \
- AwesomePlayer.cpp \
- CameraSource.cpp \
- DataSource.cpp \
- FileSource.cpp \
- HTTPStream.cpp \
- JPEGSource.cpp \
- MP3Extractor.cpp \
- MPEG4Extractor.cpp \
- MPEG4Writer.cpp \
- MediaExtractor.cpp \
- NuCachedSource2.cpp \
- NuHTTPDataSource.cpp \
- OggExtractor.cpp \
- SampleIterator.cpp \
- SampleTable.cpp \
- ShoutcastSource.cpp \
- StagefrightMediaScanner.cpp \
- StagefrightMetadataRetriever.cpp \
- ThrottledSource.cpp \
- TimeSource.cpp \
- TimedEventQueue.cpp \
- WAVExtractor.cpp \
+LOCAL_SRC_FILES:= \
+ AMRExtractor.cpp \
+ AMRWriter.cpp \
+ AudioPlayer.cpp \
+ AudioSource.cpp \
+ AwesomePlayer.cpp \
+ CameraSource.cpp \
+ DataSource.cpp \
+ ESDS.cpp \
+ FileSource.cpp \
+ HTTPStream.cpp \
+ JPEGSource.cpp \
+ MP3Extractor.cpp \
+ MPEG4Extractor.cpp \
+ MPEG4Writer.cpp \
+ MediaBuffer.cpp \
+ MediaBufferGroup.cpp \
+ MediaDefs.cpp \
+ MediaExtractor.cpp \
+ MediaSource.cpp \
+ MetaData.cpp \
+ NuCachedSource2.cpp \
+ NuHTTPDataSource.cpp \
+ OMXClient.cpp \
+ OMXCodec.cpp \
+ OggExtractor.cpp \
+ SampleIterator.cpp \
+ SampleTable.cpp \
+ ShoutcastSource.cpp \
+ StagefrightMediaScanner.cpp \
+ StagefrightMetadataRetriever.cpp \
+ ThrottledSource.cpp \
+ TimeSource.cpp \
+ TimedEventQueue.cpp \
+ Utils.cpp \
+ WAVExtractor.cpp \
string.cpp
-LOCAL_CFLAGS += -DBUILD_WITH_FULL_STAGEFRIGHT
-endif
-
LOCAL_C_INCLUDES:= \
$(JNI_H_INCLUDE) \
$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
@@ -82,20 +75,13 @@
libstagefright_mpeg2ts \
libstagefright_httplive \
libstagefright_rtsp \
+ libstagefright_id3 \
LOCAL_SHARED_LIBRARIES += \
libstagefright_amrnb_common \
libstagefright_enc_common \
libstagefright_avc_common \
libstagefright_foundation \
-
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
-
-LOCAL_STATIC_LIBRARIES += \
- libstagefright_id3
-
-LOCAL_SHARED_LIBRARIES += \
libstagefright_color_conversion
ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
@@ -108,8 +94,6 @@
LOCAL_SHARED_LIBRARIES += libdl
endif
-endif
-
ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
LOCAL_LDLIBS += -lpthread
endif
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index d203dbf..6031797 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -78,6 +78,8 @@
mCollectStats = true;
}
+ mTrackMaxAmplitude = false;
+ mMaxAmplitude = 0;
mStartTimeUs = 0;
int64_t startTimeUs;
if (params && params->findInt64(kKeyTime, &startTimeUs)) {
@@ -168,6 +170,10 @@
return (status_t)n;
}
+ if (mTrackMaxAmplitude) {
+ trackMaxAmplitude((int16_t *) buffer->data(), n >> 1);
+ }
+
uint32_t sampleRate = mRecord->getSampleRate();
int64_t timestampUs = (1000000LL * numFramesRecorded) / sampleRate + mStartTimeUs;
buffer->meta_data()->setInt64(kKeyTime, timestampUs);
@@ -181,4 +187,27 @@
return OK;
}
+void AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) {
+ for (int i = nSamples; i > 0; --i) {
+ int16_t value = *data++;
+ if (value < 0) {
+ value = -value;
+ }
+ if (mMaxAmplitude < value) {
+ mMaxAmplitude = value;
+ }
+ }
+}
+
+int16_t AudioSource::getMaxAmplitude() {
+ // First call activates the tracking.
+ if (!mTrackMaxAmplitude) {
+ mTrackMaxAmplitude = true;
+ }
+ int16_t value = mMaxAmplitude;
+ mMaxAmplitude = 0;
+ LOGV("max amplitude since last call: %d", value);
+ return value;
+}
+
} // namespace android
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 3639db4..0c2f1e6 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -428,6 +428,14 @@
}
chunk_size = ntoh64(chunk_size);
data_offset += 8;
+
+ if (chunk_size < 16) {
+ // The smallest valid chunk is 16 bytes long in this case.
+ return ERROR_MALFORMED;
+ }
+ } else if (chunk_size < 8) {
+ // The smallest valid chunk is 8 bytes long.
+ return ERROR_MALFORMED;
}
char chunk[5];
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 4242d36..65d109b 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -180,12 +180,73 @@
return OK;
}
-status_t MPEG4Writer::start() {
+int64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
+ // This implementation is highly experimental/heurisitic.
+ //
+ // Statistical analysis shows that metadata usually accounts
+ // for a small portion of the total file size, usually < 0.6%.
+ // Currently, lets set to 0.4% for now.
+
+ // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB,
+ // where 1MB is the common file size limit for MMS application.
+ // The default MAX _MOOV_BOX_SIZE value is based on about 4
+ // minute video recording with a bit rate about 3 Mbps, because
+ // statistics also show that most of the video captured are going
+ // to be less than 3 minutes.
+
+ // If the estimation is wrong, we will pay the price of wasting
+ // some reserved space. This should not happen so often statistically.
+ static const int32_t factor = mUse32BitOffset? 1: 2;
+ static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024; // 4 KB
+ static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
+ int64_t size = MIN_MOOV_BOX_SIZE;
+
+ if (mMaxFileSizeLimitBytes != 0) {
+ size = mMaxFileSizeLimitBytes * 4 / 1000;
+ } else if (mMaxFileDurationLimitUs != 0) {
+ if (bitRate <= 0) {
+ // We could not estimate the file size since bitRate is not set.
+ size = MIN_MOOV_BOX_SIZE;
+ } else {
+ size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000);
+ }
+ }
+ if (size < MIN_MOOV_BOX_SIZE) {
+ size = MIN_MOOV_BOX_SIZE;
+ }
+
+ // Any long duration recording will be probably end up with
+ // non-streamable mp4 file.
+ if (size > MAX_MOOV_BOX_SIZE) {
+ size = MAX_MOOV_BOX_SIZE;
+ }
+
+ LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
+ " moov size %lld bytes",
+ mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
+ return factor * size;
+}
+
+status_t MPEG4Writer::start(MetaData *param) {
if (mFile == NULL) {
return UNKNOWN_ERROR;
}
- mStartTimestampUs = 0;
+ int32_t use64BitOffset;
+ if (param &&
+ param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
+ use64BitOffset) {
+ mUse32BitOffset = false;
+ }
+
+ // System property can overwrite the file offset bits parameter
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("media.stagefright.record-64bits", value, NULL)
+ && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
+ mUse32BitOffset = false;
+ }
+
+ mStartTimestampUs = -1;
if (mStarted) {
if (mPaused) {
mPaused = false;
@@ -208,9 +269,11 @@
mFreeBoxOffset = mOffset;
if (mEstimatedMoovBoxSize == 0) {
- // XXX: Estimate the moov box size
- // based on max file size or duration limit
- mEstimatedMoovBoxSize = 0x0F00;
+ int32_t bitRate = -1;
+ if (param) {
+ param->findInt32(kKeyBitRate, &bitRate);
+ }
+ mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
}
CHECK(mEstimatedMoovBoxSize >= 8);
fseeko(mFile, mFreeBoxOffset, SEEK_SET);
@@ -332,8 +395,7 @@
write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile);
// Free box
- mFreeBoxOffset = mStreamableFile? mOffset: mFreeBoxOffset;
- fseeko(mFile, mFreeBoxOffset, SEEK_SET);
+ fseeko(mFile, mOffset, SEEK_SET);
writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
write("free", 4);
@@ -341,6 +403,8 @@
free(mMoovBoxBuffer);
mMoovBoxBuffer = NULL;
mMoovBoxBufferOffset = 0;
+ } else {
+ LOGI("The mp4 file will not be streamable.");
}
CHECK(mBoxes.empty());
@@ -561,8 +625,7 @@
LOGI("setStartTimestampUs: %lld", timeUs);
CHECK(timeUs >= 0);
Mutex::Autolock autoLock(mLock);
- if (mStartTimestampUs == 0 ||
- (mStartTimestampUs > 0 && mStartTimestampUs > timeUs)) {
+ if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
mStartTimestampUs = timeUs;
LOGI("Earliest track starting time: %lld", mStartTimestampUs);
}
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 8979c3b..02a073e 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -425,7 +425,6 @@
for (size_t i = 0; i < matchingCodecs.size(); ++i) {
componentName = matchingCodecs[i].string();
-#if BUILD_WITH_FULL_STAGEFRIGHT
sp<MediaSource> softwareCodec = createEncoder?
InstantiateSoftwareEncoder(componentName, source, meta):
InstantiateSoftwareCodec(componentName, source);
@@ -435,7 +434,6 @@
return softwareCodec;
}
-#endif
LOGV("Attempting to allocate OMX node '%s'", componentName);
diff --git a/media/libstagefright/codecs/aacenc/AACEncoder.cpp b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
index 52204fa..b914023 100644
--- a/media/libstagefright/codecs/aacenc/AACEncoder.cpp
+++ b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
@@ -139,6 +139,8 @@
CHECK_EQ(OK, initCheck());
+ mNumInputSamples = 0;
+ mAnchorTimeUs = 0;
mFrameCount = 0;
mSource->start(params);
@@ -205,33 +207,65 @@
buffer->set_range(0, 2);
buffer->meta_data()->setInt32(kKeyIsCodecConfig, true);
*out = buffer;
- mInputBuffer = NULL;
++mFrameCount;
return OK;
} else if (mFrameCount == 1) {
buffer->meta_data()->setInt32(kKeyIsCodecConfig, false);
}
- // XXX: We assume that the input buffer contains at least
- // (actually, exactly) 1024 PCM samples. This needs to be fixed.
- if (mInputBuffer == NULL) {
- if (mSource->read(&mInputBuffer, options) != OK) {
- LOGE("failed to read from input audio source");
- return UNKNOWN_ERROR;
+ while (mNumInputSamples < kNumSamplesPerFrame) {
+ if (mInputBuffer == NULL) {
+ if (mSource->read(&mInputBuffer, options) != OK) {
+ if (mNumInputSamples == 0) {
+ return ERROR_END_OF_STREAM;
+ }
+ memset(&mInputFrame[mNumInputSamples],
+ 0,
+ sizeof(int16_t) * (kNumSamplesPerFrame - mNumInputSamples));
+ mNumInputSamples = 0;
+ break;
+ }
+
+ size_t align = mInputBuffer->range_length() % sizeof(int16_t);
+ CHECK_EQ(align, 0);
+
+ int64_t timeUs;
+ if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
+ mAnchorTimeUs = timeUs;
+ }
}
+ size_t copy =
+ (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t);
+
+ if (copy > mInputBuffer->range_length()) {
+ copy = mInputBuffer->range_length();
+ }
+
+ memcpy(&mInputFrame[mNumInputSamples],
+ (const uint8_t *) mInputBuffer->data()
+ + mInputBuffer->range_offset(),
+ copy);
+
+ mInputBuffer->set_range(
+ mInputBuffer->range_offset() + copy,
+ mInputBuffer->range_length() - copy);
+
if (mInputBuffer->range_length() == 0) {
mInputBuffer->release();
mInputBuffer = NULL;
- return ERROR_END_OF_STREAM;
}
- VO_CODECBUFFER inputData;
- memset(&inputData, 0, sizeof(inputData));
- inputData.Buffer = (unsigned char*) mInputBuffer->data();
- inputData.Length = mInputBuffer->range_length();
- CHECK(VO_ERR_NONE == mApiHandle->SetInputData(mEncoderHandle,&inputData));
+ mNumInputSamples += copy / sizeof(int16_t);
+ if (mNumInputSamples >= kNumSamplesPerFrame) {
+ mNumInputSamples %= kNumSamplesPerFrame;
+ break;
+ }
}
- CHECK(mInputBuffer != NULL);
+ VO_CODECBUFFER inputData;
+ memset(&inputData, 0, sizeof(inputData));
+ inputData.Buffer = (unsigned char*) mInputFrame;
+ inputData.Length = kNumSamplesPerFrame * sizeof(int16_t);
+ CHECK(VO_ERR_NONE == mApiHandle->SetInputData(mEncoderHandle,&inputData));
VO_CODECBUFFER outputData;
memset(&outputData, 0, sizeof(outputData));
@@ -239,24 +273,14 @@
memset(&outputInfo, 0, sizeof(outputInfo));
VO_U32 ret = VO_ERR_NONE;
- int32_t outputLength = 0;
outputData.Buffer = outPtr;
outputData.Length = buffer->size();
ret = mApiHandle->GetOutputData(mEncoderHandle, &outputData, &outputInfo);
- if (ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL) {
- outputLength += outputData.Length;
- if (ret == VO_ERR_INPUT_BUFFER_SMALL) { // All done
- mInputBuffer->release();
- mInputBuffer = NULL;
- }
- } else {
- LOGE("failed to encode the input data 0x%lx", ret);
- }
+ CHECK(ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL);
+ CHECK(outputData.Length != 0);
+ buffer->set_range(0, outputData.Length);
- buffer->set_range(0, outputLength);
-
- // Each output frame compresses 1024 input PCM samples.
- int64_t timestampUs = ((mFrameCount - 1) * 1000000LL * 1024) / mSampleRate;
+ int64_t timestampUs = ((mFrameCount - 1) * 1000000LL * kNumSamplesPerFrame) / mSampleRate;
++mFrameCount;
buffer->meta_data()->setInt64(kKeyTime, timestampUs);
diff --git a/media/libstagefright/id3/Android.mk b/media/libstagefright/id3/Android.mk
index 93fac1c..23c8e44 100644
--- a/media/libstagefright/id3/Android.mk
+++ b/media/libstagefright/id3/Android.mk
@@ -1,5 +1,3 @@
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -28,5 +26,3 @@
LOCAL_MODULE := testid3
include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/media/libstagefright/include/AACEncoder.h b/media/libstagefright/include/AACEncoder.h
index 211a332..ecc533f 100644
--- a/media/libstagefright/include/AACEncoder.h
+++ b/media/libstagefright/include/AACEncoder.h
@@ -52,6 +52,16 @@
int32_t mChannels;
int32_t mBitRate;
int32_t mFrameCount;
+
+ int64_t mAnchorTimeUs;
+ int64_t mNumInputSamples;
+
+ enum {
+ kNumSamplesPerFrame = 1024,
+ };
+
+ int16_t mInputFrame[kNumSamplesPerFrame];
+
uint8_t mAudioSpecificConfigData[2]; // auido specific data
void *mEncoderHandle;
VO_AUDIO_CODECAPI *mApiHandle;
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index f73e837..3a20c16 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -49,8 +49,8 @@
friend struct AHandlerReflector<NuCachedSource2>;
enum {
- kPageSize = 16384,
- kHighWaterThreshold = 3 * 1024 * 1024,
+ kPageSize = 65536,
+ kHighWaterThreshold = 5 * 1024 * 1024,
kLowWaterThreshold = 512 * 1024,
// Read data after a 15 sec timeout whether we're actively
diff --git a/media/libstagefright/omx/tests/Android.mk b/media/libstagefright/omx/tests/Android.mk
index ee117e5..8bf4336 100644
--- a/media/libstagefright/omx/tests/Android.mk
+++ b/media/libstagefright/omx/tests/Android.mk
@@ -1,5 +1,3 @@
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -17,7 +15,3 @@
LOCAL_MODULE:= omx_tests
include $(BUILD_EXECUTABLE)
-
-endif
-
-