diff options
170 files changed, 1696 insertions, 3916 deletions
diff --git a/cmds/stagefright/SineSource.cpp b/cmds/stagefright/SineSource.cpp index 14b4306..587077a 100644 --- a/cmds/stagefright/SineSource.cpp +++ b/cmds/stagefright/SineSource.cpp @@ -24,7 +24,7 @@ SineSource::~SineSource() { } } -status_t SineSource::start(MetaData *params) { +status_t SineSource::start(MetaData * /* params */) { CHECK(!mStarted); mGroup = new MediaBufferGroup; @@ -58,7 +58,7 @@ sp<MetaData> SineSource::getFormat() { } status_t SineSource::read( - MediaBuffer **out, const ReadOptions *options) { + MediaBuffer **out, const ReadOptions * /* options */) { *out = NULL; MediaBuffer *buffer; diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp index b7a40c2..fdc352e 100644 --- a/cmds/stagefright/record.cpp +++ b/cmds/stagefright/record.cpp @@ -296,7 +296,7 @@ int main(int argc, char **argv) { } #else -int main(int argc, char **argv) { +int main(int /* argc */, char ** /* argv */) { android::ProcessState::self()->startThreadPool(); OMXClient client; diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index dfc2066..fd86737 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -141,8 +141,8 @@ public: static uint32_t getInputFramesLost(audio_io_handle_t ioHandle); static int newAudioSessionId(); - static void acquireAudioSessionId(int audioSession); - static void releaseAudioSessionId(int audioSession); + static void acquireAudioSessionId(int audioSession, pid_t pid); + static void releaseAudioSessionId(int audioSession, pid_t pid); // types of io configuration change events received with ioConfigChanged() enum io_config_event { diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index 5a50280..d0df710 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -190,7 +190,8 @@ public: int sessionId = AUDIO_SESSION_ALLOCATE, transfer_type transferType = TRANSFER_DEFAULT, const audio_offload_info_t *offloadInfo = NULL, - int uid = -1); + int uid = -1, + pid_t pid = -1); /* Creates an audio track and registers it with AudioFlinger. * With this constructor, the track is configured for static buffer mode. @@ -215,7 +216,8 @@ public: int sessionId = AUDIO_SESSION_ALLOCATE, transfer_type transferType = TRANSFER_DEFAULT, const audio_offload_info_t *offloadInfo = NULL, - int uid = -1); + int uid = -1, + pid_t pid = -1); /* Terminates the AudioTrack and unregisters it from AudioFlinger. * Also destroys all resources associated with the AudioTrack. @@ -253,7 +255,8 @@ public: int sessionId = AUDIO_SESSION_ALLOCATE, transfer_type transferType = TRANSFER_DEFAULT, const audio_offload_info_t *offloadInfo = NULL, - int uid = -1); + int uid = -1, + pid_t pid = -1); /* Result of constructing the AudioTrack. This must be checked for successful initialization * before using any AudioTrack API (except for set()), because using @@ -757,6 +760,7 @@ private: sp<DeathNotifier> mDeathNotifier; uint32_t mSequence; // incremented for each new IAudioTrack attempt int mClientUid; + pid_t mClientPid; }; class TimedAudioTrack : public AudioTrack diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h index ea225ac..7f53bfc 100644 --- a/include/media/IAudioFlinger.h +++ b/include/media/IAudioFlinger.h @@ -180,8 +180,8 @@ public: virtual int newAudioSessionId() = 0; - virtual void acquireAudioSessionId(int audioSession) = 0; - virtual void releaseAudioSessionId(int audioSession) = 0; + virtual void acquireAudioSessionId(int audioSession, pid_t pid) = 0; + virtual void releaseAudioSessionId(int audioSession, pid_t pid) = 0; virtual status_t queryNumberEffects(uint32_t *numEffects) const = 0; diff --git a/include/media/nbaio/NBLog.h b/include/media/nbaio/NBLog.h index 6d59ea7..bcbbc04 100644 --- a/include/media/nbaio/NBLog.h +++ b/include/media/nbaio/NBLog.h @@ -25,6 +25,8 @@ namespace android { +class String8; + class NBLog { public: @@ -187,6 +189,10 @@ private: const Shared* const mShared; // raw pointer to shared memory const sp<IMemory> mIMemory; // ref-counted version int32_t mFront; // index of oldest acknowledged Entry + int mFd; // file descriptor + int mIndent; // indentation level + + void dumpLine(const String8& timestamp, String8& body); static const size_t kSquashTimestamp = 5; // squash this many or more adjacent timestamps }; diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h index 69cfbd0..dd0a106 100644 --- a/include/media/stagefright/CameraSource.h +++ b/include/media/stagefright/CameraSource.h @@ -172,7 +172,7 @@ protected: const sp<IGraphicBufferProducer>& surface, bool storeMetaDataInVideoBuffers); - virtual void startCameraRecording(); + virtual status_t startCameraRecording(); virtual void releaseRecordingFrame(const sp<IMemory>& frame); // Returns true if need to skip the current frame. diff --git a/include/media/stagefright/DataURISource.h b/include/media/stagefright/DataURISource.h new file mode 100644 index 0000000..693562e --- /dev/null +++ b/include/media/stagefright/DataURISource.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2014 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 DATA_URI_SOURCE_H_ + +#define DATA_URI_SOURCE_H_ + +#include <media/stagefright/DataSource.h> +#include <media/stagefright/foundation/ABase.h> + +namespace android { + +struct ABuffer; + +struct DataURISource : public DataSource { + static sp<DataURISource> Create(const char *uri); + + virtual status_t initCheck() const; + virtual ssize_t readAt(off64_t offset, void *data, size_t size); + virtual status_t getSize(off64_t *size); + +protected: + virtual ~DataURISource(); + +private: + sp<ABuffer> mBuffer; + + DataURISource(const sp<ABuffer> &buffer); + + DISALLOW_EVIL_CONSTRUCTORS(DataURISource); +}; + +} // namespace android + +#endif // DATA_URI_SOURCE_H_ + diff --git a/include/media/stagefright/MediaSource.h b/include/media/stagefright/MediaSource.h index 3818e63..204d1c6 100644 --- a/include/media/stagefright/MediaSource.h +++ b/include/media/stagefright/MediaSource.h @@ -105,7 +105,7 @@ struct MediaSource : public virtual RefBase { // This will be called after a successful start() and before the // first read() call. // Callee assumes ownership of the buffers if no error is returned. - virtual status_t setBuffers(const Vector<MediaBuffer *> &buffers) { + virtual status_t setBuffers(const Vector<MediaBuffer *> & /* buffers */) { return ERROR_UNSUPPORTED; } diff --git a/media/libeffects/factory/Android.mk b/media/libeffects/factory/Android.mk index 60a6ce5..a932af7 100644 --- a/media/libeffects/factory/Android.mk +++ b/media/libeffects/factory/Android.mk @@ -9,7 +9,6 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := \ libcutils liblog -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES) LOCAL_MODULE:= libeffects LOCAL_SHARED_LIBRARIES += libdl diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index fc4b2a5..e0acae6 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -60,16 +60,12 @@ LOCAL_SRC_FILES:= \ LOCAL_SRC_FILES += ../libnbaio/roundup.c -# for <cutils/atomic-inline.h> -LOCAL_CFLAGS += -DANDROID_SMP=$(if $(findstring true,$(TARGET_CPU_SMP)),1,0) -LOCAL_SRC_FILES += SingleStateQueue.cpp -LOCAL_CFLAGS += -DSINGLE_STATE_QUEUE_INSTANTIATIONS='"SingleStateQueueInstantiations.cpp"' -# Consider a separate a library for SingleStateQueueInstantiations. - LOCAL_SHARED_LIBRARIES := \ libui liblog libcutils libutils libbinder libsonivox libicuuc libicui18n libexpat \ libcamera_client libstagefright_foundation \ - libgui libdl libaudioutils + libgui libdl libaudioutils libnbaio + +LOCAL_STATIC_LIBRARIES += libinstantssq LOCAL_WHOLE_STATIC_LIBRARY := libmedia_helper @@ -84,3 +80,15 @@ LOCAL_C_INCLUDES := \ $(call include-path-for, audio-utils) include $(BUILD_SHARED_LIBRARY) + +include $(CLEAR_VARS) + +# for <cutils/atomic-inline.h> +LOCAL_CFLAGS += -DANDROID_SMP=$(if $(findstring true,$(TARGET_CPU_SMP)),1,0) +LOCAL_SRC_FILES += SingleStateQueue.cpp +LOCAL_CFLAGS += -DSINGLE_STATE_QUEUE_INSTANTIATIONS='"SingleStateQueueInstantiations.cpp"' + +LOCAL_MODULE := libinstantssq +LOCAL_MODULE_TAGS := optional + +include $(BUILD_STATIC_LIBRARY) diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 541cb51..700718d 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -115,7 +115,7 @@ AudioRecord::~AudioRecord() mAudioRecord.clear(); } IPCThreadState::self()->flushCommands(); - AudioSystem::releaseAudioSessionId(mSessionId); + AudioSystem::releaseAudioSessionId(mSessionId, -1); } } @@ -266,7 +266,7 @@ status_t AudioRecord::set( mMarkerReached = false; mNewPosition = 0; mUpdatePeriod = 0; - AudioSystem::acquireAudioSessionId(mSessionId); + AudioSystem::acquireAudioSessionId(mSessionId, -1); mSequence = 1; mObservedSequence = mSequence; mInOverrun = false; @@ -462,7 +462,9 @@ status_t AudioRecord::openRecord_l(size_t epoch) audio_io_handle_t input = AudioSystem::getInput(mInputSource, mSampleRate, mFormat, mChannelMask, mSessionId); if (input == 0) { - ALOGE("Could not get audio input for record source %d", mInputSource); + ALOGE("Could not get audio input for record source %d, sample rate %u, format %#x, " + "channel mask %#x, session %d", + mInputSource, mSampleRate, mFormat, mChannelMask, mSessionId); return BAD_VALUE; } { diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 87f4b4c..140fb66 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -435,19 +435,19 @@ int AudioSystem::newAudioSessionId() return af->newAudioSessionId(); } -void AudioSystem::acquireAudioSessionId(int audioSession) +void AudioSystem::acquireAudioSessionId(int audioSession, pid_t pid) { const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); if (af != 0) { - af->acquireAudioSessionId(audioSession); + af->acquireAudioSessionId(audioSession, pid); } } -void AudioSystem::releaseAudioSessionId(int audioSession) +void AudioSystem::releaseAudioSessionId(int audioSession, pid_t pid) { const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); if (af != 0) { - af->releaseAudioSessionId(audioSession); + af->releaseAudioSessionId(audioSession, pid); } } diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 63eaf1a..5c62260 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -116,7 +116,8 @@ AudioTrack::AudioTrack( int sessionId, transfer_type transferType, const audio_offload_info_t *offloadInfo, - int uid) + int uid, + pid_t pid) : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), @@ -125,7 +126,7 @@ AudioTrack::AudioTrack( mStatus = set(streamType, sampleRate, format, channelMask, frameCount, flags, cbf, user, notificationFrames, 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType, - offloadInfo, uid); + offloadInfo, uid, pid); } AudioTrack::AudioTrack( @@ -141,7 +142,8 @@ AudioTrack::AudioTrack( int sessionId, transfer_type transferType, const audio_offload_info_t *offloadInfo, - int uid) + int uid, + pid_t pid) : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), @@ -149,7 +151,8 @@ AudioTrack::AudioTrack( { mStatus = set(streamType, sampleRate, format, channelMask, 0 /*frameCount*/, flags, cbf, user, notificationFrames, - sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo, uid); + sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo, + uid, pid); } AudioTrack::~AudioTrack() @@ -168,7 +171,9 @@ AudioTrack::~AudioTrack() mAudioTrack->asBinder()->unlinkToDeath(mDeathNotifier, this); mAudioTrack.clear(); IPCThreadState::self()->flushCommands(); - AudioSystem::releaseAudioSessionId(mSessionId); + ALOGV("~AudioTrack, releasing session id from %d on behalf of %d", + IPCThreadState::self()->getCallingPid(), mClientPid); + AudioSystem::releaseAudioSessionId(mSessionId, mClientPid); } } @@ -187,7 +192,8 @@ status_t AudioTrack::set( int sessionId, transfer_type transferType, const audio_offload_info_t *offloadInfo, - int uid) + int uid, + pid_t pid) { switch (transferType) { case TRANSFER_DEFAULT: @@ -335,11 +341,18 @@ status_t AudioTrack::set( mNotificationFramesReq = notificationFrames; mNotificationFramesAct = 0; mSessionId = sessionId; - if (uid == -1 || (IPCThreadState::self()->getCallingPid() != getpid())) { + int callingpid = IPCThreadState::self()->getCallingPid(); + int mypid = getpid(); + if (uid == -1 || (callingpid != mypid)) { mClientUid = IPCThreadState::self()->getCallingUid(); } else { mClientUid = uid; } + if (pid == -1 || (callingpid != mypid)) { + mClientPid = callingpid; + } else { + mClientPid = pid; + } mAuxEffectId = 0; mFlags = flags; mCbf = cbf; @@ -379,7 +392,7 @@ status_t AudioTrack::set( mMarkerReached = false; mNewPosition = 0; mUpdatePeriod = 0; - AudioSystem::acquireAudioSessionId(mSessionId); + AudioSystem::acquireAudioSessionId(mSessionId, mClientPid); mSequence = 1; mObservedSequence = mSequence; mInUnderrun = false; diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index eef6a3d..e696323 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -609,19 +609,21 @@ public: return id; } - virtual void acquireAudioSessionId(int audioSession) + virtual void acquireAudioSessionId(int audioSession, int pid) { Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); data.writeInt32(audioSession); + data.writeInt32(pid); remote()->transact(ACQUIRE_AUDIO_SESSION_ID, data, &reply); } - virtual void releaseAudioSessionId(int audioSession) + virtual void releaseAudioSessionId(int audioSession, int pid) { Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); data.writeInt32(audioSession); + data.writeInt32(pid); remote()->transact(RELEASE_AUDIO_SESSION_ID, data, &reply); } @@ -986,7 +988,7 @@ status_t BnAudioFlinger::onTransact( &latency, flags, hasOffloadInfo ? &offloadInfo : NULL); - ALOGV("OPEN_OUTPUT output, %p", output); + ALOGV("OPEN_OUTPUT output, %d", output); reply->writeInt32((int32_t) output); reply->writeInt32(devices); reply->writeInt32(samplingRate); @@ -1082,13 +1084,15 @@ status_t BnAudioFlinger::onTransact( case ACQUIRE_AUDIO_SESSION_ID: { CHECK_INTERFACE(IAudioFlinger, data, reply); int audioSession = data.readInt32(); - acquireAudioSessionId(audioSession); + int pid = data.readInt32(); + acquireAudioSessionId(audioSession, pid); return NO_ERROR; } break; case RELEASE_AUDIO_SESSION_ID: { CHECK_INTERFACE(IAudioFlinger, data, reply); int audioSession = data.readInt32(); - releaseAudioSessionId(audioSession); + int pid = data.readInt32(); + releaseAudioSessionId(audioSession, pid); return NO_ERROR; } break; case QUERY_NUM_EFFECTS: { diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 24663ad..d94c7c5 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -58,7 +58,7 @@ MediaPlayer::MediaPlayer() mVideoWidth = mVideoHeight = 0; mLockThreadId = 0; mAudioSessionId = AudioSystem::newAudioSessionId(); - AudioSystem::acquireAudioSessionId(mAudioSessionId); + AudioSystem::acquireAudioSessionId(mAudioSessionId, -1); mSendLevel = 0; mRetransmitEndpointValid = false; } @@ -66,7 +66,7 @@ MediaPlayer::MediaPlayer() MediaPlayer::~MediaPlayer() { ALOGV("destructor"); - AudioSystem::releaseAudioSessionId(mAudioSessionId); + AudioSystem::releaseAudioSessionId(mAudioSessionId, -1); disconnect(); IPCThreadState::self()->flushCommands(); } @@ -576,8 +576,8 @@ status_t MediaPlayer::setAudioSessionId(int sessionId) return BAD_VALUE; } if (sessionId != mAudioSessionId) { - AudioSystem::acquireAudioSessionId(sessionId); - AudioSystem::releaseAudioSessionId(mAudioSessionId); + AudioSystem::acquireAudioSessionId(sessionId, -1); + AudioSystem::releaseAudioSessionId(mAudioSessionId, -1); mAudioSessionId = sessionId; } return NO_ERROR; diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 1f70620..142788d 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -586,7 +586,8 @@ sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre( } if (!p->hardwareOutput()) { - mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid()); + mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(), + mPid); static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput); } @@ -1299,13 +1300,14 @@ Exit: #undef LOG_TAG #define LOG_TAG "AudioSink" -MediaPlayerService::AudioOutput::AudioOutput(int sessionId, int uid) +MediaPlayerService::AudioOutput::AudioOutput(int sessionId, int uid, int pid) : mCallback(NULL), mCallbackCookie(NULL), mCallbackData(NULL), mBytesWritten(0), mSessionId(sessionId), mUid(uid), + mPid(pid), mFlags(AUDIO_OUTPUT_FLAG_NONE) { ALOGV("AudioOutput(%d)", sessionId); mStreamType = AUDIO_STREAM_MUSIC; @@ -1554,7 +1556,8 @@ status_t MediaPlayerService::AudioOutput::open( mSessionId, AudioTrack::TRANSFER_CALLBACK, offloadInfo, - mUid); + mUid, + mPid); } else { t = new AudioTrack( mStreamType, @@ -1569,7 +1572,8 @@ status_t MediaPlayerService::AudioOutput::open( mSessionId, AudioTrack::TRANSFER_DEFAULT, NULL, // offload info - mUid); + mUid, + mPid); } if ((t == 0) || (t->initCheck() != NO_ERROR)) { diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index fc355b0..448f27a 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -72,7 +72,7 @@ class MediaPlayerService : public BnMediaPlayerService class CallbackData; public: - AudioOutput(int sessionId, int uid); + AudioOutput(int sessionId, int uid, int pid); virtual ~AudioOutput(); virtual bool ready() const { return mTrack != 0; } @@ -140,6 +140,7 @@ class MediaPlayerService : public BnMediaPlayerService float mMsecsPerFrame; int mSessionId; int mUid; + int mPid; float mSendLevel; int mAuxEffectId; static bool mIsOnEmulator; diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp index b19e8bf..b37aee3 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.cpp +++ b/media/libmediaplayerservice/StagefrightPlayer.cpp @@ -189,7 +189,7 @@ status_t StagefrightPlayer::getParameter(int key, Parcel *reply) { } status_t StagefrightPlayer::getMetadata( - const media::Metadata::Filter& ids, Parcel *records) { + const media::Metadata::Filter& /* ids */, Parcel *records) { using media::Metadata; uint32_t flags = mPlayer->flags(); diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index a20c1d2..845a589 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -243,7 +243,7 @@ status_t StagefrightRecorder::setPreviewSurface(const sp<IGraphicBufferProducer> return OK; } -status_t StagefrightRecorder::setOutputFile(const char *path) { +status_t StagefrightRecorder::setOutputFile(const char * /* path */) { ALOGE("setOutputFile(const char*) must not be called"); // We don't actually support this at all, as the media_server process // no longer has permissions to create files. diff --git a/media/libmediaplayerservice/nuplayer/Android.mk b/media/libmediaplayerservice/nuplayer/Android.mk index f946c1c..f97ba57 100644 --- a/media/libmediaplayerservice/nuplayer/Android.mk +++ b/media/libmediaplayerservice/nuplayer/Android.mk @@ -11,7 +11,6 @@ LOCAL_SRC_FILES:= \ NuPlayerStreamListener.cpp \ RTSPSource.cpp \ StreamingSource.cpp \ - mp4/MP4Source.cpp \ LOCAL_C_INCLUDES := \ $(TOP)/frameworks/av/media/libstagefright/httplive \ diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp index ac2aab8..cbedf5c 100644 --- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp +++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp @@ -139,7 +139,7 @@ status_t NuPlayer::HTTPLiveSource::selectTrack(size_t trackIndex, bool select) { // LiveSession::selectTrack returns BAD_VALUE when selecting the currently // selected track, or unselecting a non-selected track. In this case it's an // no-op so we return OK. - return (err == OK || err == BAD_VALUE) ? OK : err; + return (err == OK || err == BAD_VALUE) ? (status_t)OK : err; } status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs) { diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 817395a..d47ac98 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -28,13 +28,11 @@ #include "RTSPSource.h" #include "StreamingSource.h" #include "GenericSource.h" -#include "mp4/MP4Source.h" #include "ATSParser.h" #include "SoftwareRenderer.h" -#include <cutils/properties.h> // for property_get #include <media/stagefright/foundation/hexdump.h> #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ADebug.h> @@ -183,14 +181,7 @@ void NuPlayer::setDataSourceAsync(const sp<IStreamSource> &source) { sp<AMessage> notify = new AMessage(kWhatSourceNotify, id()); - char prop[PROPERTY_VALUE_MAX]; - if (property_get("media.stagefright.use-mp4source", prop, NULL) - && (!strcmp(prop, "1") || !strcasecmp(prop, "true"))) { - msg->setObject("source", new MP4Source(notify, source)); - } else { - msg->setObject("source", new StreamingSource(notify, source)); - } - + msg->setObject("source", new StreamingSource(notify, source)); msg->post(); } @@ -1528,7 +1519,7 @@ void NuPlayer::Source::notifyPrepared(status_t err) { notify->post(); } -void NuPlayer::Source::onMessageReceived(const sp<AMessage> &msg) { +void NuPlayer::Source::onMessageReceived(const sp<AMessage> & /* msg */) { TRESPASS(); } diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp index 9ef8dbd..e4850f0 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp @@ -367,7 +367,7 @@ status_t NuPlayerDriver::reset() { return OK; } -status_t NuPlayerDriver::setLooping(int loop) { +status_t NuPlayerDriver::setLooping(int /* loop */) { return INVALID_OPERATION; } @@ -423,16 +423,17 @@ void NuPlayerDriver::setAudioSink(const sp<AudioSink> &audioSink) { mPlayer->setAudioSink(audioSink); } -status_t NuPlayerDriver::setParameter(int key, const Parcel &request) { +status_t NuPlayerDriver::setParameter( + int /* key */, const Parcel & /* request */) { return INVALID_OPERATION; } -status_t NuPlayerDriver::getParameter(int key, Parcel *reply) { +status_t NuPlayerDriver::getParameter(int /* key */, Parcel * /* reply */) { return INVALID_OPERATION; } status_t NuPlayerDriver::getMetadata( - const media::Metadata::Filter& ids, Parcel *records) { + const media::Metadata::Filter& /* ids */, Parcel *records) { Mutex::Autolock autoLock(mLock); using media::Metadata; @@ -496,7 +497,8 @@ void NuPlayerDriver::notifyFrameStats( mNumFramesDropped = numFramesDropped; } -status_t NuPlayerDriver::dump(int fd, const Vector<String16> &args) const { +status_t NuPlayerDriver::dump( + int fd, const Vector<String16> & /* args */) const { Mutex::Autolock autoLock(mLock); FILE *out = fdopen(dup(fd), "w"); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h index e50533a..11279fc 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h @@ -68,19 +68,19 @@ struct NuPlayer::Source : public AHandler { virtual status_t dequeueAccessUnit( bool audio, sp<ABuffer> *accessUnit) = 0; - virtual status_t getDuration(int64_t *durationUs) { + virtual status_t getDuration(int64_t * /* durationUs */) { return INVALID_OPERATION; } - virtual status_t getTrackInfo(Parcel* reply) const { + virtual status_t getTrackInfo(Parcel* /* reply */) const { return INVALID_OPERATION; } - virtual status_t selectTrack(size_t trackIndex, bool select) { + virtual status_t selectTrack(size_t /* trackIndex */, bool /* select */) { return INVALID_OPERATION; } - virtual status_t seekTo(int64_t seekTimeUs) { + virtual status_t seekTo(int64_t /* seekTimeUs */) { return INVALID_OPERATION; } @@ -93,7 +93,7 @@ protected: virtual void onMessageReceived(const sp<AMessage> &msg); - virtual sp<MetaData> getFormatMeta(bool audio) { return NULL; } + virtual sp<MetaData> getFormatMeta(bool /* audio */) { return NULL; } sp<AMessage> dupNotify() const { return mNotify->dup(); } diff --git a/media/libmediaplayerservice/nuplayer/mp4/MP4Source.cpp b/media/libmediaplayerservice/nuplayer/mp4/MP4Source.cpp deleted file mode 100644 index 2aae4dd..0000000 --- a/media/libmediaplayerservice/nuplayer/mp4/MP4Source.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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 "MP4Source.h" - -#include "FragmentedMP4Parser.h" -#include "../NuPlayerStreamListener.h" - -#include <media/IStreamSource.h> -#include <media/stagefright/foundation/AMessage.h> -#include <media/stagefright/MediaErrors.h> -#include <media/stagefright/MetaData.h> - -namespace android { - -struct StreamSource : public FragmentedMP4Parser::Source { - StreamSource(const sp<IStreamSource> &source) - : mListener(new NuPlayer::NuPlayerStreamListener(source, 0)), - mPosition(0) { - mListener->start(); - } - - virtual ssize_t readAt(off64_t offset, void *data, size_t size) { - if (offset < mPosition) { - return -EPIPE; - } - - while (offset > mPosition) { - char buffer[1024]; - off64_t skipBytes = offset - mPosition; - if (skipBytes > sizeof(buffer)) { - skipBytes = sizeof(buffer); - } - - sp<AMessage> extra; - ssize_t n; - for (;;) { - n = mListener->read(buffer, skipBytes, &extra); - - if (n == -EWOULDBLOCK) { - usleep(10000); - continue; - } - - break; - } - - ALOGV("skipped %ld bytes at offset %lld", n, mPosition); - - if (n < 0) { - return n; - } - - mPosition += n; - } - - sp<AMessage> extra; - size_t total = 0; - while (total < size) { - ssize_t n = mListener->read( - (uint8_t *)data + total, size - total, &extra); - - if (n == -EWOULDBLOCK) { - usleep(10000); - continue; - } else if (n == 0) { - break; - } else if (n < 0) { - mPosition += total; - return n; - } - - total += n; - } - - ALOGV("read %ld bytes at offset %lld", total, mPosition); - - mPosition += total; - - return total; - } - - bool isSeekable() { - return false; - } - -private: - sp<NuPlayer::NuPlayerStreamListener> mListener; - off64_t mPosition; - - DISALLOW_EVIL_CONSTRUCTORS(StreamSource); -}; - -MP4Source::MP4Source( - const sp<AMessage> ¬ify, const sp<IStreamSource> &source) - : Source(notify), - mSource(source), - mLooper(new ALooper), - mParser(new FragmentedMP4Parser), - mEOS(false) { - mLooper->registerHandler(mParser); -} - -MP4Source::~MP4Source() { -} - -void MP4Source::prepareAsync() { - notifyVideoSizeChanged(0, 0); - notifyFlagsChanged(0); - notifyPrepared(); -} - -void MP4Source::start() { - mLooper->start(false /* runOnCallingThread */); - mParser->start(new StreamSource(mSource)); -} - -status_t MP4Source::feedMoreTSData() { - return mEOS ? ERROR_END_OF_STREAM : (status_t)OK; -} - -sp<AMessage> MP4Source::getFormat(bool audio) { - return mParser->getFormat(audio); -} - -status_t MP4Source::dequeueAccessUnit( - bool audio, sp<ABuffer> *accessUnit) { - return mParser->dequeueAccessUnit(audio, accessUnit); -} - -} // namespace android diff --git a/media/libmediaplayerservice/nuplayer/mp4/MP4Source.h b/media/libmediaplayerservice/nuplayer/mp4/MP4Source.h deleted file mode 100644 index a6ef622..0000000 --- a/media/libmediaplayerservice/nuplayer/mp4/MP4Source.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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. - */ - -#ifndef MP4_SOURCE_H -#define MP4_SOURCE_H - -#include "NuPlayerSource.h" - -namespace android { - -struct FragmentedMP4Parser; - -struct MP4Source : public NuPlayer::Source { - MP4Source(const sp<AMessage> ¬ify, const sp<IStreamSource> &source); - - virtual void prepareAsync(); - virtual void start(); - - virtual status_t feedMoreTSData(); - - virtual sp<AMessage> getFormat(bool audio); - - virtual status_t dequeueAccessUnit( - bool audio, sp<ABuffer> *accessUnit); - -protected: - virtual ~MP4Source(); - -private: - sp<IStreamSource> mSource; - sp<ALooper> mLooper; - sp<FragmentedMP4Parser> mParser; - bool mEOS; - - DISALLOW_EVIL_CONSTRUCTORS(MP4Source); -}; - -} // namespace android - -#endif // MP4_SOURCE_H diff --git a/media/libnbaio/Android.mk b/media/libnbaio/Android.mk index 69c75b8..9707c4a 100644 --- a/media/libnbaio/Android.mk +++ b/media/libnbaio/Android.mk @@ -31,9 +31,8 @@ LOCAL_SHARED_LIBRARIES := \ libcommon_time_client \ libcutils \ libutils \ - liblog \ - libmedia -# This dependency on libmedia is for SingleStateQueueInstantiations. -# Consider a separate a library for SingleStateQueueInstantiations. + liblog + +LOCAL_STATIC_LIBRARIES += libinstantssq include $(BUILD_SHARED_LIBRARY) diff --git a/media/libnbaio/NBLog.cpp b/media/libnbaio/NBLog.cpp index 190824d..96738a7 100644 --- a/media/libnbaio/NBLog.cpp +++ b/media/libnbaio/NBLog.cpp @@ -26,6 +26,7 @@ #include <cutils/atomic.h> #include <media/nbaio/NBLog.h> #include <utils/Log.h> +#include <utils/String8.h> namespace android { @@ -337,25 +338,25 @@ void NBLog::Reader::dump(int fd, size_t indent) } i -= length + 3; } - if (i > 0) { - lost += i; - if (fd >= 0) { - fdprintf(fd, "%*swarning: lost %zu bytes worth of events\n", indent, "", lost); - } else { - ALOGI("%*swarning: lost %u bytes worth of events\n", indent, "", lost); - } + mFd = fd; + mIndent = indent; + String8 timestamp, body; + lost += i; + if (lost > 0) { + body.appendFormat("warning: lost %u bytes worth of events", lost); + // TODO timestamp empty here, only other choice to wait for the first timestamp event in the + // log to push it out. Consider keeping the timestamp/body between calls to readAt(). + dumpLine(timestamp, body); } size_t width = 1; while (maxSec >= 10) { ++width; maxSec /= 10; } - char prefix[32]; if (maxSec >= 0) { - snprintf(prefix, sizeof(prefix), "[%*s] ", width + 4, ""); - } else { - prefix[0] = '\0'; + timestamp.appendFormat("[%*s]", width + 4, ""); } + bool deferredTimestamp = false; while (i < avail) { event = (Event) copy[i]; length = copy[i + 1]; @@ -363,11 +364,8 @@ void NBLog::Reader::dump(int fd, size_t indent) size_t advance = length + 3; switch (event) { case EVENT_STRING: - if (fd >= 0) { - fdprintf(fd, "%*s%s%.*s\n", indent, "", prefix, length, (const char *) data); - } else { - ALOGI("%*s%s%.*s", indent, "", prefix, length, (const char *) data); - } break; + body.appendFormat("%.*s", length, (const char *) data); + break; case EVENT_TIMESTAMP: { // already checked that length == sizeof(struct timespec); memcpy(&ts, data, sizeof(struct timespec)); @@ -400,45 +398,53 @@ void NBLog::Reader::dump(int fd, size_t indent) prevNsec = tsNext.tv_nsec; } size_t n = (j - i) / (sizeof(struct timespec) + 3); + if (deferredTimestamp) { + dumpLine(timestamp, body); + deferredTimestamp = false; + } + timestamp.clear(); if (n >= kSquashTimestamp) { - if (fd >= 0) { - fdprintf(fd, "%*s[%d.%03d to .%.03d by .%.03d to .%.03d]\n", indent, "", - (int) ts.tv_sec, (int) (ts.tv_nsec / 1000000), - (int) ((ts.tv_nsec + deltaTotal) / 1000000), - (int) (deltaMin / 1000000), (int) (deltaMax / 1000000)); - } else { - ALOGI("%*s[%d.%03d to .%.03d by .%.03d to .%.03d]\n", indent, "", - (int) ts.tv_sec, (int) (ts.tv_nsec / 1000000), - (int) ((ts.tv_nsec + deltaTotal) / 1000000), - (int) (deltaMin / 1000000), (int) (deltaMax / 1000000)); - } + timestamp.appendFormat("[%d.%03d to .%.03d by .%.03d to .%.03d]", + (int) ts.tv_sec, (int) (ts.tv_nsec / 1000000), + (int) ((ts.tv_nsec + deltaTotal) / 1000000), + (int) (deltaMin / 1000000), (int) (deltaMax / 1000000)); i = j; advance = 0; break; } - if (fd >= 0) { - fdprintf(fd, "%*s[%d.%03d]\n", indent, "", (int) ts.tv_sec, - (int) (ts.tv_nsec / 1000000)); - } else { - ALOGI("%*s[%d.%03d]", indent, "", (int) ts.tv_sec, - (int) (ts.tv_nsec / 1000000)); - } + timestamp.appendFormat("[%d.%03d]", (int) ts.tv_sec, + (int) (ts.tv_nsec / 1000000)); + deferredTimestamp = true; } break; case EVENT_RESERVED: default: - if (fd >= 0) { - fdprintf(fd, "%*s%swarning: unknown event %d\n", indent, "", prefix, event); - } else { - ALOGI("%*s%swarning: unknown event %d", indent, "", prefix, event); - } + body.appendFormat("warning: unknown event %d", event); break; } i += advance; + + if (!body.isEmpty()) { + dumpLine(timestamp, body); + deferredTimestamp = false; + } + } + if (deferredTimestamp) { + dumpLine(timestamp, body); } // FIXME it would be more efficient to put a char mCopy[256] as a member variable of the dumper delete[] copy; } +void NBLog::Reader::dumpLine(const String8& timestamp, String8& body) +{ + if (mFd >= 0) { + fdprintf(mFd, "%.*s%s %s\n", mIndent, "", timestamp.string(), body.string()); + } else { + ALOGI("%.*s%s %s", mIndent, "", timestamp.string(), body.string()); + } + body.clear(); +} + bool NBLog::Reader::isIMemory(const sp<IMemory>& iMemory) const { return iMemory != 0 && mIMemory != 0 && iMemory->pointer() == mIMemory->pointer(); diff --git a/media/libstagefright/AACExtractor.cpp b/media/libstagefright/AACExtractor.cpp index 4d1072f..196f6ee 100644 --- a/media/libstagefright/AACExtractor.cpp +++ b/media/libstagefright/AACExtractor.cpp @@ -219,7 +219,7 @@ sp<MediaSource> AACExtractor::getTrack(size_t index) { return new AACSource(mDataSource, mMeta, mOffsetVector, mFrameDurationUs); } -sp<MetaData> AACExtractor::getTrackMetaData(size_t index, uint32_t flags) { +sp<MetaData> AACExtractor::getTrackMetaData(size_t index, uint32_t /* flags */) { if (mInitCheck != OK || index != 0) { return NULL; } @@ -252,7 +252,7 @@ AACSource::~AACSource() { } } -status_t AACSource::start(MetaData *params) { +status_t AACSource::start(MetaData * /* params */) { CHECK(!mStarted); if (mOffsetVector.empty()) { diff --git a/media/libstagefright/AACWriter.cpp b/media/libstagefright/AACWriter.cpp index c9bcaba..deee8e7 100644 --- a/media/libstagefright/AACWriter.cpp +++ b/media/libstagefright/AACWriter.cpp @@ -111,7 +111,7 @@ status_t AACWriter::addSource(const sp<MediaSource> &source) { return OK; } -status_t AACWriter::start(MetaData *params) { +status_t AACWriter::start(MetaData * /* params */) { if (mInitCheck != OK) { return mInitCheck; } diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 3d5b3b3..4450d62 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -1177,7 +1177,7 @@ status_t ACodec::configureCodec( if (canDoAdaptivePlayback && msg->findInt32("max-width", &maxWidth) && msg->findInt32("max-height", &maxHeight)) { - ALOGV("[%s] prepareForAdaptivePlayback(%ldx%ld)", + ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)", mComponentName.c_str(), maxWidth, maxHeight); err = mOMX->prepareForAdaptivePlayback( @@ -2974,7 +2974,8 @@ ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) mCodec(codec) { } -ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) { +ACodec::BaseState::PortMode ACodec::BaseState::getPortMode( + OMX_U32 /* portIndex */) { return KEEP_BUFFERS; } @@ -3383,8 +3384,8 @@ bool ACodec::BaseState::onOMXFillBufferDone( size_t rangeOffset, size_t rangeLength, OMX_U32 flags, int64_t timeUs, - void *platformPrivate, - void *dataPtr) { + void * /* platformPrivate */, + void * /* dataPtr */) { ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx", mCodec->mComponentName.c_str(), bufferID, timeUs, flags); @@ -3917,7 +3918,7 @@ bool ACodec::LoadedState::onConfigureComponent( } void ACodec::LoadedState::onCreateInputSurface( - const sp<AMessage> &msg) { + const sp<AMessage> & /* msg */) { ALOGV("onCreateInputSurface"); sp<AMessage> notify = mCodec->mNotify->dup(); @@ -4180,7 +4181,7 @@ ACodec::ExecutingState::ExecutingState(ACodec *codec) } ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( - OMX_U32 portIndex) { + OMX_U32 /* portIndex */) { return RESUBMIT_BUFFERS; } diff --git a/media/libstagefright/AMRExtractor.cpp b/media/libstagefright/AMRExtractor.cpp index 03dcbf9..3f592ed 100644 --- a/media/libstagefright/AMRExtractor.cpp +++ b/media/libstagefright/AMRExtractor.cpp @@ -189,7 +189,7 @@ sp<MediaSource> AMRExtractor::getTrack(size_t index) { mOffsetTable, mOffsetTableLength); } -sp<MetaData> AMRExtractor::getTrackMetaData(size_t index, uint32_t flags) { +sp<MetaData> AMRExtractor::getTrackMetaData(size_t index, uint32_t /* flags */) { if (mInitCheck != OK || index != 0) { return NULL; } @@ -221,7 +221,7 @@ AMRSource::~AMRSource() { } } -status_t AMRSource::start(MetaData *params) { +status_t AMRSource::start(MetaData * /* params */) { CHECK(!mStarted); mOffset = mIsWide ? 9 : 6; @@ -258,7 +258,7 @@ status_t AMRSource::read( int64_t seekFrame = seekTimeUs / 20000ll; // 20ms per frame. mCurrentTimeUs = seekFrame * 20000ll; - int index = seekFrame / 50; + size_t index = seekFrame < 0 ? 0 : seekFrame / 50; if (index >= mOffsetTableLength) { index = mOffsetTableLength - 1; } diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp index 3fe247a..653ca36 100644 --- a/media/libstagefright/AMRWriter.cpp +++ b/media/libstagefright/AMRWriter.cpp @@ -105,7 +105,7 @@ status_t AMRWriter::addSource(const sp<MediaSource> &source) { return OK; } -status_t AMRWriter::start(MetaData *params) { +status_t AMRWriter::start(MetaData * /* params */) { if (mInitCheck != OK) { return mInitCheck; } diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index 63f9399..0636dcc 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -15,6 +15,7 @@ LOCAL_SRC_FILES:= \ CameraSource.cpp \ CameraSourceTimeLapse.cpp \ DataSource.cpp \ + DataURISource.cpp \ DRMExtractor.cpp \ ESDS.cpp \ FileSource.cpp \ @@ -57,8 +58,6 @@ LOCAL_SRC_FILES:= \ WVMExtractor.cpp \ XINGSeeker.cpp \ avc_utils.cpp \ - mp4/FragmentedMP4Parser.cpp \ - mp4/TrackFragment.cpp \ LOCAL_C_INCLUDES:= \ $(TOP)/frameworks/av/include/media/stagefright/timedtext \ diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp index 05ee34e..8623100 100644 --- a/media/libstagefright/AudioPlayer.cpp +++ b/media/libstagefright/AudioPlayer.cpp @@ -410,7 +410,7 @@ status_t AudioPlayer::setPlaybackRatePermille(int32_t ratePermille) { // static size_t AudioPlayer::AudioSinkCallback( - MediaPlayerBase::AudioSink *audioSink, + MediaPlayerBase::AudioSink * /* audioSink */, void *buffer, size_t size, void *cookie, MediaPlayerBase::AudioSink::cb_event_t event) { AudioPlayer *me = (AudioPlayer *)cookie; diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp index 6fdee6b..df7da0a 100644 --- a/media/libstagefright/AudioSource.cpp +++ b/media/libstagefright/AudioSource.cpp @@ -68,7 +68,7 @@ AudioSource::AudioSource( int frameCount = kMaxBufferSize / sizeof(int16_t) / channelCount; // make sure that the AudioRecord total buffer size is large enough - int bufCount = 2; + size_t bufCount = 2; while ((bufCount * frameCount) < minFrameCount) { bufCount++; } @@ -208,7 +208,7 @@ void AudioSource::rampVolume( } status_t AudioSource::read( - MediaBuffer **out, const ReadOptions *options) { + MediaBuffer **out, const ReadOptions * /* options */) { Mutex::Autolock autoLock(mLock); *out = NULL; diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index f57ee25..e83ec62 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -86,7 +86,7 @@ struct AwesomeEvent : public TimedEventQueue::Event { protected: virtual ~AwesomeEvent() {} - virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) { + virtual void fire(TimedEventQueue * /* queue */, int64_t /* now_us */) { (mPlayer->*mMethod)(); } @@ -2813,7 +2813,8 @@ bool AwesomePlayer::isStreamingHTTP() const { return mCachedSource != NULL || mWVMExtractor != NULL; } -status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const { +status_t AwesomePlayer::dump( + int fd, const Vector<String16> & /* args */) const { Mutex::Autolock autoLock(mStatsLock); FILE *out = fdopen(dup(fd), "w"); diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp index 3017fe7..b31e9e8 100644 --- a/media/libstagefright/CameraSource.cpp +++ b/media/libstagefright/CameraSource.cpp @@ -31,6 +31,12 @@ #include <utils/String8.h> #include <cutils/properties.h> +#if LOG_NDEBUG +#define UNUSED_UNLESS_VERBOSE(x) (void)(x) +#else +#define UNUSED_UNLESS_VERBOSE(x) +#endif + namespace android { static const int64_t CAMERA_SOURCE_TIMEOUT_NS = 3000000000LL; @@ -63,11 +69,14 @@ CameraSourceListener::~CameraSourceListener() { } void CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) { + UNUSED_UNLESS_VERBOSE(msgType); + UNUSED_UNLESS_VERBOSE(ext1); + UNUSED_UNLESS_VERBOSE(ext2); ALOGV("notify(%d, %d, %d)", msgType, ext1, ext2); } void CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr, - camera_frame_metadata_t *metadata) { + camera_frame_metadata_t * /* metadata */) { ALOGV("postData(%d, ptr:%p, size:%d)", msgType, dataPtr->pointer(), dataPtr->size()); @@ -577,14 +586,15 @@ CameraSource::~CameraSource() { } } -void CameraSource::startCameraRecording() { +status_t CameraSource::startCameraRecording() { ALOGV("startCameraRecording"); // Reset the identity to the current thread because media server owns the // camera and recording is started by the applications. The applications // will connect to the camera in ICameraRecordingProxy::startRecording. int64_t token = IPCThreadState::self()->clearCallingIdentity(); + status_t err; if (mNumInputBuffers > 0) { - status_t err = mCamera->sendCommand( + err = mCamera->sendCommand( CAMERA_CMD_SET_VIDEO_BUFFER_COUNT, mNumInputBuffers, 0); // This could happen for CameraHAL1 clients; thus the failure is @@ -595,17 +605,25 @@ void CameraSource::startCameraRecording() { } } + err = OK; if (mCameraFlags & FLAGS_HOT_CAMERA) { mCamera->unlock(); mCamera.clear(); - CHECK_EQ((status_t)OK, - mCameraRecordingProxy->startRecording(new ProxyListener(this))); + if ((err = mCameraRecordingProxy->startRecording( + new ProxyListener(this))) != OK) { + ALOGE("Failed to start recording, received error: %s (%d)", + strerror(-err), err); + } } else { mCamera->setListener(new CameraSourceListener(this)); mCamera->startRecording(); - CHECK(mCamera->recordingEnabled()); + if (!mCamera->recordingEnabled()) { + err = -EINVAL; + ALOGE("Failed to start recording"); + } } IPCThreadState::self()->restoreCallingIdentity(token); + return err; } status_t CameraSource::start(MetaData *meta) { @@ -637,10 +655,12 @@ status_t CameraSource::start(MetaData *meta) { } } - startCameraRecording(); + status_t err; + if ((err = startCameraRecording()) == OK) { + mStarted = true; + } - mStarted = true; - return OK; + return err; } void CameraSource::stopCameraRecording() { diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp index 86844b8..60cdf66 100644 --- a/media/libstagefright/CameraSourceTimeLapse.cpp +++ b/media/libstagefright/CameraSourceTimeLapse.cpp @@ -232,7 +232,7 @@ sp<IMemory> CameraSourceTimeLapse::createIMemoryCopy( return newMemory; } -bool CameraSourceTimeLapse::skipCurrentFrame(int64_t timestampUs) { +bool CameraSourceTimeLapse::skipCurrentFrame(int64_t /* timestampUs */) { ALOGV("skipCurrentFrame"); if (mSkipCurrentFrame) { mSkipCurrentFrame = false; diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp index 2704b74..6e0f37a 100644 --- a/media/libstagefright/DataSource.cpp +++ b/media/libstagefright/DataSource.cpp @@ -35,6 +35,7 @@ #include <media/IMediaHTTPService.h> #include <media/stagefright/foundation/AMessage.h> #include <media/stagefright/DataSource.h> +#include <media/stagefright/DataURISource.h> #include <media/stagefright/FileSource.h> #include <media/stagefright/MediaErrors.h> #include <media/stagefright/MediaHTTP.h> @@ -221,6 +222,8 @@ sp<DataSource> DataSource::CreateFromURI( // in the widevine:// case. source = httpSource; } + } else if (!strncasecmp("data:", uri, 5)) { + source = DataURISource::Create(uri); } else { // Assume it's a filename. source = new FileSource(uri); diff --git a/media/libstagefright/DataURISource.cpp b/media/libstagefright/DataURISource.cpp new file mode 100644 index 0000000..377bc85 --- /dev/null +++ b/media/libstagefright/DataURISource.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2014 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/DataURISource.h> + +#include <media/stagefright/foundation/ABuffer.h> +#include <media/stagefright/foundation/AString.h> +#include <media/stagefright/foundation/base64.h> + +namespace android { + +// static +sp<DataURISource> DataURISource::Create(const char *uri) { + if (strncasecmp("data:", uri, 5)) { + return NULL; + } + + char *commaPos = strrchr(uri, ','); + + if (commaPos == NULL) { + return NULL; + } + + sp<ABuffer> buffer; + + AString tmp(&uri[5], commaPos - &uri[5]); + + if (tmp.endsWith(";base64")) { + AString encoded(commaPos + 1); + + // Strip CR and LF... + for (size_t i = encoded.size(); i-- > 0;) { + if (encoded.c_str()[i] == '\r' || encoded.c_str()[i] == '\n') { + encoded.erase(i, 1); + } + } + + buffer = decodeBase64(encoded); + + if (buffer == NULL) { + ALOGE("Malformed base64 encoded content found."); + return NULL; + } + } else { +#if 0 + size_t dataLen = strlen(uri) - tmp.size() - 6; + buffer = new ABuffer(dataLen); + memcpy(buffer->data(), commaPos + 1, dataLen); + + // unescape +#else + // MediaPlayer doesn't care for this right now as we don't + // play any text-based media. + return NULL; +#endif + } + + // We don't really care about charset or mime type. + + return new DataURISource(buffer); +} + +DataURISource::DataURISource(const sp<ABuffer> &buffer) + : mBuffer(buffer) { +} + +DataURISource::~DataURISource() { +} + +status_t DataURISource::initCheck() const { + return OK; +} + +ssize_t DataURISource::readAt(off64_t offset, void *data, size_t size) { + if (offset >= mBuffer->size()) { + return 0; + } + + size_t copy = mBuffer->size() - offset; + if (copy > size) { + copy = size; + } + + memcpy(data, mBuffer->data() + offset, copy); + + return copy; +} + +status_t DataURISource::getSize(off64_t *size) { + *size = mBuffer->size(); + + return OK; +} + +} // namespace android + diff --git a/media/libstagefright/FLACExtractor.cpp b/media/libstagefright/FLACExtractor.cpp index 098fcf9..fa7251c 100644 --- a/media/libstagefright/FLACExtractor.cpp +++ b/media/libstagefright/FLACExtractor.cpp @@ -208,55 +208,55 @@ private: // with the same parameter list, but discard redundant information. FLAC__StreamDecoderReadStatus FLACParser::read_callback( - const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], + const FLAC__StreamDecoder * /* decoder */, FLAC__byte buffer[], size_t *bytes, void *client_data) { return ((FLACParser *) client_data)->readCallback(buffer, bytes); } FLAC__StreamDecoderSeekStatus FLACParser::seek_callback( - const FLAC__StreamDecoder *decoder, + const FLAC__StreamDecoder * /* decoder */, FLAC__uint64 absolute_byte_offset, void *client_data) { return ((FLACParser *) client_data)->seekCallback(absolute_byte_offset); } FLAC__StreamDecoderTellStatus FLACParser::tell_callback( - const FLAC__StreamDecoder *decoder, + const FLAC__StreamDecoder * /* decoder */, FLAC__uint64 *absolute_byte_offset, void *client_data) { return ((FLACParser *) client_data)->tellCallback(absolute_byte_offset); } FLAC__StreamDecoderLengthStatus FLACParser::length_callback( - const FLAC__StreamDecoder *decoder, + const FLAC__StreamDecoder * /* decoder */, FLAC__uint64 *stream_length, void *client_data) { return ((FLACParser *) client_data)->lengthCallback(stream_length); } FLAC__bool FLACParser::eof_callback( - const FLAC__StreamDecoder *decoder, void *client_data) + const FLAC__StreamDecoder * /* decoder */, void *client_data) { return ((FLACParser *) client_data)->eofCallback(); } FLAC__StreamDecoderWriteStatus FLACParser::write_callback( - const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, + const FLAC__StreamDecoder * /* decoder */, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) { return ((FLACParser *) client_data)->writeCallback(frame, buffer); } void FLACParser::metadata_callback( - const FLAC__StreamDecoder *decoder, + const FLAC__StreamDecoder * /* decoder */, const FLAC__StreamMetadata *metadata, void *client_data) { ((FLACParser *) client_data)->metadataCallback(metadata); } void FLACParser::error_callback( - const FLAC__StreamDecoder *decoder, + const FLAC__StreamDecoder * /* decoder */, FLAC__StreamDecoderErrorStatus status, void *client_data) { ((FLACParser *) client_data)->errorCallback(status); @@ -380,15 +380,21 @@ void FLACParser::errorCallback(FLAC__StreamDecoderErrorStatus status) // Copy samples from FLAC native 32-bit non-interleaved to 16-bit interleaved. // These are candidates for optimization if needed. -static void copyMono8(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels) -{ +static void copyMono8( + short *dst, + const int *const *src, + unsigned nSamples, + unsigned /* nChannels */) { for (unsigned i = 0; i < nSamples; ++i) { *dst++ = src[0][i] << 8; } } -static void copyStereo8(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels) -{ +static void copyStereo8( + short *dst, + const int *const *src, + unsigned nSamples, + unsigned /* nChannels */) { for (unsigned i = 0; i < nSamples; ++i) { *dst++ = src[0][i] << 8; *dst++ = src[1][i] << 8; @@ -404,15 +410,21 @@ static void copyMultiCh8(short *dst, const int *const *src, unsigned nSamples, u } } -static void copyMono16(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels) -{ +static void copyMono16( + short *dst, + const int *const *src, + unsigned nSamples, + unsigned /* nChannels */) { for (unsigned i = 0; i < nSamples; ++i) { *dst++ = src[0][i]; } } -static void copyStereo16(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels) -{ +static void copyStereo16( + short *dst, + const int *const *src, + unsigned nSamples, + unsigned /* nChannels */) { for (unsigned i = 0; i < nSamples; ++i) { *dst++ = src[0][i]; *dst++ = src[1][i]; @@ -430,15 +442,21 @@ static void copyMultiCh16(short *dst, const int *const *src, unsigned nSamples, // 24-bit versions should do dithering or noise-shaping, here or in AudioFlinger -static void copyMono24(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels) -{ +static void copyMono24( + short *dst, + const int *const *src, + unsigned nSamples, + unsigned /* nChannels */) { for (unsigned i = 0; i < nSamples; ++i) { *dst++ = src[0][i] >> 8; } } -static void copyStereo24(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels) -{ +static void copyStereo24( + short *dst, + const int *const *src, + unsigned nSamples, + unsigned /* nChannels */) { for (unsigned i = 0; i < nSamples; ++i) { *dst++ = src[0][i] >> 8; *dst++ = src[1][i] >> 8; @@ -454,8 +472,11 @@ static void copyMultiCh24(short *dst, const int *const *src, unsigned nSamples, } } -static void copyTrespass(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels) -{ +static void copyTrespass( + short * /* dst */, + const int *const * /* src */, + unsigned /* nSamples */, + unsigned /* nChannels */) { TRESPASS(); } @@ -700,7 +721,7 @@ FLACSource::~FLACSource() } } -status_t FLACSource::start(MetaData *params) +status_t FLACSource::start(MetaData * /* params */) { ALOGV("FLACSource::start"); @@ -792,8 +813,7 @@ sp<MediaSource> FLACExtractor::getTrack(size_t index) } sp<MetaData> FLACExtractor::getTrackMetaData( - size_t index, uint32_t flags) -{ + size_t index, uint32_t /* flags */) { if (mInitCheck != OK || index > 0) { return NULL; } diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp index 380dab4..4a63152 100644 --- a/media/libstagefright/MP3Extractor.cpp +++ b/media/libstagefright/MP3Extractor.cpp @@ -398,7 +398,8 @@ sp<MediaSource> MP3Extractor::getTrack(size_t index) { mSeeker); } -sp<MetaData> MP3Extractor::getTrackMetaData(size_t index, uint32_t flags) { +sp<MetaData> MP3Extractor::getTrackMetaData( + size_t index, uint32_t /* flags */) { if (mInitCheck != OK || index != 0) { return NULL; } diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp index c9ed5bb..78c12e1 100644 --- a/media/libstagefright/MPEG2TSWriter.cpp +++ b/media/libstagefright/MPEG2TSWriter.cpp @@ -555,7 +555,7 @@ status_t MPEG2TSWriter::addSource(const sp<MediaSource> &source) { return OK; } -status_t MPEG2TSWriter::start(MetaData *param) { +status_t MPEG2TSWriter::start(MetaData * /* param */) { CHECK(!mStarted); mStarted = true; @@ -596,7 +596,8 @@ bool MPEG2TSWriter::reachedEOS() { return !mStarted || (mNumSourcesDone == mSources.size() ? true : false); } -status_t MPEG2TSWriter::dump(int fd, const Vector<String16> &args) { +status_t MPEG2TSWriter::dump( + int /* fd */, const Vector<String16> & /* args */) { return OK; } diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index e6312c1..f80772a 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -488,12 +488,12 @@ status_t MPEG4Extractor::readMetaData() { break; } uint32_t chunk_type = ntohl(hdr[1]); - if (chunk_type == FOURCC('s', 'i', 'd', 'x')) { - // parse the sidx box too - continue; - } else if (chunk_type == FOURCC('m', 'o', 'o', 'f')) { + if (chunk_type == FOURCC('m', 'o', 'o', 'f')) { // store the offset of the first segment mMoofOffset = offset; + } else if (chunk_type != FOURCC('m', 'd', 'a', 't')) { + // keep parsing until we get to the data + continue; } break; } @@ -571,7 +571,8 @@ static int32_t readSize(off64_t offset, return size; } -status_t MPEG4Extractor::parseDrmSINF(off64_t *offset, off64_t data_offset) { +status_t MPEG4Extractor::parseDrmSINF( + off64_t * /* offset */, off64_t data_offset) { uint8_t updateIdTag; if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) { return ERROR_IO; @@ -1920,9 +1921,10 @@ status_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) { ALOGW("sub-sidx boxes not supported yet"); } bool sap = d3 & 0x80000000; - bool saptype = d3 >> 28; - if (!sap || saptype > 2) { - ALOGW("not a stream access point, or unsupported type"); + uint32_t saptype = (d3 >> 28) & 7; + if (!sap || (saptype != 1 && saptype != 2)) { + // type 1 and 2 are sync samples + ALOGW("not a stream access point, or unsupported type: %08x", d3); } total_duration += d2; offset += 12; @@ -2898,9 +2900,20 @@ status_t MPEG4Source::parseChunk(off64_t *offset) { } } if (chunk_type == FOURCC('m', 'o', 'o', 'f')) { - // *offset points to the mdat box following this moof - parseChunk(offset); // doesn't actually parse it, just updates offset - mNextMoofOffset = *offset; + // *offset points to the box following this moof. Find the next moof from there. + + while (true) { + if (mDataSource->readAt(*offset, hdr, 8) < 8) { + return ERROR_END_OF_STREAM; + } + chunk_size = ntohl(hdr[0]); + chunk_type = ntohl(hdr[1]); + if (chunk_type == FOURCC('m', 'o', 'o', 'f')) { + mNextMoofOffset = *offset; + break; + } + *offset += chunk_size; + } } break; } @@ -2959,7 +2972,8 @@ status_t MPEG4Source::parseChunk(off64_t *offset) { return OK; } -status_t MPEG4Source::parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size) { +status_t MPEG4Source::parseSampleAuxiliaryInformationSizes( + off64_t offset, off64_t /* size */) { ALOGV("parseSampleAuxiliaryInformationSizes"); // 14496-12 8.7.12 uint8_t version; @@ -3021,7 +3035,8 @@ status_t MPEG4Source::parseSampleAuxiliaryInformationSizes(off64_t offset, off64 return OK; } -status_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size) { +status_t MPEG4Source::parseSampleAuxiliaryInformationOffsets( + off64_t offset, off64_t /* size */) { ALOGV("parseSampleAuxiliaryInformationOffsets"); // 14496-12 8.7.13 uint8_t version; @@ -3703,7 +3718,7 @@ status_t MPEG4Source::fragmentedRead( const SidxEntry *se = &mSegments[i]; if (totalTime + se->mDurationUs > seekTimeUs) { // The requested time is somewhere in this segment - if ((mode == ReadOptions::SEEK_NEXT_SYNC) || + if ((mode == ReadOptions::SEEK_NEXT_SYNC && seekTimeUs > totalTime) || (mode == ReadOptions::SEEK_CLOSEST_SYNC && (seekTimeUs - totalTime) > (totalTime + se->mDurationUs - seekTimeUs))) { // requested next sync, or closest sync and it was closer to the end of @@ -3716,11 +3731,19 @@ status_t MPEG4Source::fragmentedRead( totalTime += se->mDurationUs; totalOffset += se->mSize; } - mCurrentMoofOffset = totalOffset; - mCurrentSamples.clear(); - mCurrentSampleIndex = 0; - parseChunk(&totalOffset); - mCurrentTime = totalTime * mTimescale / 1000000ll; + mCurrentMoofOffset = totalOffset; + mCurrentSamples.clear(); + mCurrentSampleIndex = 0; + parseChunk(&totalOffset); + mCurrentTime = totalTime * mTimescale / 1000000ll; + } else { + // without sidx boxes, we can only seek to 0 + mCurrentMoofOffset = mFirstMoofOffset; + mCurrentSamples.clear(); + mCurrentSampleIndex = 0; + off64_t tmp = mCurrentMoofOffset; + parseChunk(&tmp); + mCurrentTime = 0; } if (mBuffer != NULL) { @@ -3732,7 +3755,7 @@ status_t MPEG4Source::fragmentedRead( } off64_t offset = 0; - size_t size; + size_t size = 0; uint32_t cts = 0; bool isSyncSample = false; bool newBuffer = false; @@ -3740,16 +3763,18 @@ status_t MPEG4Source::fragmentedRead( newBuffer = true; if (mCurrentSampleIndex >= mCurrentSamples.size()) { - // move to next fragment - Sample lastSample = mCurrentSamples[mCurrentSamples.size() - 1]; - off64_t nextMoof = mNextMoofOffset; // lastSample.offset + lastSample.size; + // move to next fragment if there is one + if (mNextMoofOffset <= mCurrentMoofOffset) { + return ERROR_END_OF_STREAM; + } + off64_t nextMoof = mNextMoofOffset; mCurrentMoofOffset = nextMoof; mCurrentSamples.clear(); mCurrentSampleIndex = 0; parseChunk(&nextMoof); - if (mCurrentSampleIndex >= mCurrentSamples.size()) { - return ERROR_END_OF_STREAM; - } + if (mCurrentSampleIndex >= mCurrentSamples.size()) { + return ERROR_END_OF_STREAM; + } } const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex]; diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp index ff6feb9..c839560 100644 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -44,7 +44,9 @@ namespace android { static const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024; -static const int64_t kMax32BitFileSize = 0x007fffffffLL; +static const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32 + // filesystem file size + // used by most SD cards static const uint8_t kNalUnitTypeSeqParamSet = 0x07; static const uint8_t kNalUnitTypePicParamSet = 0x08; static const int64_t kInitialDelayTimeUs = 700000LL; @@ -407,7 +409,7 @@ status_t MPEG4Writer::dump( } status_t MPEG4Writer::Track::dump( - int fd, const Vector<String16>& args) const { + int fd, const Vector<String16>& /* args */) const { const size_t SIZE = 256; char buffer[SIZE]; String8 result; @@ -861,11 +863,11 @@ status_t MPEG4Writer::reset() { // Fix up the size of the 'mdat' chunk. if (mUse32BitOffset) { lseek64(mFd, mMdatOffset, SEEK_SET); - int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset)); + uint32_t size = htonl(static_cast<uint32_t>(mOffset - mMdatOffset)); ::write(mFd, &size, 4); } else { lseek64(mFd, mMdatOffset + 8, SEEK_SET); - int64_t size = mOffset - mMdatOffset; + uint64_t size = mOffset - mMdatOffset; size = hton64(size); ::write(mFd, &size, 8); } @@ -2278,6 +2280,22 @@ status_t MPEG4Writer::Track::threadEntry() { return UNKNOWN_ERROR; } + // if the duration is different for this sample, see if it is close enough to the previous + // duration that we can fudge it and use the same value, to avoid filling the stts table + // with lots of near-identical entries. + // "close enough" here means that the current duration needs to be adjusted by less + // than 0.1 milliseconds + if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) { + int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL + + (mTimeScale / 2)) / mTimeScale; + if (deltaUs > -100 && deltaUs < 100) { + // use previous ticks, and adjust timestamp as if it was actually that number + // of ticks + currDurationTicks = lastDurationTicks; + timestampUs += deltaUs; + } + } + mStszTableEntries->add(htonl(sampleSize)); if (mStszTableEntries->count() > 2) { diff --git a/media/libstagefright/MediaAdapter.cpp b/media/libstagefright/MediaAdapter.cpp index 2484212..d680e0c 100644 --- a/media/libstagefright/MediaAdapter.cpp +++ b/media/libstagefright/MediaAdapter.cpp @@ -36,7 +36,7 @@ MediaAdapter::~MediaAdapter() { CHECK(mCurrentMediaBuffer == NULL); } -status_t MediaAdapter::start(MetaData *params) { +status_t MediaAdapter::start(MetaData * /* params */) { Mutex::Autolock autoLock(mAdapterLock); if (!mStarted) { mStarted = true; @@ -75,7 +75,7 @@ void MediaAdapter::signalBufferReturned(MediaBuffer *buffer) { } status_t MediaAdapter::read( - MediaBuffer **buffer, const ReadOptions *options) { + MediaBuffer **buffer, const ReadOptions * /* options */) { Mutex::Autolock autoLock(mAdapterLock); if (!mStarted) { ALOGV("Read before even started!"); diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index c4c47b3..fe21296 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -115,7 +115,7 @@ status_t MediaCodec::init(const char *name, bool nameIsType, bool encoder) { if (codecIdx >= 0) { Vector<AString> types; if (mcl->getSupportedTypes(codecIdx, &types) == OK) { - for (int i = 0; i < types.size(); i++) { + for (size_t i = 0; i < types.size(); i++) { if (types[i].startsWith("video/")) { needDedicatedLooper = true; break; diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp index 2c20d62..924173c 100644 --- a/media/libstagefright/MediaCodecSource.cpp +++ b/media/libstagefright/MediaCodecSource.cpp @@ -293,8 +293,8 @@ sp<IGraphicBufferProducer> MediaCodecSource::getGraphicBufferProducer() { return mGraphicBufferProducer; } -status_t MediaCodecSource::read(MediaBuffer** buffer, - const ReadOptions* options) { +status_t MediaCodecSource::read( + MediaBuffer** buffer, const ReadOptions* /* options */) { Mutex::Autolock autolock(mOutputBufferLock); *buffer = NULL; diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp index 1287fb1..72ea32d 100644 --- a/media/libstagefright/NuCachedSource2.cpp +++ b/media/libstagefright/NuCachedSource2.cpp @@ -333,7 +333,7 @@ void NuCachedSource2::fetchInternal() { mNumRetriesLeft = 0; } - ALOGE("source returned error %ld, %d retries left", n, mNumRetriesLeft); + ALOGE("source returned error %d, %d retries left", n, mNumRetriesLeft); mCache->releasePage(page); } else if (n == 0) { ALOGI("ERROR_END_OF_STREAM"); @@ -648,7 +648,7 @@ void NuCachedSource2::updateCacheParamsFromString(const char *s) { ssize_t lowwaterMarkKb, highwaterMarkKb; int keepAliveSecs; - if (sscanf(s, "%ld/%ld/%d", + if (sscanf(s, "%d/%d/%d", &lowwaterMarkKb, &highwaterMarkKb, &keepAliveSecs) != 3) { ALOGE("Failed to parse cache parameters from '%s'.", s); return; diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp index 5e79e78..f3eeb03 100644 --- a/media/libstagefright/OggExtractor.cpp +++ b/media/libstagefright/OggExtractor.cpp @@ -151,7 +151,7 @@ sp<MetaData> OggSource::getFormat() { return mExtractor->mImpl->getFormat(); } -status_t OggSource::start(MetaData *params) { +status_t OggSource::start(MetaData * /* params */) { if (mStarted) { return INVALID_OPERATION; } @@ -381,7 +381,7 @@ ssize_t MyVorbisExtractor::readPage(off64_t offset, Page *page) { ssize_t n; if ((n = mSource->readAt(offset, header, sizeof(header))) < (ssize_t)sizeof(header)) { - ALOGV("failed to read %d bytes at offset 0x%016llx, got %ld bytes", + ALOGV("failed to read %zu bytes at offset 0x%016llx, got %d bytes", sizeof(header), offset, n); if (n < 0) { @@ -505,7 +505,7 @@ status_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) { packetSize); if (n < (ssize_t)packetSize) { - ALOGV("failed to read %d bytes at 0x%016llx, got %ld bytes", + ALOGV("failed to read %zu bytes at 0x%016llx, got %d bytes", packetSize, dataOffset, n); return ERROR_IO; } @@ -546,7 +546,7 @@ status_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) { buffer = NULL; } - ALOGV("readPage returned %ld", n); + ALOGV("readPage returned %d", n); return n < 0 ? n : (status_t)ERROR_END_OF_STREAM; } @@ -998,7 +998,7 @@ sp<MediaSource> OggExtractor::getTrack(size_t index) { } sp<MetaData> OggExtractor::getTrackMetaData( - size_t index, uint32_t flags) { + size_t index, uint32_t /* flags */) { if (index >= 1) { return NULL; } diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp index edd12fc..fe20835 100644 --- a/media/libstagefright/StagefrightMediaScanner.cpp +++ b/media/libstagefright/StagefrightMediaScanner.cpp @@ -118,7 +118,7 @@ MediaScanResult StagefrightMediaScanner::processFile( } MediaScanResult StagefrightMediaScanner::processFileInternal( - const char *path, const char *mimeType, + const char *path, const char * /* mimeType */, MediaScannerClient &client) { const char *extension = strrchr(path, '.'); diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp index 94c0a1e..10c00f4 100644 --- a/media/libstagefright/SurfaceMediaSource.cpp +++ b/media/libstagefright/SurfaceMediaSource.cpp @@ -99,8 +99,11 @@ void SurfaceMediaSource::dump(String8& result) const dump(result, "", buffer, 1024); } -void SurfaceMediaSource::dump(String8& result, const char* prefix, - char* buffer, size_t SIZE) const +void SurfaceMediaSource::dump( + String8& result, + const char* /* prefix */, + char* buffer, + size_t /* SIZE */) const { Mutex::Autolock lock(mMutex); @@ -270,9 +273,8 @@ static void passMetadataBuffer(MediaBuffer **buffer, bufferHandle, (*buffer)->range_length(), (*buffer)->range_offset()); } -status_t SurfaceMediaSource::read( MediaBuffer **buffer, - const ReadOptions *options) -{ +status_t SurfaceMediaSource::read( + MediaBuffer **buffer, const ReadOptions * /* options */) { ALOGV("read"); Mutex::Autolock lock(mMutex); diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp index 0afac69..3d2eb1f 100644 --- a/media/libstagefright/TimedEventQueue.cpp +++ b/media/libstagefright/TimedEventQueue.cpp @@ -376,8 +376,8 @@ void TimedEventQueue::clearPowerManager() mPowerManager.clear(); } -void TimedEventQueue::PMDeathRecipient::binderDied(const wp<IBinder>& who) -{ +void TimedEventQueue::PMDeathRecipient::binderDied( + const wp<IBinder>& /* who */) { mQueue->clearPowerManager(); } diff --git a/media/libstagefright/VBRISeeker.cpp b/media/libstagefright/VBRISeeker.cpp index a245f2c..af858b9 100644 --- a/media/libstagefright/VBRISeeker.cpp +++ b/media/libstagefright/VBRISeeker.cpp @@ -119,7 +119,7 @@ sp<VBRISeeker> VBRISeeker::CreateFromSource( seeker->mSegments.push(numBytes); - ALOGV("entry #%d: %d offset 0x%08lx", i, numBytes, offset); + ALOGV("entry #%d: %u offset 0x%016llx", i, numBytes, offset); offset += numBytes; } @@ -160,7 +160,7 @@ bool VBRISeeker::getOffsetForTime(int64_t *timeUs, off64_t *pos) { *pos += mSegments.itemAt(segmentIndex++); } - ALOGV("getOffsetForTime %lld us => 0x%08lx", *timeUs, *pos); + ALOGV("getOffsetForTime %lld us => 0x%016llx", *timeUs, *pos); *timeUs = nowUs; diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp index 22af6fb..fe9058b 100644 --- a/media/libstagefright/WAVExtractor.cpp +++ b/media/libstagefright/WAVExtractor.cpp @@ -127,7 +127,7 @@ sp<MediaSource> WAVExtractor::getTrack(size_t index) { } sp<MetaData> WAVExtractor::getTrackMetaData( - size_t index, uint32_t flags) { + size_t index, uint32_t /* flags */) { if (mInitCheck != OK || index > 0) { return NULL; } @@ -358,7 +358,7 @@ WAVSource::~WAVSource() { } } -status_t WAVSource::start(MetaData *params) { +status_t WAVSource::start(MetaData * /* params */) { ALOGV("WAVSource::start"); CHECK(!mStarted); diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp index b822868..38a1f6b 100644 --- a/media/libstagefright/avc_utils.cpp +++ b/media/libstagefright/avc_utils.cpp @@ -40,6 +40,25 @@ unsigned parseUE(ABitReader *br) { return x + (1u << numZeroes) - 1; } +signed parseSE(ABitReader *br) { + unsigned codeNum = parseUE(br); + + return (codeNum & 1) ? (codeNum + 1) / 2 : -(codeNum / 2); +} + +static void skipScalingList(ABitReader *br, size_t sizeOfScalingList) { + size_t lastScale = 8; + size_t nextScale = 8; + for (size_t j = 0; j < sizeOfScalingList; ++j) { + if (nextScale != 0) { + signed delta_scale = parseSE(br); + nextScale = (lastScale + delta_scale + 256) % 256; + } + + lastScale = (nextScale == 0) ? lastScale : nextScale; + } +} + // Determine video dimensions from the sequence parameterset. void FindAVCDimensions( const sp<ABuffer> &seqParamSet, @@ -63,7 +82,24 @@ void FindAVCDimensions( parseUE(&br); // bit_depth_luma_minus8 parseUE(&br); // bit_depth_chroma_minus8 br.skipBits(1); // qpprime_y_zero_transform_bypass_flag - CHECK_EQ(br.getBits(1), 0u); // seq_scaling_matrix_present_flag + + if (br.getBits(1)) { // seq_scaling_matrix_present_flag + for (size_t i = 0; i < 8; ++i) { + if (br.getBits(1)) { // seq_scaling_list_present_flag[i] + + // WARNING: the code below has not ever been exercised... + // need a real-world example. + + if (i < 6) { + // ScalingList4x4[i],16,... + skipScalingList(&br, 16); + } else { + // ScalingList8x8[i-6],64,... + skipScalingList(&br, 64); + } + } + } + } } parseUE(&br); // log2_max_frame_num_minus4 @@ -251,9 +287,7 @@ status_t getNextNALUnit( return OK; } -static sp<ABuffer> FindNAL( - const uint8_t *data, size_t size, unsigned nalType, - size_t *stopOffset) { +static sp<ABuffer> FindNAL(const uint8_t *data, size_t size, unsigned nalType) { const uint8_t *nalStart; size_t nalSize; while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) { @@ -293,7 +327,7 @@ sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit) { const uint8_t *data = accessUnit->data(); size_t size = accessUnit->size(); - sp<ABuffer> seqParamSet = FindNAL(data, size, 7, NULL); + sp<ABuffer> seqParamSet = FindNAL(data, size, 7); if (seqParamSet == NULL) { return NULL; } @@ -303,8 +337,7 @@ sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit) { FindAVCDimensions( seqParamSet, &width, &height, &sarWidth, &sarHeight); - size_t stopOffset; - sp<ABuffer> picParamSet = FindNAL(data, size, 8, &stopOffset); + sp<ABuffer> picParamSet = FindNAL(data, size, 8); CHECK(picParamSet != NULL); size_t csdSize = diff --git a/media/libstagefright/codecs/aacdec/Android.mk b/media/libstagefright/codecs/aacdec/Android.mk index ffa64f9..49ff238 100644 --- a/media/libstagefright/codecs/aacdec/Android.mk +++ b/media/libstagefright/codecs/aacdec/Android.mk @@ -17,6 +17,8 @@ LOCAL_C_INCLUDES := \ LOCAL_CFLAGS := +LOCAL_CFLAGS += -Werror + LOCAL_STATIC_LIBRARIES := libFraunhoferAAC LOCAL_SHARED_LIBRARIES := \ diff --git a/media/libstagefright/codecs/aacenc/Android.mk b/media/libstagefright/codecs/aacenc/Android.mk index 057c69b..58ec3ba 100644 --- a/media/libstagefright/codecs/aacenc/Android.mk +++ b/media/libstagefright/codecs/aacenc/Android.mk @@ -82,6 +82,8 @@ LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV7 endif +LOCAL_CFLAGS += -Werror + include $(BUILD_STATIC_LIBRARY) ################################################################################ @@ -106,6 +108,8 @@ ifeq ($(AAC_LIBRARY), fraunhofer) LOCAL_CFLAGS := + LOCAL_CFLAGS += -Werror + LOCAL_STATIC_LIBRARIES := libFraunhoferAAC LOCAL_SHARED_LIBRARIES := \ @@ -128,6 +132,8 @@ else # visualon LOCAL_CFLAGS := -DOSCL_IMPORT_REF= + LOCAL_CFLAGS += -Werror + LOCAL_STATIC_LIBRARIES := \ libstagefright_aacenc diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp index ff2b503..9a91579 100644 --- a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp +++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp @@ -338,7 +338,7 @@ status_t SoftAACEncoder2::setAudioParams() { return OK; } -void SoftAACEncoder2::onQueueFilled(OMX_U32 portIndex) { +void SoftAACEncoder2::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError) { return; } diff --git a/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c index cc01927..1d029fc 100644 --- a/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c +++ b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c @@ -24,6 +24,8 @@ #include "basic_op.h" #include "oper_32b.h" +#define UNUSED(x) (void)(x) + /***************************************************************************** * * * Function L_Extract() * @@ -243,6 +245,8 @@ Word16 iLog4(Word32 value) Word32 rsqrt(Word32 value, /*!< Operand to square root (0.0 ... 1) */ Word32 accuracy) /*!< Number of valid bits that will be calculated */ { + UNUSED(accuracy); + Word32 root = 0; Word32 scale; diff --git a/media/libstagefright/codecs/aacenc/src/aacenc.c b/media/libstagefright/codecs/aacenc/src/aacenc.c index d1c8621..40db92c 100644 --- a/media/libstagefright/codecs/aacenc/src/aacenc.c +++ b/media/libstagefright/codecs/aacenc/src/aacenc.c @@ -27,6 +27,8 @@ #include "cmnMemory.h" #include "memalign.h" +#define UNUSED(x) (void)(x) + /** * Init the audio codec module and return codec handle * \param phCodec [OUT] Return the video codec handle @@ -46,6 +48,8 @@ VO_U32 VO_API voAACEncInit(VO_HANDLE * phCodec,VO_AUDIO_CODINGTYPE vType, VO_COD VO_MEM_OPERATOR *pMemOP; int interMem; + UNUSED(vType); + interMem = 0; error = 0; @@ -471,6 +475,10 @@ VO_U32 VO_API voAACEncSetParam(VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData) */ VO_U32 VO_API voAACEncGetParam(VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData) { + UNUSED(hCodec); + UNUSED(uParamID); + UNUSED(pData); + return VO_ERR_NONE; } diff --git a/media/libstagefright/codecs/aacenc/src/adj_thr.c b/media/libstagefright/codecs/aacenc/src/adj_thr.c index ccfe883..471631c 100644 --- a/media/libstagefright/codecs/aacenc/src/adj_thr.c +++ b/media/libstagefright/codecs/aacenc/src/adj_thr.c @@ -72,7 +72,7 @@ static void calcThreshExp(Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB], const Word16 nChannels) { Word16 ch, sfb, sfbGrp; - Word32 *pthrExp, *psfbThre; + Word32 *pthrExp = NULL, *psfbThre; for (ch=0; ch<nChannels; ch++) { PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch]; for(sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; sfbGrp+= psyOutChan->sfbPerGroup) diff --git a/media/libstagefright/codecs/aacenc/src/bitenc.c b/media/libstagefright/codecs/aacenc/src/bitenc.c index fcc12dd..d1fd647 100644 --- a/media/libstagefright/codecs/aacenc/src/bitenc.c +++ b/media/libstagefright/codecs/aacenc/src/bitenc.c @@ -26,6 +26,7 @@ #include "qc_data.h" #include "interface.h" +#define UNUSED(x) (void)(x) static const Word16 globalGainOffset = 100; static const Word16 icsReservedBit = 0; @@ -585,6 +586,8 @@ Word16 WriteBitstream (HANDLE_BIT_BUF hBitStream, Word16 elementUsedBits; Word16 frameBits=0; + UNUSED(ancBytes); + /* struct bitbuffer bsWriteCopy; */ bitMarkUp = GetBitsAvail(hBitStream); if(qcOut->qcElement.adtsUsed) /* write adts header*/ diff --git a/media/libstagefright/codecs/aacenc/src/dyn_bits.c b/media/libstagefright/codecs/aacenc/src/dyn_bits.c index 7769188..4d763d0 100644 --- a/media/libstagefright/codecs/aacenc/src/dyn_bits.c +++ b/media/libstagefright/codecs/aacenc/src/dyn_bits.c @@ -25,7 +25,6 @@ #include "bit_cnt.h" #include "psy_const.h" - /***************************************************************************** * * function name: buildBitLookUp @@ -226,7 +225,7 @@ gmStage2(SECTION_INFO *sectionInfo, } while (TRUE) { - Word16 maxMergeGain, maxNdx, maxNdxNext, maxNdxLast; + Word16 maxMergeGain, maxNdx = 0, maxNdxNext, maxNdxLast; maxMergeGain = findMaxMerge(mergeGainLookUp, sectionInfo, maxSfb, &maxNdx); diff --git a/media/libstagefright/codecs/aacenc/src/psy_main.c b/media/libstagefright/codecs/aacenc/src/psy_main.c index 4e9218c..6f0679c 100644 --- a/media/libstagefright/codecs/aacenc/src/psy_main.c +++ b/media/libstagefright/codecs/aacenc/src/psy_main.c @@ -38,6 +38,8 @@ #include "tns_func.h" #include "memalign.h" +#define UNUSED(x) (void)(x) + /* long start short stop */ static Word16 blockType2windowShape[] = {KBD_WINDOW,SINE_WINDOW,SINE_WINDOW,KBD_WINDOW}; @@ -170,7 +172,9 @@ Word16 PsyOutNew(PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP) *****************************************************************************/ Word16 PsyOutDelete(PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP) { - hPsyOut=NULL; + UNUSED(hPsyOut); + UNUSED(pMemOP); + return 0; } diff --git a/media/libstagefright/codecs/aacenc/src/qc_main.c b/media/libstagefright/codecs/aacenc/src/qc_main.c index 48ff300..e5d78aa 100644 --- a/media/libstagefright/codecs/aacenc/src/qc_main.c +++ b/media/libstagefright/codecs/aacenc/src/qc_main.c @@ -33,6 +33,7 @@ #include "channel_map.h" #include "memalign.h" +#define UNUSED(x) (void)(x) typedef enum{ FRAME_LEN_BYTES_MODULO = 1, @@ -204,11 +205,8 @@ Word16 QCNew(QC_STATE *hQC, VO_MEM_OPERATOR *pMemOP) **********************************************************************************/ void QCDelete(QC_STATE *hQC, VO_MEM_OPERATOR *pMemOP) { - - /* - nothing to do - */ - hQC=NULL; + UNUSED(hQC); + UNUSED(pMemOP); } /********************************************************************************* diff --git a/media/libstagefright/codecs/aacenc/src/tns.c b/media/libstagefright/codecs/aacenc/src/tns.c index 455a864..5172612 100644 --- a/media/libstagefright/codecs/aacenc/src/tns.c +++ b/media/libstagefright/codecs/aacenc/src/tns.c @@ -30,6 +30,8 @@ #include "psy_configuration.h" #include "tns_func.h" +#define UNUSED(x) (void)(x) + #define TNS_MODIFY_BEGIN 2600 /* Hz */ #define RATIO_PATCH_LOWER_BORDER 380 /* Hz */ #define TNS_GAIN_THRESH 141 /* 1.41*100 */ @@ -643,6 +645,8 @@ static Word16 CalcTnsFilter(const Word16 *signal, Word32 i; Word32 tnsOrderPlus1 = tnsOrder + 1; + UNUSED(window); + assert(tnsOrder <= TNS_MAX_ORDER); /* remove asserts later? (btg) */ for(i=0;i<tnsOrder;i++) { diff --git a/media/libstagefright/codecs/amrnb/common/Android.mk b/media/libstagefright/codecs/amrnb/common/Android.mk index 30ce29c..a2b3c8f 100644 --- a/media/libstagefright/codecs/amrnb/common/Android.mk +++ b/media/libstagefright/codecs/amrnb/common/Android.mk @@ -69,6 +69,8 @@ LOCAL_C_INCLUDES := \ LOCAL_CFLAGS := \ -DOSCL_UNUSED_ARG= -DOSCL_IMPORT_REF= -DOSCL_EXPORT_REF= +LOCAL_CFLAGS += -Werror + LOCAL_MODULE := libstagefright_amrnb_common include $(BUILD_SHARED_LIBRARY) diff --git a/media/libstagefright/codecs/amrnb/dec/Android.mk b/media/libstagefright/codecs/amrnb/dec/Android.mk index 8d6c6f8..b067456 100644 --- a/media/libstagefright/codecs/amrnb/dec/Android.mk +++ b/media/libstagefright/codecs/amrnb/dec/Android.mk @@ -47,6 +47,8 @@ LOCAL_C_INCLUDES := \ LOCAL_CFLAGS := \ -DOSCL_UNUSED_ARG= -DOSCL_IMPORT_REF= +LOCAL_CFLAGS += -Werror + LOCAL_MODULE := libstagefright_amrnbdec include $(BUILD_STATIC_LIBRARY) @@ -68,6 +70,8 @@ LOCAL_C_INCLUDES := \ LOCAL_CFLAGS := -DOSCL_IMPORT_REF= +LOCAL_CFLAGS += -Werror + LOCAL_STATIC_LIBRARIES := \ libstagefright_amrnbdec libstagefright_amrwbdec diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp index 3320688..d1b0f76 100644 --- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp +++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp @@ -274,7 +274,7 @@ static size_t getFrameSize(unsigned FT) { return frameSize; } -void SoftAMR::onQueueFilled(OMX_U32 portIndex) { +void SoftAMR::onQueueFilled(OMX_U32 /* portIndex */) { List<BufferInfo *> &inQueue = getPortQueue(0); List<BufferInfo *> &outQueue = getPortQueue(1); @@ -428,7 +428,7 @@ void SoftAMR::onQueueFilled(OMX_U32 portIndex) { } } -void SoftAMR::onPortFlushCompleted(OMX_U32 portIndex) { +void SoftAMR::onPortFlushCompleted(OMX_U32 /* portIndex */) { } void SoftAMR::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) { diff --git a/media/libstagefright/codecs/amrnb/enc/Android.mk b/media/libstagefright/codecs/amrnb/enc/Android.mk index f4e467a..afc0b89 100644 --- a/media/libstagefright/codecs/amrnb/enc/Android.mk +++ b/media/libstagefright/codecs/amrnb/enc/Android.mk @@ -69,6 +69,8 @@ LOCAL_C_INCLUDES := \ LOCAL_CFLAGS := \ -DOSCL_UNUSED_ARG= +LOCAL_CFLAGS += -Werror + LOCAL_MODULE := libstagefright_amrnbenc include $(BUILD_STATIC_LIBRARY) @@ -88,6 +90,8 @@ LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/../common/include \ $(LOCAL_PATH)/../common +LOCAL_CFLAGS += -Werror + LOCAL_STATIC_LIBRARIES := \ libstagefright_amrnbenc diff --git a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp index 50b739c..9489457 100644 --- a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp +++ b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp @@ -270,7 +270,7 @@ OMX_ERRORTYPE SoftAMRNBEncoder::internalSetParameter( } } -void SoftAMRNBEncoder::onQueueFilled(OMX_U32 portIndex) { +void SoftAMRNBEncoder::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError) { return; } diff --git a/media/libstagefright/codecs/amrwb/Android.mk b/media/libstagefright/codecs/amrwb/Android.mk index 677107f..efdf988 100644 --- a/media/libstagefright/codecs/amrwb/Android.mk +++ b/media/libstagefright/codecs/amrwb/Android.mk @@ -50,6 +50,8 @@ LOCAL_C_INCLUDES := \ LOCAL_CFLAGS := \ -DOSCL_UNUSED_ARG= -DOSCL_IMPORT_REF= +LOCAL_CFLAGS += -Werror + LOCAL_MODULE := libstagefright_amrwbdec include $(BUILD_STATIC_LIBRARY) diff --git a/media/libstagefright/codecs/amrwbenc/Android.mk b/media/libstagefright/codecs/amrwbenc/Android.mk index c5b8e0c..64fe8d1 100644 --- a/media/libstagefright/codecs/amrwbenc/Android.mk +++ b/media/libstagefright/codecs/amrwbenc/Android.mk @@ -112,6 +112,8 @@ LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV7 endif +LOCAL_CFLAGS += -Werror + include $(BUILD_STATIC_LIBRARY) ################################################################################ @@ -126,6 +128,8 @@ LOCAL_C_INCLUDES := \ frameworks/av/media/libstagefright/codecs/common/include \ frameworks/native/include/media/openmax +LOCAL_CFLAGS += -Werror + LOCAL_STATIC_LIBRARIES := \ libstagefright_amrwbenc diff --git a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp index 9ccb49c..91a512d 100644 --- a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp +++ b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp @@ -317,7 +317,7 @@ OMX_ERRORTYPE SoftAMRWBEncoder::internalSetParameter( } } -void SoftAMRWBEncoder::onQueueFilled(OMX_U32 portIndex) { +void SoftAMRWBEncoder::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError) { return; } diff --git a/media/libstagefright/codecs/amrwbenc/src/autocorr.c b/media/libstagefright/codecs/amrwbenc/src/autocorr.c index 8c477ca..0b2ea89 100644 --- a/media/libstagefright/codecs/amrwbenc/src/autocorr.c +++ b/media/libstagefright/codecs/amrwbenc/src/autocorr.c @@ -28,6 +28,8 @@ #include "acelp.h" #include "ham_wind.tab" +#define UNUSED(x) (void)(x) + void Autocorr( Word16 x[], /* (i) : Input signal */ Word16 m, /* (i) : LPC order */ @@ -40,6 +42,8 @@ void Autocorr( Word32 L_sum, L_sum1, L_tmp, F_LEN; Word16 *p1,*p2,*p3; const Word16 *p4; + UNUSED(m); + /* Windowing of signal */ p1 = x; p4 = vo_window; diff --git a/media/libstagefright/codecs/amrwbenc/src/convolve.c b/media/libstagefright/codecs/amrwbenc/src/convolve.c index acba532..4c1f7d4 100644 --- a/media/libstagefright/codecs/amrwbenc/src/convolve.c +++ b/media/libstagefright/codecs/amrwbenc/src/convolve.c @@ -25,6 +25,8 @@ #include "typedef.h" #include "basic_op.h" +#define UNUSED(x) (void)(x) + void Convolve ( Word16 x[], /* (i) : input vector */ Word16 h[], /* (i) : impulse response */ @@ -35,6 +37,8 @@ void Convolve ( Word32 i, n; Word16 *tmpH,*tmpX; Word32 s; + UNUSED(L); + for (n = 0; n < 64;) { tmpH = h+n; diff --git a/media/libstagefright/codecs/amrwbenc/src/pitch_f4.c b/media/libstagefright/codecs/amrwbenc/src/pitch_f4.c index 0d66c31..b66b55e 100644 --- a/media/libstagefright/codecs/amrwbenc/src/pitch_f4.c +++ b/media/libstagefright/codecs/amrwbenc/src/pitch_f4.c @@ -31,6 +31,8 @@ #define UP_SAMP 4 #define L_INTERPOL1 4 +#define UNUSED(x) (void)(x) + /* Local functions */ #ifdef ASM_OPT @@ -171,6 +173,7 @@ static void Norm_Corr( Word32 corr, exp_corr, norm, exp, scale; Word16 exp_norm, excf[L_SUBFR], tmp; Word32 L_tmp, L_tmp1, L_tmp2; + UNUSED(L_subfr); /* compute the filtered excitation for the first delay t_min */ k = -t_min; diff --git a/media/libstagefright/codecs/amrwbenc/src/syn_filt.c b/media/libstagefright/codecs/amrwbenc/src/syn_filt.c index 1bda05a..961aadc 100644 --- a/media/libstagefright/codecs/amrwbenc/src/syn_filt.c +++ b/media/libstagefright/codecs/amrwbenc/src/syn_filt.c @@ -26,6 +26,8 @@ #include "math_op.h" #include "cnst.h" +#define UNUSED(x) (void)(x) + void Syn_filt( Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */ Word16 x[], /* (i) : input signal */ @@ -95,6 +97,8 @@ void Syn_filt_32( Word32 i,a0; Word32 L_tmp, L_tmp1; Word16 *p1, *p2, *p3; + UNUSED(m); + a0 = a[0] >> (4 + Qnew); /* input / 16 and >>Qnew */ /* Do the filtering. */ for (i = 0; i < lg; i++) diff --git a/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c b/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c index ea9da52..df7b9b3 100644 --- a/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c +++ b/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c @@ -39,6 +39,8 @@ #include "mem_align.h" #include "cmnMemory.h" +#define UNUSED(x) (void)(x) + #ifdef __cplusplus extern "C" { #endif @@ -1602,6 +1604,8 @@ VO_U32 VO_API voAMRWB_Init(VO_HANDLE * phCodec, /* o: the audi VO_MEM_OPERATOR voMemoprator; #endif VO_MEM_OPERATOR *pMemOP; + UNUSED(vType); + int interMem = 0; if(pUserData == NULL || pUserData->memflag != VO_IMF_USERMEMOPERATOR || pUserData->memData == NULL ) diff --git a/media/libstagefright/codecs/avc/common/Android.mk b/media/libstagefright/codecs/avc/common/Android.mk index 22dee15..844ef0a 100644 --- a/media/libstagefright/codecs/avc/common/Android.mk +++ b/media/libstagefright/codecs/avc/common/Android.mk @@ -16,4 +16,6 @@ LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/src \ $(LOCAL_PATH)/include +LOCAL_CFLAGS += -Werror + include $(BUILD_SHARED_LIBRARY) diff --git a/media/libstagefright/codecs/avc/enc/Android.mk b/media/libstagefright/codecs/avc/enc/Android.mk index 7d17c2a..537ba42 100644 --- a/media/libstagefright/codecs/avc/enc/Android.mk +++ b/media/libstagefright/codecs/avc/enc/Android.mk @@ -30,6 +30,8 @@ LOCAL_C_INCLUDES := \ LOCAL_CFLAGS := \ -DOSCL_IMPORT_REF= -DOSCL_UNUSED_ARG= -DOSCL_EXPORT_REF= +LOCAL_CFLAGS += -Werror + include $(BUILD_STATIC_LIBRARY) ################################################################################ @@ -69,4 +71,6 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_MODULE := libstagefright_soft_h264enc LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS += -Werror + include $(BUILD_SHARED_LIBRARY) diff --git a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp index 1d398fb..a15b040 100644 --- a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp +++ b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp @@ -34,6 +34,12 @@ #include "SoftAVCEncoder.h" +#if LOG_NDEBUG +#define UNUSED_UNLESS_VERBOSE(x) (void)(x) +#else +#define UNUSED_UNLESS_VERBOSE(x) +#endif + namespace android { template<class T> @@ -136,14 +142,14 @@ inline static void ConvertYUV420SemiPlanarToYUV420Planar( } static void* MallocWrapper( - void *userData, int32_t size, int32_t attrs) { + void * /* userData */, int32_t size, int32_t /* attrs */) { void *ptr = malloc(size); if (ptr) memset(ptr, 0, size); return ptr; } -static void FreeWrapper(void *userData, void* ptr) { +static void FreeWrapper(void * /* userData */, void* ptr) { free(ptr); } @@ -217,7 +223,7 @@ OMX_ERRORTYPE SoftAVCEncoder::initEncParams() { mHandle->CBAVC_Free = FreeWrapper; CHECK(mEncParams != NULL); - memset(mEncParams, 0, sizeof(mEncParams)); + memset(mEncParams, 0, sizeof(*mEncParams)); mEncParams->rate_control = AVC_ON; mEncParams->initQP = 0; mEncParams->init_CBP_removal_delay = 1600; @@ -722,7 +728,7 @@ OMX_ERRORTYPE SoftAVCEncoder::internalSetParameter( } } -void SoftAVCEncoder::onQueueFilled(OMX_U32 portIndex) { +void SoftAVCEncoder::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError || mSawInputEOS) { return; } @@ -795,7 +801,7 @@ void SoftAVCEncoder::onQueueFilled(OMX_U32 portIndex) { } } - buffer_handle_t srcBuffer; // for MetaDataMode only + buffer_handle_t srcBuffer = NULL; // for MetaDataMode only // Get next input video frame if (mReadyForNextFrame) { @@ -964,6 +970,7 @@ int32_t SoftAVCEncoder::bindOutputBuffer(int32_t index, uint8_t **yuv) { } void SoftAVCEncoder::signalBufferReturned(MediaBuffer *buffer) { + UNUSED_UNLESS_VERBOSE(buffer); ALOGV("signalBufferReturned: %p", buffer); } diff --git a/media/libstagefright/codecs/avc/enc/src/bitstream_io.cpp b/media/libstagefright/codecs/avc/enc/src/bitstream_io.cpp index 0e3037f..d71c327 100644 --- a/media/libstagefright/codecs/avc/enc/src/bitstream_io.cpp +++ b/media/libstagefright/codecs/avc/enc/src/bitstream_io.cpp @@ -103,6 +103,15 @@ AVCEnc_Status AVCBitstreamSaveWord(AVCEncBitstream *stream) { num_bits -= 8; byte = (current_word >> num_bits) & 0xFF; + if (stream->count_zeros == 2) + { /* for num_bits = 32, this can add 2 more bytes extra for EPBS */ + if (byte <= 3) + { + *write_pnt++ = 0x3; + stream->write_pos++; + stream->count_zeros = 0; + } + } if (byte != 0) { *write_pnt++ = byte; @@ -114,12 +123,6 @@ AVCEnc_Status AVCBitstreamSaveWord(AVCEncBitstream *stream) stream->count_zeros++; *write_pnt++ = byte; stream->write_pos++; - if (stream->count_zeros == 2) - { /* for num_bits = 32, this can add 2 more bytes extra for EPBS */ - *write_pnt++ = 0x3; - stream->write_pos++; - stream->count_zeros = 0; - } } } diff --git a/media/libstagefright/codecs/common/Android.mk b/media/libstagefright/codecs/common/Android.mk index a33cb92..b0010ff 100644 --- a/media/libstagefright/codecs/common/Android.mk +++ b/media/libstagefright/codecs/common/Android.mk @@ -14,6 +14,8 @@ LOCAL_STATIC_LIBRARIES := LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/include +LOCAL_CFLAGS += -Werror + include $(BUILD_SHARED_LIBRARY) diff --git a/media/libstagefright/codecs/common/cmnMemory.c b/media/libstagefright/codecs/common/cmnMemory.c index aa52bd9..5bb6cc4 100644 --- a/media/libstagefright/codecs/common/cmnMemory.c +++ b/media/libstagefright/codecs/common/cmnMemory.c @@ -26,8 +26,12 @@ //VO_MEM_OPERATOR g_memOP; +#define UNUSED(x) (void)(x) + VO_U32 cmnMemAlloc (VO_S32 uID, VO_MEM_INFO * pMemInfo) { + UNUSED(uID); + if (!pMemInfo) return VO_ERR_INVALID_ARG; @@ -37,34 +41,48 @@ VO_U32 cmnMemAlloc (VO_S32 uID, VO_MEM_INFO * pMemInfo) VO_U32 cmnMemFree (VO_S32 uID, VO_PTR pMem) { + UNUSED(uID); + free (pMem); return 0; } VO_U32 cmnMemSet (VO_S32 uID, VO_PTR pBuff, VO_U8 uValue, VO_U32 uSize) { + UNUSED(uID); + memset (pBuff, uValue, uSize); return 0; } VO_U32 cmnMemCopy (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize) { + UNUSED(uID); + memcpy (pDest, pSource, uSize); return 0; } VO_U32 cmnMemCheck (VO_S32 uID, VO_PTR pBuffer, VO_U32 uSize) { + UNUSED(uID); + UNUSED(pBuffer); + UNUSED(uSize); + return 0; } VO_S32 cmnMemCompare (VO_S32 uID, VO_PTR pBuffer1, VO_PTR pBuffer2, VO_U32 uSize) { + UNUSED(uID); + return memcmp(pBuffer1, pBuffer2, uSize); } VO_U32 cmnMemMove (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize) { + UNUSED(uID); + memmove (pDest, pSource, uSize); return 0; } diff --git a/media/libstagefright/codecs/flac/enc/Android.mk b/media/libstagefright/codecs/flac/enc/Android.mk index f01d605..59a11de 100644 --- a/media/libstagefright/codecs/flac/enc/Android.mk +++ b/media/libstagefright/codecs/flac/enc/Android.mk @@ -9,6 +9,8 @@ LOCAL_C_INCLUDES := \ frameworks/native/include/media/openmax \ external/flac/include +LOCAL_CFLAGS += -Werror + LOCAL_SHARED_LIBRARIES := \ libstagefright libstagefright_omx libstagefright_foundation libutils liblog diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp index e64fe72..40661e7 100644 --- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp +++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp @@ -27,6 +27,12 @@ #define FLAC_COMPRESSION_LEVEL_DEFAULT 5 #define FLAC_COMPRESSION_LEVEL_MAX 8 +#if LOG_NDEBUG +#define UNUSED_UNLESS_VERBOSE(x) (void)(x) +#else +#define UNUSED_UNLESS_VERBOSE(x) +#endif + namespace android { template<class T> @@ -257,7 +263,7 @@ OMX_ERRORTYPE SoftFlacEncoder::internalSetParameter( } void SoftFlacEncoder::onQueueFilled(OMX_U32 portIndex) { - + UNUSED_UNLESS_VERBOSE(portIndex); ALOGV("SoftFlacEncoder::onQueueFilled(portIndex=%ld)", portIndex); if (mSignalledError) { @@ -343,10 +349,11 @@ void SoftFlacEncoder::onQueueFilled(OMX_U32 portIndex) { } } - FLAC__StreamEncoderWriteStatus SoftFlacEncoder::onEncodedFlacAvailable( const FLAC__byte buffer[], - size_t bytes, unsigned samples, unsigned current_frame) { + size_t bytes, unsigned samples, + unsigned current_frame) { + UNUSED_UNLESS_VERBOSE(current_frame); ALOGV("SoftFlacEncoder::onEncodedFlacAvailable(bytes=%d, samples=%d, curr_frame=%d)", bytes, samples, current_frame); @@ -444,8 +451,12 @@ return_result: // static FLAC__StreamEncoderWriteStatus SoftFlacEncoder::flacEncoderWriteCallback( - const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], - size_t bytes, unsigned samples, unsigned current_frame, void *client_data) { + const FLAC__StreamEncoder * /* encoder */, + const FLAC__byte buffer[], + size_t bytes, + unsigned samples, + unsigned current_frame, + void *client_data) { return ((SoftFlacEncoder*) client_data)->onEncodedFlacAvailable( buffer, bytes, samples, current_frame); } diff --git a/media/libstagefright/codecs/g711/dec/Android.mk b/media/libstagefright/codecs/g711/dec/Android.mk index 4c80da6..a0112e1 100644 --- a/media/libstagefright/codecs/g711/dec/Android.mk +++ b/media/libstagefright/codecs/g711/dec/Android.mk @@ -14,4 +14,6 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_MODULE := libstagefright_soft_g711dec LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS += -Werror + include $(BUILD_SHARED_LIBRARY) diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.cpp b/media/libstagefright/codecs/g711/dec/SoftG711.cpp index bcdd3c7..160ada0 100644 --- a/media/libstagefright/codecs/g711/dec/SoftG711.cpp +++ b/media/libstagefright/codecs/g711/dec/SoftG711.cpp @@ -182,7 +182,7 @@ OMX_ERRORTYPE SoftG711::internalSetParameter( } } -void SoftG711::onQueueFilled(OMX_U32 portIndex) { +void SoftG711::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError) { return; } diff --git a/media/libstagefright/codecs/gsm/dec/Android.mk b/media/libstagefright/codecs/gsm/dec/Android.mk index 71613d2..30868d5 100644 --- a/media/libstagefright/codecs/gsm/dec/Android.mk +++ b/media/libstagefright/codecs/gsm/dec/Android.mk @@ -9,6 +9,8 @@ LOCAL_C_INCLUDES := \ frameworks/native/include/media/openmax \ external/libgsm/inc +LOCAL_CFLAGS += -Werror + LOCAL_SHARED_LIBRARIES := \ libstagefright libstagefright_omx libstagefright_foundation libutils liblog diff --git a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp index 00e0c85..18f7d29 100644 --- a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp +++ b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp @@ -172,7 +172,7 @@ OMX_ERRORTYPE SoftGSM::internalSetParameter( } } -void SoftGSM::onQueueFilled(OMX_U32 portIndex) { +void SoftGSM::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError) { return; } diff --git a/media/libstagefright/codecs/m4v_h263/dec/Android.mk b/media/libstagefright/codecs/m4v_h263/dec/Android.mk index a3d5779..1d232c6 100644 --- a/media/libstagefright/codecs/m4v_h263/dec/Android.mk +++ b/media/libstagefright/codecs/m4v_h263/dec/Android.mk @@ -46,6 +46,8 @@ LOCAL_C_INCLUDES := \ LOCAL_CFLAGS := -DOSCL_EXPORT_REF= -DOSCL_IMPORT_REF= +LOCAL_CFLAGS += -Werror + include $(BUILD_STATIC_LIBRARY) ################################################################################ @@ -72,4 +74,6 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_MODULE := libstagefright_soft_mpeg4dec LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS += -Werror + include $(BUILD_SHARED_LIBRARY) diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp index fb2a430..0d1ab71 100644 --- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp +++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp @@ -91,7 +91,7 @@ status_t SoftMPEG4::initDecoder() { return OK; } -void SoftMPEG4::onQueueFilled(OMX_U32 portIndex) { +void SoftMPEG4::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError || mOutputPortSettingsChange != NONE) { return; } diff --git a/media/libstagefright/codecs/m4v_h263/enc/Android.mk b/media/libstagefright/codecs/m4v_h263/enc/Android.mk index 83a2dd2..c9006d9 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/Android.mk +++ b/media/libstagefright/codecs/m4v_h263/enc/Android.mk @@ -33,6 +33,8 @@ LOCAL_C_INCLUDES := \ $(TOP)/frameworks/av/media/libstagefright/include \ $(TOP)/frameworks/native/include/media/openmax +LOCAL_CFLAGS += -Werror + include $(BUILD_STATIC_LIBRARY) ################################################################################ @@ -72,4 +74,6 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_MODULE := libstagefright_soft_mpeg4enc LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS += -Werror + include $(BUILD_SHARED_LIBRARY) diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp index e02af90..2c73e57 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp +++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp @@ -620,7 +620,7 @@ OMX_ERRORTYPE SoftMPEG4Encoder::internalSetParameter( } } -void SoftMPEG4Encoder::onQueueFilled(OMX_U32 portIndex) { +void SoftMPEG4Encoder::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError || mSawInputEOS) { return; } @@ -677,7 +677,7 @@ void SoftMPEG4Encoder::onQueueFilled(OMX_U32 portIndex) { mSawInputEOS = true; } - buffer_handle_t srcBuffer; // for MetaDataMode only + buffer_handle_t srcBuffer = NULL; // for MetaDataMode only if (inHeader->nFilledLen > 0) { uint8_t *inputData = NULL; if (mStoreMetaDataInBuffers) { diff --git a/media/libstagefright/codecs/mp3dec/Android.mk b/media/libstagefright/codecs/mp3dec/Android.mk index 135c715..8284490 100644 --- a/media/libstagefright/codecs/mp3dec/Android.mk +++ b/media/libstagefright/codecs/mp3dec/Android.mk @@ -50,6 +50,8 @@ LOCAL_C_INCLUDES := \ LOCAL_CFLAGS := \ -DOSCL_UNUSED_ARG= +LOCAL_CFLAGS += -Werror + LOCAL_MODULE := libstagefright_mp3dec LOCAL_ARM_MODE := arm @@ -69,6 +71,8 @@ LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/src \ $(LOCAL_PATH)/include +LOCAL_CFLAGS += -Werror + LOCAL_SHARED_LIBRARIES := \ libstagefright libstagefright_omx libstagefright_foundation libutils liblog diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp index 61df65e..a09ab7c 100644 --- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp +++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp @@ -188,7 +188,7 @@ OMX_ERRORTYPE SoftMP3::internalSetParameter( } } -void SoftMP3::onQueueFilled(OMX_U32 portIndex) { +void SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError || mOutputPortSettingsChange != NONE) { return; } diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp index ee42dc5..499672b 100644 --- a/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp +++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp @@ -139,7 +139,7 @@ void pvmp3_mpeg2_get_scale_data(mp3SideInfo *si, int16 blocknumber = 0; granuleInfo *gr_info = &(si->ch[ch].gran[gr]); - uint32 scalefac_comp, int_scalefac_comp, new_slen[4]; + uint32 scalefac_comp, int_scalefac_comp, new_slen[4] = { 0,0,0,0 }; scalefac_comp = gr_info->scalefac_compress; diff --git a/media/libstagefright/codecs/on2/dec/Android.mk b/media/libstagefright/codecs/on2/dec/Android.mk index 7f2c46d..93ff64c 100644 --- a/media/libstagefright/codecs/on2/dec/Android.mk +++ b/media/libstagefright/codecs/on2/dec/Android.mk @@ -20,4 +20,6 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_MODULE := libstagefright_soft_vpxdec LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS += -Werror + include $(BUILD_SHARED_LIBRARY) diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp index 476e986..423a057 100644 --- a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp +++ b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp @@ -85,7 +85,7 @@ status_t SoftVPX::initDecoder() { return OK; } -void SoftVPX::onQueueFilled(OMX_U32 portIndex) { +void SoftVPX::onQueueFilled(OMX_U32 /* portIndex */) { if (mOutputPortSettingsChange != NONE) { return; } diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp index 7ddb13c..a7bde97 100644 --- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp +++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp @@ -98,7 +98,7 @@ status_t SoftAVC::initDecoder() { return UNKNOWN_ERROR; } -void SoftAVC::onQueueFilled(OMX_U32 portIndex) { +void SoftAVC::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError || mOutputPortSettingsChange != NONE) { return; } diff --git a/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c b/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c index 2bb4c4d..524a3f0 100644 --- a/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c +++ b/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c @@ -42,6 +42,8 @@ #include "h264bsd_decoder.h" #include "h264bsd_util.h" +#define UNUSED(x) (void)(x) + /*------------------------------------------------------------------------------ Version Information ------------------------------------------------------------------------------*/ @@ -73,6 +75,7 @@ H264DEC_EVALUATION Compile evaluation version, restricts number of frames #endif void H264SwDecTrace(char *string) { + UNUSED(string); } void* H264SwDecMalloc(u32 size) { diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.c index 493fb9e..7a262ed 100755 --- a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.c +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.c @@ -267,7 +267,7 @@ u32 ConcealMb(mbStorage_t *pMb, image_t *currImage, u32 row, u32 col, i32 firstPhase[16]; i32 *pTmp; /* neighbours above, below, left and right */ - i32 a[4], b[4], l[4], r[4]; + i32 a[4] = { 0,0,0,0 }, b[4], l[4] = { 0,0,0,0 }, r[4]; u32 A, B, L, R; #ifdef H264DEC_OMXDL u8 fillBuff[32*21 + 15 + 32]; diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.c index c948776..b409a06 100755 --- a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.c +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.c @@ -42,6 +42,8 @@ #include "armVC.h" #endif /* H264DEC_OMXDL */ +#define UNUSED(x) (void)(x) + /*------------------------------------------------------------------------------ 2. External compiler flags -------------------------------------------------------------------------------- @@ -2136,7 +2138,8 @@ static void FillRow1( i32 center, i32 right) { - + UNUSED(left); + UNUSED(right); ASSERT(ref); ASSERT(fill); diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.c index a7c6f64..23401c6 100755 --- a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.c +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.c @@ -47,6 +47,8 @@ #include "h264bsd_nal_unit.h" #include "h264bsd_dpb.h" +#define UNUSED(x) (void)(x) + /*------------------------------------------------------------------------------ 2. External compiler flags -------------------------------------------------------------------------------- @@ -1407,6 +1409,7 @@ u32 h264bsdCheckPriorPicsFlag(u32 * noOutputOfPriorPicsFlag, u32 tmp, value, i; i32 ivalue; strmData_t tmpStrmData[1]; + UNUSED(nalUnitType); /* Code */ diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.c index cc838fd..fb97a28 100755 --- a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.c +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.c @@ -186,7 +186,7 @@ u32 h264bsdMoreRbspData(strmData_t *pStrmData) return(HANTRO_FALSE); if ( (bits > 8) || - ((h264bsdShowBits32(pStrmData)>>(32-bits)) != (1 << (bits-1))) ) + ((h264bsdShowBits32(pStrmData)>>(32-bits)) != (1ul << (bits-1))) ) return(HANTRO_TRUE); else return(HANTRO_FALSE); diff --git a/media/libstagefright/codecs/raw/Android.mk b/media/libstagefright/codecs/raw/Android.mk index fe90a03..87080e7 100644 --- a/media/libstagefright/codecs/raw/Android.mk +++ b/media/libstagefright/codecs/raw/Android.mk @@ -8,6 +8,8 @@ LOCAL_C_INCLUDES := \ frameworks/av/media/libstagefright/include \ frameworks/native/include/media/openmax +LOCAL_CFLAGS += -Werror + LOCAL_SHARED_LIBRARIES := \ libstagefright_omx libstagefright_foundation libutils liblog diff --git a/media/libstagefright/codecs/raw/SoftRaw.cpp b/media/libstagefright/codecs/raw/SoftRaw.cpp index 19d6f13..9d514a6 100644 --- a/media/libstagefright/codecs/raw/SoftRaw.cpp +++ b/media/libstagefright/codecs/raw/SoftRaw.cpp @@ -163,7 +163,7 @@ OMX_ERRORTYPE SoftRaw::internalSetParameter( } } -void SoftRaw::onQueueFilled(OMX_U32 portIndex) { +void SoftRaw::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError) { return; } diff --git a/media/libstagefright/codecs/vorbis/dec/Android.mk b/media/libstagefright/codecs/vorbis/dec/Android.mk index 2232353..217a6d2 100644 --- a/media/libstagefright/codecs/vorbis/dec/Android.mk +++ b/media/libstagefright/codecs/vorbis/dec/Android.mk @@ -16,4 +16,6 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_MODULE := libstagefright_soft_vorbisdec LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS += -Werror + include $(BUILD_SHARED_LIBRARY) diff --git a/media/libstagefright/foundation/ANetworkSession.cpp b/media/libstagefright/foundation/ANetworkSession.cpp index e629588..08c4a87 100644 --- a/media/libstagefright/foundation/ANetworkSession.cpp +++ b/media/libstagefright/foundation/ANetworkSession.cpp @@ -521,7 +521,7 @@ status_t ANetworkSession::Session::readMore() { return err; } -void ANetworkSession::Session::dumpFragmentStats(const Fragment &frag) { +void ANetworkSession::Session::dumpFragmentStats(const Fragment & /* frag */) { #if 0 int64_t nowUs = ALooper::GetNowUs(); int64_t delayMs = (nowUs - frag.mTimeUs) / 1000ll; diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk index ad2dab5..90a6a23 100644 --- a/media/libstagefright/foundation/Android.mk +++ b/media/libstagefright/foundation/Android.mk @@ -24,7 +24,7 @@ LOCAL_SHARED_LIBRARIES := \ libutils \ liblog -LOCAL_CFLAGS += -Wno-multichar +LOCAL_CFLAGS += -Wno-multichar -Werror LOCAL_MODULE:= libstagefright_foundation diff --git a/media/libstagefright/foundation/base64.cpp b/media/libstagefright/foundation/base64.cpp index d5fb4e0..dcf5bef 100644 --- a/media/libstagefright/foundation/base64.cpp +++ b/media/libstagefright/foundation/base64.cpp @@ -33,6 +33,10 @@ sp<ABuffer> decodeBase64(const AString &s) { if (n >= 2 && s.c_str()[n - 2] == '=') { padding = 2; + + if (n >= 3 && s.c_str()[n - 3] == '=') { + padding = 3; + } } } @@ -71,7 +75,7 @@ sp<ABuffer> decodeBase64(const AString &s) { if (((i + 1) % 4) == 0) { out[j++] = (accum >> 16); - if (j < outLen) { out[j++] = (accum >> 8) & 0xff; } + if (j < outLen) { out[j++] = (accum >> 8) & 0xff; } if (j < outLen) { out[j++] = accum & 0xff; } accum = 0; diff --git a/media/libstagefright/http/Android.mk b/media/libstagefright/http/Android.mk index a6b481f..7f3307d 100644 --- a/media/libstagefright/http/Android.mk +++ b/media/libstagefright/http/Android.mk @@ -21,6 +21,8 @@ LOCAL_MODULE:= libstagefright_http_support LOCAL_CFLAGS += -Wno-multichar +LOCAL_CFLAGS += -Werror + include $(BUILD_SHARED_LIBRARY) endif diff --git a/media/libstagefright/httplive/Android.mk b/media/libstagefright/httplive/Android.mk index f3529f9..e8d558c 100644 --- a/media/libstagefright/httplive/Android.mk +++ b/media/libstagefright/httplive/Android.mk @@ -13,6 +13,8 @@ LOCAL_C_INCLUDES:= \ $(TOP)/frameworks/native/include/media/openmax \ $(TOP)/external/openssl/include +LOCAL_CFLAGS += -Werror + LOCAL_SHARED_LIBRARIES := \ libbinder \ libcrypto \ diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp index 149a817..bc26de1 100644 --- a/media/libstagefright/httplive/LiveSession.cpp +++ b/media/libstagefright/httplive/LiveSession.cpp @@ -61,14 +61,14 @@ LiveSession::LiveSession( mRealTimeBaseUs(0ll), mReconfigurationInProgress(false), mDisconnectReplyID(0) { - mPacketSources.add( - STREAMTYPE_AUDIO, new AnotherPacketSource(NULL /* meta */)); - mPacketSources.add( - STREAMTYPE_VIDEO, new AnotherPacketSource(NULL /* meta */)); + mStreams[kAudioIndex] = StreamItem("audio"); + mStreams[kVideoIndex] = StreamItem("video"); + mStreams[kSubtitleIndex] = StreamItem("subtitle"); - mPacketSources.add( - STREAMTYPE_SUBTITLES, new AnotherPacketSource(NULL /* meta */)); + for (size_t i = 0; i < kMaxStreams; ++i) { + mPacketSources.add(indexToType(i), new AnotherPacketSource(NULL /* meta */)); + } } LiveSession::~LiveSession() { @@ -369,6 +369,12 @@ int LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) return 1; } +// static +LiveSession::StreamType LiveSession::indexToType(int idx) { + CHECK(idx >= 0 && idx < kMaxStreams); + return (StreamType)(1 << idx); +} + void LiveSession::onConnect(const sp<AMessage> &msg) { AString url; CHECK(msg->findString("url", &url)); @@ -507,53 +513,81 @@ sp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) { return info.mFetcher; } +/* + * Illustration of parameters: + * + * 0 `range_offset` + * +------------+-------------------------------------------------------+--+--+ + * | | | next block to fetch | | | + * | | `source` handle => `out` buffer | | | | + * | `url` file |<--------- buffer size --------->|<--- `block_size` -->| | | + * | |<----------- `range_length` / buffer capacity ----------->| | + * |<------------------------------ file_size ------------------------------->| + * + * Special parameter values: + * - range_length == -1 means entire file + * - block_size == 0 means entire range + * + */ status_t LiveSession::fetchFile( const char *url, sp<ABuffer> *out, - int64_t range_offset, int64_t range_length) { - *out = NULL; + int64_t range_offset, int64_t range_length, + uint32_t block_size, /* download block size */ + sp<DataSource> *source, /* to return and reuse source */ + String8 *actualUrl) { + off64_t size; + sp<DataSource> temp_source; + if (source == NULL) { + source = &temp_source; + } - sp<DataSource> source; + if (*source == NULL) { + if (!strncasecmp(url, "file://", 7)) { + *source = new FileSource(url + 7); + } else if (strncasecmp(url, "http://", 7) + && strncasecmp(url, "https://", 8)) { + return ERROR_UNSUPPORTED; + } else { + KeyedVector<String8, String8> headers = mExtraHeaders; + if (range_offset > 0 || range_length >= 0) { + headers.add( + String8("Range"), + String8( + StringPrintf( + "bytes=%lld-%s", + range_offset, + range_length < 0 + ? "" : StringPrintf("%lld", + range_offset + range_length - 1).c_str()).c_str())); + } + status_t err = mHTTPDataSource->connect(url, &headers); - if (!strncasecmp(url, "file://", 7)) { - source = new FileSource(url + 7); - } else if (strncasecmp(url, "http://", 7) - && strncasecmp(url, "https://", 8)) { - return ERROR_UNSUPPORTED; - } else { - KeyedVector<String8, String8> headers = mExtraHeaders; - if (range_offset > 0 || range_length >= 0) { - headers.add( - String8("Range"), - String8( - StringPrintf( - "bytes=%lld-%s", - range_offset, - range_length < 0 - ? "" : StringPrintf("%lld", range_offset + range_length - 1).c_str()).c_str())); - } - status_t err = mHTTPDataSource->connect(url, &headers); + if (err != OK) { + return err; + } - if (err != OK) { - return err; + *source = mHTTPDataSource; } - - source = mHTTPDataSource; } - off64_t size; - status_t err = source->getSize(&size); - - if (err != OK) { + status_t getSizeErr = (*source)->getSize(&size); + if (getSizeErr != OK) { size = 65536; } - sp<ABuffer> buffer = new ABuffer(size); - buffer->setRange(0, 0); + sp<ABuffer> buffer = *out != NULL ? *out : new ABuffer(size); + if (*out == NULL) { + buffer->setRange(0, 0); + } + // adjust range_length if only reading partial block + if (block_size > 0 && (range_length == -1 || buffer->size() + block_size < range_length)) { + range_length = buffer->size() + block_size; + } for (;;) { + // Only resize when we don't know the size. size_t bufferRemaining = buffer->capacity() - buffer->size(); - - if (bufferRemaining == 0) { + if (bufferRemaining == 0 && getSizeErr != OK) { bufferRemaining = 32768; ALOGV("increasing download buffer to %d bytes", @@ -578,7 +612,9 @@ status_t LiveSession::fetchFile( } } - ssize_t n = source->readAt( + // The DataSource is responsible for informing us of error (n < 0) or eof (n == 0) + // to help us break out of the loop. + ssize_t n = (*source)->readAt( buffer->size(), buffer->data() + buffer->size(), maxBytesToRead); @@ -594,6 +630,12 @@ status_t LiveSession::fetchFile( } *out = buffer; + if (actualUrl != NULL) { + *actualUrl = (*source)->getUri(); + if (actualUrl->isEmpty()) { + *actualUrl = url; + } + } return OK; } @@ -605,7 +647,8 @@ sp<M3UParser> LiveSession::fetchPlaylist( *unchanged = false; sp<ABuffer> buffer; - status_t err = fetchFile(url, &buffer); + String8 actualUrl; + status_t err = fetchFile(url, &buffer, 0, -1, 0, NULL, &actualUrl); if (err != OK) { return NULL; @@ -636,7 +679,7 @@ sp<M3UParser> LiveSession::fetchPlaylist( #endif sp<M3UParser> playlist = - new M3UParser(url, buffer->data(), buffer->size()); + new M3UParser(actualUrl.string(), buffer->data(), buffer->size()); if (playlist->initCheck() != OK) { ALOGE("failed to parse .m3u8 playlist"); @@ -821,19 +864,11 @@ void LiveSession::changeConfiguration( uint32_t streamMask = 0; - AString audioURI; - if (mPlaylist->getAudioURI(item.mPlaylistIndex, &audioURI)) { - streamMask |= STREAMTYPE_AUDIO; - } - - AString videoURI; - if (mPlaylist->getVideoURI(item.mPlaylistIndex, &videoURI)) { - streamMask |= STREAMTYPE_VIDEO; - } - - AString subtitleURI; - if (mPlaylist->getSubtitleURI(item.mPlaylistIndex, &subtitleURI)) { - streamMask |= STREAMTYPE_SUBTITLES; + AString URIs[kMaxStreams]; + for (size_t i = 0; i < kMaxStreams; ++i) { + if (mPlaylist->getTypeURI(item.mPlaylistIndex, mStreams[i].mType, &URIs[i])) { + streamMask |= indexToType(i); + } } // Step 1, stop and discard fetchers that are no longer needed. @@ -845,10 +880,10 @@ void LiveSession::changeConfiguration( // If we're seeking all current fetchers are discarded. if (timeUs < 0ll) { - if (((streamMask & STREAMTYPE_AUDIO) && uri == audioURI) - || ((streamMask & STREAMTYPE_VIDEO) && uri == videoURI) - || ((streamMask & STREAMTYPE_SUBTITLES) && uri == subtitleURI)) { - discardFetcher = false; + for (size_t j = 0; j < kMaxStreams; ++j) { + if ((streamMask & indexToType(j)) && uri == URIs[j]) { + discardFetcher = false; + } } } @@ -862,14 +897,10 @@ void LiveSession::changeConfiguration( sp<AMessage> msg = new AMessage(kWhatChangeConfiguration2, id()); msg->setInt32("streamMask", streamMask); msg->setInt64("timeUs", timeUs); - if (streamMask & STREAMTYPE_AUDIO) { - msg->setString("audioURI", audioURI.c_str()); - } - if (streamMask & STREAMTYPE_VIDEO) { - msg->setString("videoURI", videoURI.c_str()); - } - if (streamMask & STREAMTYPE_SUBTITLES) { - msg->setString("subtitleURI", subtitleURI.c_str()); + for (size_t i = 0; i < kMaxStreams; ++i) { + if (streamMask & indexToType(i)) { + msg->setString(mStreams[i].uriKey().c_str(), URIs[i].c_str()); + } } // Every time a fetcher acknowledges the stopAsync or pauseAsync request @@ -900,18 +931,13 @@ void LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) { uint32_t streamMask; CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask)); - AString audioURI, videoURI, subtitleURI; - if (streamMask & STREAMTYPE_AUDIO) { - CHECK(msg->findString("audioURI", &audioURI)); - ALOGV("audioURI = '%s'", audioURI.c_str()); - } - if (streamMask & STREAMTYPE_VIDEO) { - CHECK(msg->findString("videoURI", &videoURI)); - ALOGV("videoURI = '%s'", videoURI.c_str()); - } - if (streamMask & STREAMTYPE_SUBTITLES) { - CHECK(msg->findString("subtitleURI", &subtitleURI)); - ALOGV("subtitleURI = '%s'", subtitleURI.c_str()); + AString URIs[kMaxStreams]; + for (size_t i = 0; i < kMaxStreams; ++i) { + if (streamMask & indexToType(i)) { + const AString &uriKey = mStreams[i].uriKey(); + CHECK(msg->findString(uriKey.c_str(), &URIs[i])); + ALOGV("%s = '%s'", uriKey.c_str(), URIs[i].c_str()); + } } // Determine which decoders to shutdown on the player side, @@ -921,15 +947,12 @@ void LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) { // 2) its streamtype was already active and still is but the URI // has changed. uint32_t changedMask = 0; - if (((mStreamMask & streamMask & STREAMTYPE_AUDIO) - && !(audioURI == mAudioURI)) - || (mStreamMask & ~streamMask & STREAMTYPE_AUDIO)) { - changedMask |= STREAMTYPE_AUDIO; - } - if (((mStreamMask & streamMask & STREAMTYPE_VIDEO) - && !(videoURI == mVideoURI)) - || (mStreamMask & ~streamMask & STREAMTYPE_VIDEO)) { - changedMask |= STREAMTYPE_VIDEO; + for (size_t i = 0; i < kMaxStreams && i != kSubtitleIndex; ++i) { + if (((mStreamMask & streamMask & indexToType(i)) + && !(URIs[i] == mStreams[i].mUri)) + || (mStreamMask & ~streamMask & indexToType(i))) { + changedMask |= indexToType(i); + } } if (changedMask == 0) { @@ -961,15 +984,10 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) { uint32_t streamMask; CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask)); - AString audioURI, videoURI, subtitleURI; - if (streamMask & STREAMTYPE_AUDIO) { - CHECK(msg->findString("audioURI", &audioURI)); - } - if (streamMask & STREAMTYPE_VIDEO) { - CHECK(msg->findString("videoURI", &videoURI)); - } - if (streamMask & STREAMTYPE_SUBTITLES) { - CHECK(msg->findString("subtitleURI", &subtitleURI)); + for (size_t i = 0; i < kMaxStreams; ++i) { + if (streamMask & indexToType(i)) { + CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mUri)); + } } int64_t timeUs; @@ -981,9 +999,6 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) { mRealTimeBaseUs = ALooper::GetNowUs() - timeUs; mStreamMask = streamMask; - mAudioURI = audioURI; - mVideoURI = videoURI; - mSubtitleURI = subtitleURI; // Resume all existing fetchers and assign them packet sources. for (size_t i = 0; i < mFetcherInfos.size(); ++i) { @@ -991,22 +1006,13 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) { uint32_t resumeMask = 0; - sp<AnotherPacketSource> audioSource; - if ((streamMask & STREAMTYPE_AUDIO) && uri == audioURI) { - audioSource = mPacketSources.valueFor(STREAMTYPE_AUDIO); - resumeMask |= STREAMTYPE_AUDIO; - } - - sp<AnotherPacketSource> videoSource; - if ((streamMask & STREAMTYPE_VIDEO) && uri == videoURI) { - videoSource = mPacketSources.valueFor(STREAMTYPE_VIDEO); - resumeMask |= STREAMTYPE_VIDEO; - } - - sp<AnotherPacketSource> subtitleSource; - if ((streamMask & STREAMTYPE_SUBTITLES) && uri == subtitleURI) { - subtitleSource = mPacketSources.valueFor(STREAMTYPE_SUBTITLES); - resumeMask |= STREAMTYPE_SUBTITLES; + sp<AnotherPacketSource> sources[kMaxStreams]; + // TRICKY: looping from i as earlier streams are already removed from streamMask + for (size_t j = i; j < kMaxStreams; ++j) { + if ((streamMask & indexToType(j)) && uri == mStreams[j].mUri) { + sources[j] = mPacketSources.valueFor(indexToType(j)); + resumeMask |= indexToType(j); + } } CHECK_NE(resumeMask, 0u); @@ -1016,7 +1022,7 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) { streamMask &= ~resumeMask; mFetcherInfos.valueAt(i).mFetcher->startAsync( - audioSource, videoSource, subtitleSource); + sources[kAudioIndex], sources[kVideoIndex], sources[kSubtitleIndex]); } // streamMask now only contains the types that need a new fetcher created. @@ -1025,52 +1031,33 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) { ALOGV("creating new fetchers for mask 0x%08x", streamMask); } - while (streamMask != 0) { - StreamType streamType = (StreamType)(streamMask & ~(streamMask - 1)); + for (size_t i = 0; i < kMaxStreams; i++) { + if (!(indexToType(i) & streamMask)) { + continue; + } AString uri; - switch (streamType) { - case STREAMTYPE_AUDIO: - uri = audioURI; - break; - case STREAMTYPE_VIDEO: - uri = videoURI; - break; - case STREAMTYPE_SUBTITLES: - uri = subtitleURI; - break; - default: - TRESPASS(); - } + uri = mStreams[i].mUri; sp<PlaylistFetcher> fetcher = addFetcher(uri.c_str()); CHECK(fetcher != NULL); - sp<AnotherPacketSource> audioSource; - if ((streamMask & STREAMTYPE_AUDIO) && uri == audioURI) { - audioSource = mPacketSources.valueFor(STREAMTYPE_AUDIO); - audioSource->clear(); + sp<AnotherPacketSource> sources[kMaxStreams]; + // TRICKY: looping from i as earlier streams are already removed from streamMask + for (size_t j = i; j < kMaxStreams; ++j) { + if ((streamMask & indexToType(j)) && uri == mStreams[j].mUri) { + sources[j] = mPacketSources.valueFor(indexToType(j)); + sources[j]->clear(); - streamMask &= ~STREAMTYPE_AUDIO; - } - - sp<AnotherPacketSource> videoSource; - if ((streamMask & STREAMTYPE_VIDEO) && uri == videoURI) { - videoSource = mPacketSources.valueFor(STREAMTYPE_VIDEO); - videoSource->clear(); - - streamMask &= ~STREAMTYPE_VIDEO; - } - - sp<AnotherPacketSource> subtitleSource; - if ((streamMask & STREAMTYPE_SUBTITLES) && uri == subtitleURI) { - subtitleSource = mPacketSources.valueFor(STREAMTYPE_SUBTITLES); - subtitleSource->clear(); - - streamMask &= ~STREAMTYPE_SUBTITLES; + streamMask &= ~indexToType(j); + } } - fetcher->startAsync(audioSource, videoSource, subtitleSource, timeUs); + fetcher->startAsync( + sources[kAudioIndex], + sources[kVideoIndex], + sources[kSubtitleIndex], + timeUs); } // All fetchers have now been started, the configuration change diff --git a/media/libstagefright/httplive/LiveSession.h b/media/libstagefright/httplive/LiveSession.h index ee10e70..c4d125c 100644 --- a/media/libstagefright/httplive/LiveSession.h +++ b/media/libstagefright/httplive/LiveSession.h @@ -44,10 +44,17 @@ struct LiveSession : public AHandler { uint32_t flags, const sp<IMediaHTTPService> &httpService); + enum StreamIndex { + kAudioIndex = 0, + kVideoIndex = 1, + kSubtitleIndex = 2, + kMaxStreams = 3, + }; + enum StreamType { - STREAMTYPE_AUDIO = 1, - STREAMTYPE_VIDEO = 2, - STREAMTYPE_SUBTITLES = 4, + STREAMTYPE_AUDIO = 1 << kAudioIndex, + STREAMTYPE_VIDEO = 1 << kVideoIndex, + STREAMTYPE_SUBTITLES = 1 << kSubtitleIndex, }; status_t dequeueAccessUnit(StreamType stream, sp<ABuffer> *accessUnit); @@ -107,6 +114,19 @@ private: bool mIsPrepared; }; + struct StreamItem { + const char *mType; + AString mUri; + StreamItem() : mType("") {} + StreamItem(const char *type) : mType(type) {} + AString uriKey() { + AString key(mType); + key.append("URI"); + return key; + } + }; + StreamItem mStreams[kMaxStreams]; + sp<AMessage> mNotify; uint32_t mFlags; sp<IMediaHTTPService> mHTTPService; @@ -124,7 +144,6 @@ private: sp<M3UParser> mPlaylist; KeyedVector<AString, FetcherInfo> mFetcherInfos; - AString mAudioURI, mVideoURI, mSubtitleURI; uint32_t mStreamMask; KeyedVector<StreamType, sp<AnotherPacketSource> > mPacketSources; @@ -146,9 +165,26 @@ private: status_t onSeek(const sp<AMessage> &msg); void onFinishDisconnect2(); + // If given a non-zero block_size (default 0), it is used to cap the number of + // bytes read in from the DataSource. If given a non-NULL buffer, new content + // is read into the end. + // + // The DataSource we read from is responsible for signaling error or EOF to help us + // break out of the read loop. The DataSource can be returned to the caller, so + // that the caller can reuse it for subsequent fetches (within the initially + // requested range). + // + // For reused HTTP sources, the caller must download a file sequentially without + // any overlaps or gaps to prevent reconnection. status_t fetchFile( const char *url, sp<ABuffer> *out, - int64_t range_offset = 0, int64_t range_length = -1); + /* request/open a file starting at range_offset for range_length bytes */ + int64_t range_offset = 0, int64_t range_length = -1, + /* download block size */ + uint32_t block_size = 0, + /* reuse DataSource if doing partial fetch */ + sp<DataSource> *source = NULL, + String8 *actualUrl = NULL); sp<M3UParser> fetchPlaylist( const char *url, uint8_t *curPlaylistHash, bool *unchanged); @@ -156,6 +192,7 @@ private: size_t getBandwidthIndex(); static int SortByBandwidth(const BandwidthItem *, const BandwidthItem *); + static StreamType indexToType(int idx); void changeConfiguration( int64_t timeUs, size_t bandwidthIndex, bool pickTrack = false); diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp index 5ef7c0f..4dc5db0 100644 --- a/media/libstagefright/httplive/M3UParser.cpp +++ b/media/libstagefright/httplive/M3UParser.cpp @@ -125,7 +125,7 @@ void M3UParser::MediaGroup::pickRandomMediaItems() { mSelectedIndex = strtoul(value, &end, 10); CHECK(end > value && *end == '\0'); - if (mSelectedIndex >= mMediaItems.size()) { + if (mSelectedIndex >= (ssize_t)mMediaItems.size()) { mSelectedIndex = mMediaItems.size() - 1; } } else { @@ -165,14 +165,14 @@ status_t M3UParser::MediaGroup::selectTrack(size_t index, bool select) { ALOGE("track %d does not exist", index); return INVALID_OPERATION; } - if (mSelectedIndex == index) { + if (mSelectedIndex == (ssize_t)index) { ALOGE("track %d already selected", index); return BAD_VALUE; } ALOGV("selected track %d", index); mSelectedIndex = index; } else { - if (mSelectedIndex != index) { + if (mSelectedIndex != (ssize_t)index) { ALOGE("track %d is not selected", index); return BAD_VALUE; } @@ -369,18 +369,6 @@ bool M3UParser::getTypeURI(size_t index, const char *key, AString *uri) const { return true; } -bool M3UParser::getAudioURI(size_t index, AString *uri) const { - return getTypeURI(index, "audio", uri); -} - -bool M3UParser::getVideoURI(size_t index, AString *uri) const { - return getTypeURI(index, "video", uri); -} - -bool M3UParser::getSubtitleURI(size_t index, AString *uri) const { - return getTypeURI(index, "subtitles", uri); -} - static bool MakeURL(const char *baseURL, const char *url, AString *out) { out->clear(); diff --git a/media/libstagefright/httplive/M3UParser.h b/media/libstagefright/httplive/M3UParser.h index 5248004..2051e41 100644 --- a/media/libstagefright/httplive/M3UParser.h +++ b/media/libstagefright/httplive/M3UParser.h @@ -45,9 +45,7 @@ struct M3UParser : public RefBase { status_t getTrackInfo(Parcel* reply) const; ssize_t getSelectedIndex() const; - bool getAudioURI(size_t index, AString *uri) const; - bool getVideoURI(size_t index, AString *uri) const; - bool getSubtitleURI(size_t index, AString *uri) const; + bool getTypeURI(size_t index, const char *key, AString *uri) const; protected: virtual ~M3UParser(); @@ -95,8 +93,6 @@ private: status_t parseMedia(const AString &line); - bool getTypeURI(size_t index, const char *key, AString *uri) const; - static status_t ParseInt32(const char *s, int32_t *x); static status_t ParseDouble(const char *s, double *x); diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp index f095987..030cbde 100644 --- a/media/libstagefright/httplive/PlaylistFetcher.cpp +++ b/media/libstagefright/httplive/PlaylistFetcher.cpp @@ -170,7 +170,8 @@ int64_t PlaylistFetcher::delayUsToRefreshPlaylist() const { } status_t PlaylistFetcher::decryptBuffer( - size_t playlistIndex, const sp<ABuffer> &buffer) { + size_t playlistIndex, const sp<ABuffer> &buffer, + bool first) { sp<AMessage> itemMeta; bool found = false; AString method; @@ -188,6 +189,7 @@ status_t PlaylistFetcher::decryptBuffer( if (!found) { method = "NONE"; } + buffer->meta()->setString("cipher-method", method.c_str()); if (method == "NONE") { return OK; @@ -227,59 +229,77 @@ status_t PlaylistFetcher::decryptBuffer( return UNKNOWN_ERROR; } - unsigned char aes_ivec[16]; + size_t n = buffer->size(); + if (!n) { + return OK; + } + CHECK(n % 16 == 0); - AString iv; - if (itemMeta->findString("cipher-iv", &iv)) { - if ((!iv.startsWith("0x") && !iv.startsWith("0X")) - || iv.size() != 16 * 2 + 2) { - ALOGE("malformed cipher IV '%s'.", iv.c_str()); - return ERROR_MALFORMED; - } + if (first) { + // If decrypting the first block in a file, read the iv from the manifest + // or derive the iv from the file's sequence number. - memset(aes_ivec, 0, sizeof(aes_ivec)); - for (size_t i = 0; i < 16; ++i) { - char c1 = tolower(iv.c_str()[2 + 2 * i]); - char c2 = tolower(iv.c_str()[3 + 2 * i]); - if (!isxdigit(c1) || !isxdigit(c2)) { + AString iv; + if (itemMeta->findString("cipher-iv", &iv)) { + if ((!iv.startsWith("0x") && !iv.startsWith("0X")) + || iv.size() != 16 * 2 + 2) { ALOGE("malformed cipher IV '%s'.", iv.c_str()); return ERROR_MALFORMED; } - uint8_t nibble1 = isdigit(c1) ? c1 - '0' : c1 - 'a' + 10; - uint8_t nibble2 = isdigit(c2) ? c2 - '0' : c2 - 'a' + 10; - aes_ivec[i] = nibble1 << 4 | nibble2; + memset(mAESInitVec, 0, sizeof(mAESInitVec)); + for (size_t i = 0; i < 16; ++i) { + char c1 = tolower(iv.c_str()[2 + 2 * i]); + char c2 = tolower(iv.c_str()[3 + 2 * i]); + if (!isxdigit(c1) || !isxdigit(c2)) { + ALOGE("malformed cipher IV '%s'.", iv.c_str()); + return ERROR_MALFORMED; + } + uint8_t nibble1 = isdigit(c1) ? c1 - '0' : c1 - 'a' + 10; + uint8_t nibble2 = isdigit(c2) ? c2 - '0' : c2 - 'a' + 10; + + mAESInitVec[i] = nibble1 << 4 | nibble2; + } + } else { + memset(mAESInitVec, 0, sizeof(mAESInitVec)); + mAESInitVec[15] = mSeqNumber & 0xff; + mAESInitVec[14] = (mSeqNumber >> 8) & 0xff; + mAESInitVec[13] = (mSeqNumber >> 16) & 0xff; + mAESInitVec[12] = (mSeqNumber >> 24) & 0xff; } - } else { - memset(aes_ivec, 0, sizeof(aes_ivec)); - aes_ivec[15] = mSeqNumber & 0xff; - aes_ivec[14] = (mSeqNumber >> 8) & 0xff; - aes_ivec[13] = (mSeqNumber >> 16) & 0xff; - aes_ivec[12] = (mSeqNumber >> 24) & 0xff; } AES_cbc_encrypt( buffer->data(), buffer->data(), buffer->size(), - &aes_key, aes_ivec, AES_DECRYPT); - - // hexdump(buffer->data(), buffer->size()); + &aes_key, mAESInitVec, AES_DECRYPT); - size_t n = buffer->size(); - CHECK_GT(n, 0u); + return OK; +} - size_t pad = buffer->data()[n - 1]; +status_t PlaylistFetcher::checkDecryptPadding(const sp<ABuffer> &buffer) { + status_t err; + AString method; + CHECK(buffer->meta()->findString("cipher-method", &method)); + if (method == "NONE") { + return OK; + } - CHECK_GT(pad, 0u); - CHECK_LE(pad, 16u); - CHECK_GE((size_t)n, pad); - for (size_t i = 0; i < pad; ++i) { - CHECK_EQ((unsigned)buffer->data()[n - 1 - i], pad); + uint8_t padding = 0; + if (buffer->size() > 0) { + padding = buffer->data()[buffer->size() - 1]; } - n -= pad; + if (padding > 16) { + return ERROR_MALFORMED; + } - buffer->setRange(buffer->offset(), n); + for (size_t i = buffer->size() - padding; i < padding; i++) { + if (buffer->data()[i] != padding) { + return ERROR_MALFORMED; + } + } + buffer->setRange(buffer->offset(), buffer->size() - padding); return OK; } @@ -602,7 +622,7 @@ void PlaylistFetcher::onDownloadNext() { if (mPlaylist->isComplete() || mPlaylist->isEvent()) { mSeqNumber = getSeqNumberForTime(mStartTimeUs); - ALOGV("Initial sequence number for time %lld is %ld from (%ld .. %ld)", + ALOGV("Initial sequence number for time %lld is %d from (%d .. %d)", mStartTimeUs, mSeqNumber, firstSeqNumberInPlaylist, lastSeqNumberInPlaylist); } else { @@ -611,7 +631,7 @@ void PlaylistFetcher::onDownloadNext() { if (mSeqNumber < firstSeqNumberInPlaylist) { mSeqNumber = firstSeqNumberInPlaylist; } - ALOGV("Initial sequence number for live event %ld from (%ld .. %ld)", + ALOGV("Initial sequence number for live event %d from (%d .. %d)", mSeqNumber, firstSeqNumberInPlaylist, lastSeqNumberInPlaylist); } @@ -635,7 +655,8 @@ void PlaylistFetcher::onDownloadNext() { if (delayUs > kMaxMonitorDelayUs) { delayUs = kMaxMonitorDelayUs; } - ALOGV("sequence number high: %ld from (%ld .. %ld), monitor in %lld (retry=%d)", + ALOGV("sequence number high: %d from (%d .. %d), " + "monitor in %lld (retry=%d)", mSeqNumber, firstSeqNumberInPlaylist, lastSeqNumberInPlaylist, delayUs, mNumRetries); postMonitorQueue(delayUs); @@ -706,6 +727,9 @@ void PlaylistFetcher::onDownloadNext() { CHECK(buffer != NULL); err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, buffer); + if (err == OK) { + err = checkDecryptPadding(buffer); + } if (err != OK) { ALOGE("decryptBuffer failed w/ error %d", err); diff --git a/media/libstagefright/httplive/PlaylistFetcher.h b/media/libstagefright/httplive/PlaylistFetcher.h index 78dea20..ac04a77 100644 --- a/media/libstagefright/httplive/PlaylistFetcher.h +++ b/media/libstagefright/httplive/PlaylistFetcher.h @@ -119,8 +119,23 @@ private: uint64_t mFirstPTS; int64_t mAbsoluteTimeAnchorUs; + // Stores the initialization vector to decrypt the next block of cipher text, which can + // either be derived from the sequence number, read from the manifest, or copied from + // the last block of cipher text (cipher-block chaining). + unsigned char mAESInitVec[16]; + + // Set first to true if decrypting the first segment of a playlist segment. When + // first is true, reset the initialization vector based on the available + // information in the manifest; otherwise, use the initialization vector as + // updated by the last call to AES_cbc_encrypt. + // + // For the input to decrypt correctly, decryptBuffer must be called on + // consecutive byte ranges on block boundaries, e.g. 0..15, 16..47, 48..63, + // and so on. status_t decryptBuffer( - size_t playlistIndex, const sp<ABuffer> &buffer); + size_t playlistIndex, const sp<ABuffer> &buffer, + bool first = true); + status_t checkDecryptPadding(const sp<ABuffer> &buffer); void postMonitorQueue(int64_t delayUs = 0, int64_t minDelayUs = 0); void cancelMonitorQueue(); diff --git a/media/libstagefright/id3/Android.mk b/media/libstagefright/id3/Android.mk index bf6f7bb..2194c38 100644 --- a/media/libstagefright/id3/Android.mk +++ b/media/libstagefright/id3/Android.mk @@ -4,6 +4,8 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := \ ID3.cpp +LOCAL_CFLAGS += -Werror + LOCAL_MODULE := libstagefright_id3 include $(BUILD_STATIC_LIBRARY) @@ -15,6 +17,8 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := \ testid3.cpp +LOCAL_CFLAGS += -Werror + LOCAL_SHARED_LIBRARIES := \ libstagefright libutils liblog libbinder libstagefright_foundation diff --git a/media/libstagefright/include/FragmentedMP4Parser.h b/media/libstagefright/include/FragmentedMP4Parser.h deleted file mode 100644 index dbe02b8..0000000 --- a/media/libstagefright/include/FragmentedMP4Parser.h +++ /dev/null @@ -1,274 +0,0 @@ -/* - * 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. - */ - -#ifndef PARSER_H_ - -#define PARSER_H_ - -#include <media/stagefright/foundation/AHandler.h> -#include <media/stagefright/DataSource.h> -#include <utils/Vector.h> - -namespace android { - -struct ABuffer; - -struct FragmentedMP4Parser : public AHandler { - struct Source : public RefBase { - Source() {} - - virtual ssize_t readAt(off64_t offset, void *data, size_t size) = 0; - virtual bool isSeekable() = 0; - - protected: - virtual ~Source() {} - - private: - DISALLOW_EVIL_CONSTRUCTORS(Source); - }; - - FragmentedMP4Parser(); - - void start(const char *filename); - void start(const sp<Source> &source); - void start(sp<DataSource> &source); - - sp<AMessage> getFormat(bool audio, bool synchronous = false); - status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit, bool synchronous = false); - status_t seekTo(bool audio, int64_t timeUs); - bool isSeekable() const; - - virtual void onMessageReceived(const sp<AMessage> &msg); - -protected: - virtual ~FragmentedMP4Parser(); - -private: - enum { - kWhatStart, - kWhatProceed, - kWhatReadMore, - kWhatGetFormat, - kWhatDequeueAccessUnit, - kWhatSeekTo, - }; - - struct TrackFragment; - struct DynamicTrackFragment; - struct StaticTrackFragment; - - struct DispatchEntry { - uint32_t mType; - uint32_t mParentType; - status_t (FragmentedMP4Parser::*mHandler)(uint32_t, size_t, uint64_t); - }; - - struct Container { - uint64_t mOffset; - uint64_t mBytesRemaining; - uint32_t mType; - bool mExtendsToEOF; - }; - - struct SampleDescription { - uint32_t mType; - uint16_t mDataRefIndex; - - sp<AMessage> mFormat; - }; - - struct SampleInfo { - off64_t mOffset; - size_t mSize; - uint32_t mPresentationTime; - size_t mSampleDescIndex; - uint32_t mFlags; - }; - - struct MediaDataInfo { - sp<ABuffer> mBuffer; - off64_t mOffset; - }; - - struct SidxEntry { - size_t mSize; - uint32_t mDurationUs; - }; - - struct TrackInfo { - enum Flags { - kTrackEnabled = 0x01, - kTrackInMovie = 0x02, - kTrackInPreview = 0x04, - }; - - uint32_t mTrackID; - uint32_t mFlags; - uint32_t mDuration; // This is the duration in terms of movie timescale! - uint64_t mSidxDuration; // usec, from sidx box, which can use a different timescale - - uint32_t mMediaTimeScale; - - uint32_t mMediaHandlerType; - Vector<SampleDescription> mSampleDescs; - - // from track extends: - uint32_t mDefaultSampleDescriptionIndex; - uint32_t mDefaultSampleDuration; - uint32_t mDefaultSampleSize; - uint32_t mDefaultSampleFlags; - - uint32_t mDecodingTime; - - Vector<SidxEntry> mSidx; - sp<StaticTrackFragment> mStaticFragment; - List<sp<TrackFragment> > mFragments; - }; - - struct TrackFragmentHeaderInfo { - enum Flags { - kBaseDataOffsetPresent = 0x01, - kSampleDescriptionIndexPresent = 0x02, - kDefaultSampleDurationPresent = 0x08, - kDefaultSampleSizePresent = 0x10, - kDefaultSampleFlagsPresent = 0x20, - kDurationIsEmpty = 0x10000, - }; - - uint32_t mTrackID; - uint32_t mFlags; - uint64_t mBaseDataOffset; - uint32_t mSampleDescriptionIndex; - uint32_t mDefaultSampleDuration; - uint32_t mDefaultSampleSize; - uint32_t mDefaultSampleFlags; - - uint64_t mDataOffset; - }; - - static const DispatchEntry kDispatchTable[]; - - sp<Source> mSource; - off_t mBufferPos; - bool mSuspended; - bool mDoneWithMoov; - off_t mFirstMoofOffset; // used as the starting point for offsets calculated from the sidx box - sp<ABuffer> mBuffer; - Vector<Container> mStack; - KeyedVector<uint32_t, TrackInfo> mTracks; // TrackInfo by trackID - Vector<MediaDataInfo> mMediaData; - - uint32_t mCurrentTrackID; - - status_t mFinalResult; - - TrackFragmentHeaderInfo mTrackFragmentHeaderInfo; - - status_t onProceed(); - status_t onDequeueAccessUnit(size_t trackIndex, sp<ABuffer> *accessUnit); - status_t onSeekTo(bool wantAudio, int64_t position); - - void enter(off64_t offset, uint32_t type, uint64_t size); - - uint16_t readU16(size_t offset); - uint32_t readU32(size_t offset); - uint64_t readU64(size_t offset); - void skip(off_t distance); - status_t need(size_t size); - bool fitsContainer(uint64_t size) const; - - status_t parseTrackHeader( - uint32_t type, size_t offset, uint64_t size); - - status_t parseMediaHeader( - uint32_t type, size_t offset, uint64_t size); - - status_t parseMediaHandler( - uint32_t type, size_t offset, uint64_t size); - - status_t parseTrackExtends( - uint32_t type, size_t offset, uint64_t size); - - status_t parseTrackFragmentHeader( - uint32_t type, size_t offset, uint64_t size); - - status_t parseTrackFragmentRun( - uint32_t type, size_t offset, uint64_t size); - - status_t parseVisualSampleEntry( - uint32_t type, size_t offset, uint64_t size); - - status_t parseAudioSampleEntry( - uint32_t type, size_t offset, uint64_t size); - - status_t parseSampleSizes( - uint32_t type, size_t offset, uint64_t size); - - status_t parseCompactSampleSizes( - uint32_t type, size_t offset, uint64_t size); - - status_t parseSampleToChunk( - uint32_t type, size_t offset, uint64_t size); - - status_t parseChunkOffsets( - uint32_t type, size_t offset, uint64_t size); - - status_t parseChunkOffsets64( - uint32_t type, size_t offset, uint64_t size); - - status_t parseAVCCodecSpecificData( - uint32_t type, size_t offset, uint64_t size); - - status_t parseESDSCodecSpecificData( - uint32_t type, size_t offset, uint64_t size); - - status_t parseMediaData( - uint32_t type, size_t offset, uint64_t size); - - status_t parseSegmentIndex( - uint32_t type, size_t offset, uint64_t size); - - TrackInfo *editTrack(uint32_t trackID, bool createIfNecessary = false); - - ssize_t findTrack(bool wantAudio) const; - - status_t makeAccessUnit( - TrackInfo *info, - const SampleInfo &sample, - const MediaDataInfo &mdatInfo, - sp<ABuffer> *accessUnit); - - status_t getSample( - TrackInfo *info, - sp<TrackFragment> *fragment, - SampleInfo *sampleInfo); - - static int CompareSampleLocation( - const SampleInfo &sample, const MediaDataInfo &mdatInfo); - - void resumeIfNecessary(); - - void copyBuffer( - sp<ABuffer> *dst, - size_t offset, uint64_t size) const; - - DISALLOW_EVIL_CONSTRUCTORS(FragmentedMP4Parser); -}; - -} // namespace android - -#endif // PARSER_H_ - diff --git a/media/libstagefright/include/TimedEventQueue.h b/media/libstagefright/include/TimedEventQueue.h index 3e84256..2963150 100644 --- a/media/libstagefright/include/TimedEventQueue.h +++ b/media/libstagefright/include/TimedEventQueue.h @@ -122,7 +122,7 @@ private: }; struct StopEvent : public TimedEventQueue::Event { - virtual void fire(TimedEventQueue *queue, int64_t now_us) { + virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) { queue->mStopped = true; } }; diff --git a/media/libstagefright/matroska/Android.mk b/media/libstagefright/matroska/Android.mk index 2d8c1e1..446ff8c 100644 --- a/media/libstagefright/matroska/Android.mk +++ b/media/libstagefright/matroska/Android.mk @@ -8,7 +8,7 @@ LOCAL_C_INCLUDES:= \ $(TOP)/external/libvpx/libwebm \ $(TOP)/frameworks/native/include/media/openmax \ -LOCAL_CFLAGS += -Wno-multichar +LOCAL_CFLAGS += -Wno-multichar -Werror LOCAL_MODULE:= libstagefright_matroska diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp index dcb1cda..6f69d0b 100644 --- a/media/libstagefright/matroska/MatroskaExtractor.cpp +++ b/media/libstagefright/matroska/MatroskaExtractor.cpp @@ -193,7 +193,7 @@ MatroskaSource::~MatroskaSource() { clearPendingFrames(); } -status_t MatroskaSource::start(MetaData *params) { +status_t MatroskaSource::start(MetaData * /* params */) { mBlockIter.reset(); return OK; @@ -410,7 +410,7 @@ void BlockIterator::seek( // Accept the first key frame *actualFrameTimeUs = (block()->GetTime(mCluster) + 500LL) / 1000LL; ALOGV("Requested seek point: %lld actual: %lld", - seekTimeUs, actualFrameTimeUs); + seekTimeUs, *actualFrameTimeUs); break; } } diff --git a/media/libstagefright/mp4/FragmentedMP4Parser.cpp b/media/libstagefright/mp4/FragmentedMP4Parser.cpp deleted file mode 100644 index 0102656..0000000 --- a/media/libstagefright/mp4/FragmentedMP4Parser.cpp +++ /dev/null @@ -1,1993 +0,0 @@ -/* - * 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 "FragmentedMP4Parser" -#include <utils/Log.h> - -#include "include/avc_utils.h" -#include "include/ESDS.h" -#include "include/FragmentedMP4Parser.h" -#include "TrackFragment.h" - - -#include <media/stagefright/foundation/ABuffer.h> -#include <media/stagefright/foundation/ADebug.h> -#include <media/stagefright/foundation/AMessage.h> -#include <media/stagefright/foundation/hexdump.h> -#include <media/stagefright/MediaDefs.h> -#include <media/stagefright/MediaErrors.h> -#include <media/stagefright/Utils.h> - - -namespace android { - -static const char *Fourcc2String(uint32_t fourcc) { - static char buffer[5]; - buffer[4] = '\0'; - buffer[0] = fourcc >> 24; - buffer[1] = (fourcc >> 16) & 0xff; - buffer[2] = (fourcc >> 8) & 0xff; - buffer[3] = fourcc & 0xff; - - return buffer; -} - -static const char *IndentString(size_t n) { - static const char kSpace[] = " "; - return kSpace + sizeof(kSpace) - 2 * n - 1; -} - -// static -const FragmentedMP4Parser::DispatchEntry FragmentedMP4Parser::kDispatchTable[] = { - { FOURCC('m', 'o', 'o', 'v'), 0, NULL }, - { FOURCC('t', 'r', 'a', 'k'), FOURCC('m', 'o', 'o', 'v'), NULL }, - { FOURCC('u', 'd', 't', 'a'), FOURCC('t', 'r', 'a', 'k'), NULL }, - { FOURCC('u', 'd', 't', 'a'), FOURCC('m', 'o', 'o', 'v'), NULL }, - { FOURCC('m', 'e', 't', 'a'), FOURCC('u', 'd', 't', 'a'), NULL }, - { FOURCC('i', 'l', 's', 't'), FOURCC('m', 'e', 't', 'a'), NULL }, - - { FOURCC('t', 'k', 'h', 'd'), FOURCC('t', 'r', 'a', 'k'), - &FragmentedMP4Parser::parseTrackHeader - }, - - { FOURCC('m', 'v', 'e', 'x'), FOURCC('m', 'o', 'o', 'v'), NULL }, - - { FOURCC('t', 'r', 'e', 'x'), FOURCC('m', 'v', 'e', 'x'), - &FragmentedMP4Parser::parseTrackExtends - }, - - { FOURCC('e', 'd', 't', 's'), FOURCC('t', 'r', 'a', 'k'), NULL }, - { FOURCC('m', 'd', 'i', 'a'), FOURCC('t', 'r', 'a', 'k'), NULL }, - - { FOURCC('m', 'd', 'h', 'd'), FOURCC('m', 'd', 'i', 'a'), - &FragmentedMP4Parser::parseMediaHeader - }, - - { FOURCC('h', 'd', 'l', 'r'), FOURCC('m', 'd', 'i', 'a'), - &FragmentedMP4Parser::parseMediaHandler - }, - - { FOURCC('m', 'i', 'n', 'f'), FOURCC('m', 'd', 'i', 'a'), NULL }, - { FOURCC('d', 'i', 'n', 'f'), FOURCC('m', 'i', 'n', 'f'), NULL }, - { FOURCC('s', 't', 'b', 'l'), FOURCC('m', 'i', 'n', 'f'), NULL }, - { FOURCC('s', 't', 's', 'd'), FOURCC('s', 't', 'b', 'l'), NULL }, - - { FOURCC('s', 't', 's', 'z'), FOURCC('s', 't', 'b', 'l'), - &FragmentedMP4Parser::parseSampleSizes }, - - { FOURCC('s', 't', 'z', '2'), FOURCC('s', 't', 'b', 'l'), - &FragmentedMP4Parser::parseCompactSampleSizes }, - - { FOURCC('s', 't', 's', 'c'), FOURCC('s', 't', 'b', 'l'), - &FragmentedMP4Parser::parseSampleToChunk }, - - { FOURCC('s', 't', 'c', 'o'), FOURCC('s', 't', 'b', 'l'), - &FragmentedMP4Parser::parseChunkOffsets }, - - { FOURCC('c', 'o', '6', '4'), FOURCC('s', 't', 'b', 'l'), - &FragmentedMP4Parser::parseChunkOffsets64 }, - - { FOURCC('a', 'v', 'c', 'C'), FOURCC('a', 'v', 'c', '1'), - &FragmentedMP4Parser::parseAVCCodecSpecificData }, - - { FOURCC('e', 's', 'd', 's'), FOURCC('m', 'p', '4', 'a'), - &FragmentedMP4Parser::parseESDSCodecSpecificData }, - - { FOURCC('e', 's', 'd', 's'), FOURCC('m', 'p', '4', 'v'), - &FragmentedMP4Parser::parseESDSCodecSpecificData }, - - { FOURCC('m', 'd', 'a', 't'), 0, &FragmentedMP4Parser::parseMediaData }, - - { FOURCC('m', 'o', 'o', 'f'), 0, NULL }, - { FOURCC('t', 'r', 'a', 'f'), FOURCC('m', 'o', 'o', 'f'), NULL }, - - { FOURCC('t', 'f', 'h', 'd'), FOURCC('t', 'r', 'a', 'f'), - &FragmentedMP4Parser::parseTrackFragmentHeader - }, - { FOURCC('t', 'r', 'u', 'n'), FOURCC('t', 'r', 'a', 'f'), - &FragmentedMP4Parser::parseTrackFragmentRun - }, - - { FOURCC('m', 'f', 'r', 'a'), 0, NULL }, - - { FOURCC('s', 'i', 'd', 'x'), 0, &FragmentedMP4Parser::parseSegmentIndex }, -}; - -struct FileSource : public FragmentedMP4Parser::Source { - FileSource(const char *filename) - : mFile(fopen(filename, "rb")) { - CHECK(mFile != NULL); - } - - virtual ~FileSource() { - fclose(mFile); - } - - virtual ssize_t readAt(off64_t offset, void *data, size_t size) { - fseek(mFile, offset, SEEK_SET); - return fread(data, 1, size, mFile); - } - - virtual bool isSeekable() { - return true; - } - - private: - FILE *mFile; - - DISALLOW_EVIL_CONSTRUCTORS(FileSource); -}; - -struct ReadTracker : public RefBase { - ReadTracker(off64_t size) { - allocSize = 1 + size / 8192; // 1 bit per kilobyte - bitmap = (char*) calloc(1, allocSize); - } - virtual ~ReadTracker() { - dumpToLog(); - free(bitmap); - } - void mark(off64_t offset, size_t size) { - int firstbit = offset / 1024; - int lastbit = (offset + size - 1) / 1024; - for (int i = firstbit; i <= lastbit; i++) { - bitmap[i/8] |= (0x80 >> (i & 7)); - } - } - - private: - void dumpToLog() { - // 96 chars per line, each char represents one kilobyte, 1 kb per bit - int numlines = allocSize / 12; - char buf[97]; - char *cur = bitmap; - for (int i = 0; i < numlines; i++ && cur) { - for (int j = 0; j < 12; j++) { - for (int k = 0; k < 8; k++) { - buf[(j * 8) + k] = (*cur & (0x80 >> k)) ? 'X' : '.'; - } - cur++; - } - buf[96] = '\0'; - ALOGI("%5dk: %s", i * 96, buf); - } - } - - size_t allocSize; - char *bitmap; -}; - -struct DataSourceSource : public FragmentedMP4Parser::Source { - DataSourceSource(sp<DataSource> &source) - : mDataSource(source) { - CHECK(mDataSource != NULL); -#if 0 - off64_t size; - if (source->getSize(&size) == OK) { - mReadTracker = new ReadTracker(size); - } else { - ALOGE("couldn't get data source size"); - } -#endif - } - - virtual ssize_t readAt(off64_t offset, void *data, size_t size) { - if (mReadTracker != NULL) { - mReadTracker->mark(offset, size); - } - return mDataSource->readAt(offset, data, size); - } - - virtual bool isSeekable() { - return true; - } - - private: - sp<DataSource> mDataSource; - sp<ReadTracker> mReadTracker; - - DISALLOW_EVIL_CONSTRUCTORS(DataSourceSource); -}; - -FragmentedMP4Parser::FragmentedMP4Parser() - : mBufferPos(0), - mSuspended(false), - mDoneWithMoov(false), - mFirstMoofOffset(0), - mFinalResult(OK) { -} - -FragmentedMP4Parser::~FragmentedMP4Parser() { -} - -void FragmentedMP4Parser::start(const char *filename) { - sp<AMessage> msg = new AMessage(kWhatStart, id()); - msg->setObject("source", new FileSource(filename)); - msg->post(); - ALOGV("Parser::start(%s)", filename); -} - -void FragmentedMP4Parser::start(const sp<Source> &source) { - sp<AMessage> msg = new AMessage(kWhatStart, id()); - msg->setObject("source", source); - msg->post(); - ALOGV("Parser::start(Source)"); -} - -void FragmentedMP4Parser::start(sp<DataSource> &source) { - sp<AMessage> msg = new AMessage(kWhatStart, id()); - msg->setObject("source", new DataSourceSource(source)); - msg->post(); - ALOGV("Parser::start(DataSource)"); -} - -sp<AMessage> FragmentedMP4Parser::getFormat(bool audio, bool synchronous) { - - while (true) { - bool moovDone = mDoneWithMoov; - sp<AMessage> msg = new AMessage(kWhatGetFormat, id()); - msg->setInt32("audio", audio); - - sp<AMessage> response; - status_t err = msg->postAndAwaitResponse(&response); - - if (err != OK) { - ALOGV("getFormat post failed: %d", err); - return NULL; - } - - if (response->findInt32("err", &err) && err != OK) { - if (synchronous && err == -EWOULDBLOCK && !moovDone) { - resumeIfNecessary(); - ALOGV("@getFormat parser not ready yet, retrying"); - usleep(10000); - continue; - } - ALOGV("getFormat failed: %d", err); - return NULL; - } - - sp<AMessage> format; - CHECK(response->findMessage("format", &format)); - - ALOGV("returning format %s", format->debugString().c_str()); - return format; - } -} - -status_t FragmentedMP4Parser::seekTo(bool wantAudio, int64_t timeUs) { - sp<AMessage> msg = new AMessage(kWhatSeekTo, id()); - msg->setInt32("audio", wantAudio); - msg->setInt64("position", timeUs); - - sp<AMessage> response; - status_t err = msg->postAndAwaitResponse(&response); - return err; -} - -bool FragmentedMP4Parser::isSeekable() const { - while (mFirstMoofOffset == 0 && mFinalResult == OK) { - usleep(10000); - } - bool seekable = mSource->isSeekable(); - for (size_t i = 0; seekable && i < mTracks.size(); i++) { - const TrackInfo *info = &mTracks.valueAt(i); - seekable &= !info->mSidx.empty(); - } - return seekable; -} - -status_t FragmentedMP4Parser::onSeekTo(bool wantAudio, int64_t position) { - status_t err = -EINVAL; - ssize_t trackIndex = findTrack(wantAudio); - if (trackIndex < 0) { - err = trackIndex; - } else { - TrackInfo *info = &mTracks.editValueAt(trackIndex); - - int numSidxEntries = info->mSidx.size(); - int64_t totalTime = 0; - off_t totalOffset = mFirstMoofOffset; - for (int i = 0; i < numSidxEntries; i++) { - const SidxEntry *se = &info->mSidx[i]; - if (totalTime + se->mDurationUs > position) { - mBuffer->setRange(0,0); - mBufferPos = totalOffset; - if (mFinalResult == ERROR_END_OF_STREAM) { - mFinalResult = OK; - mSuspended = true; // force resume - resumeIfNecessary(); - } - info->mFragments.clear(); - info->mDecodingTime = totalTime * info->mMediaTimeScale / 1000000ll; - return OK; - } - totalTime += se->mDurationUs; - totalOffset += se->mSize; - } - } - ALOGV("seekTo out of range"); - return err; -} - -status_t FragmentedMP4Parser::dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit, - bool synchronous) { - - while (true) { - sp<AMessage> msg = new AMessage(kWhatDequeueAccessUnit, id()); - msg->setInt32("audio", audio); - - sp<AMessage> response; - status_t err = msg->postAndAwaitResponse(&response); - - if (err != OK) { - ALOGV("dequeue fail 1: %d", err); - return err; - } - - if (response->findInt32("err", &err) && err != OK) { - if (synchronous && err == -EWOULDBLOCK) { - resumeIfNecessary(); - ALOGV("Parser not ready yet, retrying"); - usleep(10000); - continue; - } - ALOGV("dequeue fail 2: %d, %d", err, synchronous); - return err; - } - - CHECK(response->findBuffer("accessUnit", accessUnit)); - - return OK; - } -} - -ssize_t FragmentedMP4Parser::findTrack(bool wantAudio) const { - for (size_t i = 0; i < mTracks.size(); ++i) { - const TrackInfo *info = &mTracks.valueAt(i); - - bool isAudio = - info->mMediaHandlerType == FOURCC('s', 'o', 'u', 'n'); - - bool isVideo = - info->mMediaHandlerType == FOURCC('v', 'i', 'd', 'e'); - - if ((wantAudio && isAudio) || (!wantAudio && !isAudio)) { - if (info->mSampleDescs.empty()) { - break; - } - - return i; - } - } - - return -EWOULDBLOCK; -} - -void FragmentedMP4Parser::onMessageReceived(const sp<AMessage> &msg) { - switch (msg->what()) { - case kWhatStart: - { - sp<RefBase> obj; - CHECK(msg->findObject("source", &obj)); - - mSource = static_cast<Source *>(obj.get()); - - mBuffer = new ABuffer(512 * 1024); - mBuffer->setRange(0, 0); - - enter(0ll, 0, 0); - - (new AMessage(kWhatProceed, id()))->post(); - break; - } - - case kWhatProceed: - { - CHECK(!mSuspended); - - status_t err = onProceed(); - - if (err == OK) { - if (!mSuspended) { - msg->post(); - } - } else if (err != -EAGAIN) { - ALOGE("onProceed returned error %d", err); - } - - break; - } - - case kWhatReadMore: - { - size_t needed; - CHECK(msg->findSize("needed", &needed)); - - memmove(mBuffer->base(), mBuffer->data(), mBuffer->size()); - mBufferPos += mBuffer->offset(); - mBuffer->setRange(0, mBuffer->size()); - - size_t maxBytesToRead = mBuffer->capacity() - mBuffer->size(); - - if (maxBytesToRead < needed) { - ALOGV("resizing buffer."); - - sp<ABuffer> newBuffer = - new ABuffer((mBuffer->size() + needed + 1023) & ~1023); - memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size()); - newBuffer->setRange(0, mBuffer->size()); - - mBuffer = newBuffer; - maxBytesToRead = mBuffer->capacity() - mBuffer->size(); - } - - CHECK_GE(maxBytesToRead, needed); - - ssize_t n = mSource->readAt( - mBufferPos + mBuffer->size(), - mBuffer->data() + mBuffer->size(), needed); - - if (n < (ssize_t)needed) { - ALOGV("Reached EOF when reading %d @ %d + %d", needed, mBufferPos, mBuffer->size()); - if (n < 0) { - mFinalResult = n; - } else if (n == 0) { - mFinalResult = ERROR_END_OF_STREAM; - } else { - mFinalResult = ERROR_IO; - } - } else { - mBuffer->setRange(0, mBuffer->size() + n); - (new AMessage(kWhatProceed, id()))->post(); - } - - break; - } - - case kWhatGetFormat: - { - int32_t wantAudio; - CHECK(msg->findInt32("audio", &wantAudio)); - - status_t err = -EWOULDBLOCK; - sp<AMessage> response = new AMessage; - - ssize_t trackIndex = findTrack(wantAudio); - - if (trackIndex < 0) { - err = trackIndex; - } else { - TrackInfo *info = &mTracks.editValueAt(trackIndex); - - sp<AMessage> format = info->mSampleDescs.itemAt(0).mFormat; - if (info->mSidxDuration) { - format->setInt64("durationUs", info->mSidxDuration); - } else { - // this is probably going to be zero. Oh well... - format->setInt64("durationUs", - 1000000ll * info->mDuration / info->mMediaTimeScale); - } - response->setMessage( - "format", format); - - err = OK; - } - - response->setInt32("err", err); - - uint32_t replyID; - CHECK(msg->senderAwaitsResponse(&replyID)); - - response->postReply(replyID); - break; - } - - case kWhatDequeueAccessUnit: - { - int32_t wantAudio; - CHECK(msg->findInt32("audio", &wantAudio)); - - status_t err = -EWOULDBLOCK; - sp<AMessage> response = new AMessage; - - ssize_t trackIndex = findTrack(wantAudio); - - if (trackIndex < 0) { - err = trackIndex; - } else { - sp<ABuffer> accessUnit; - err = onDequeueAccessUnit(trackIndex, &accessUnit); - - if (err == OK) { - response->setBuffer("accessUnit", accessUnit); - } - } - - response->setInt32("err", err); - - uint32_t replyID; - CHECK(msg->senderAwaitsResponse(&replyID)); - - response->postReply(replyID); - break; - } - - case kWhatSeekTo: - { - ALOGV("kWhatSeekTo"); - int32_t wantAudio; - CHECK(msg->findInt32("audio", &wantAudio)); - int64_t position; - CHECK(msg->findInt64("position", &position)); - - status_t err = -EWOULDBLOCK; - sp<AMessage> response = new AMessage; - - ssize_t trackIndex = findTrack(wantAudio); - - if (trackIndex < 0) { - err = trackIndex; - } else { - err = onSeekTo(wantAudio, position); - } - response->setInt32("err", err); - uint32_t replyID; - CHECK(msg->senderAwaitsResponse(&replyID)); - response->postReply(replyID); - break; - } - default: - TRESPASS(); - } -} - -status_t FragmentedMP4Parser::onProceed() { - status_t err; - - if ((err = need(8)) != OK) { - return err; - } - - uint64_t size = readU32(0); - uint32_t type = readU32(4); - - size_t offset = 8; - - if (size == 1) { - if ((err = need(16)) != OK) { - return err; - } - - size = readU64(offset); - offset += 8; - } - - uint8_t userType[16]; - - if (type == FOURCC('u', 'u', 'i', 'd')) { - if ((err = need(offset + 16)) != OK) { - return err; - } - - memcpy(userType, mBuffer->data() + offset, 16); - offset += 16; - } - - CHECK(!mStack.isEmpty()); - uint32_t ptype = mStack.itemAt(mStack.size() - 1).mType; - - static const size_t kNumDispatchers = - sizeof(kDispatchTable) / sizeof(kDispatchTable[0]); - - size_t i; - for (i = 0; i < kNumDispatchers; ++i) { - if (kDispatchTable[i].mType == type - && kDispatchTable[i].mParentType == ptype) { - break; - } - } - - // SampleEntry boxes are container boxes that start with a variable - // amount of data depending on the media handler type. - // We don't look inside 'hint' type SampleEntry boxes. - - bool isSampleEntryBox = - (ptype == FOURCC('s', 't', 's', 'd')) - && editTrack(mCurrentTrackID)->mMediaHandlerType - != FOURCC('h', 'i', 'n', 't'); - - if ((i < kNumDispatchers && kDispatchTable[i].mHandler == 0) - || isSampleEntryBox || ptype == FOURCC('i', 'l', 's', 't')) { - // This is a container box. - if (type == FOURCC('m', 'o', 'o', 'f')) { - if (mFirstMoofOffset == 0) { - ALOGV("first moof @ %08x", mBufferPos + offset); - mFirstMoofOffset = mBufferPos + offset - 8; // point at the size - } - } - if (type == FOURCC('m', 'e', 't', 'a')) { - if ((err = need(offset + 4)) < OK) { - return err; - } - - if (readU32(offset) != 0) { - return -EINVAL; - } - - offset += 4; - } else if (type == FOURCC('s', 't', 's', 'd')) { - if ((err = need(offset + 8)) < OK) { - return err; - } - - if (readU32(offset) != 0) { - return -EINVAL; - } - - if (readU32(offset + 4) == 0) { - // We need at least some entries. - return -EINVAL; - } - - offset += 8; - } else if (isSampleEntryBox) { - size_t headerSize; - - switch (editTrack(mCurrentTrackID)->mMediaHandlerType) { - case FOURCC('v', 'i', 'd', 'e'): - { - // 8 bytes SampleEntry + 70 bytes VisualSampleEntry - headerSize = 78; - break; - } - - case FOURCC('s', 'o', 'u', 'n'): - { - // 8 bytes SampleEntry + 20 bytes AudioSampleEntry - headerSize = 28; - break; - } - - case FOURCC('m', 'e', 't', 'a'): - { - headerSize = 8; // 8 bytes SampleEntry - break; - } - - default: - TRESPASS(); - } - - if (offset + headerSize > size) { - return -EINVAL; - } - - if ((err = need(offset + headerSize)) != OK) { - return err; - } - - switch (editTrack(mCurrentTrackID)->mMediaHandlerType) { - case FOURCC('v', 'i', 'd', 'e'): - { - err = parseVisualSampleEntry( - type, offset, offset + headerSize); - break; - } - - case FOURCC('s', 'o', 'u', 'n'): - { - err = parseAudioSampleEntry( - type, offset, offset + headerSize); - break; - } - - case FOURCC('m', 'e', 't', 'a'): - { - err = OK; - break; - } - - default: - TRESPASS(); - } - - if (err != OK) { - return err; - } - - offset += headerSize; - } - - skip(offset); - - ALOGV("%sentering box of type '%s'", - IndentString(mStack.size()), Fourcc2String(type)); - - enter(mBufferPos - offset, type, size - offset); - } else { - if (!fitsContainer(size)) { - return -EINVAL; - } - - if (i < kNumDispatchers && kDispatchTable[i].mHandler != 0) { - // We have a handler for this box type. - - if ((err = need(size)) != OK) { - return err; - } - - ALOGV("%sparsing box of type '%s'", - IndentString(mStack.size()), Fourcc2String(type)); - - if ((err = (this->*kDispatchTable[i].mHandler)( - type, offset, size)) != OK) { - return err; - } - } else { - // Unknown box type - - ALOGV("%sskipping box of type '%s', size %llu", - IndentString(mStack.size()), - Fourcc2String(type), size); - - } - - skip(size); - } - - return OK; -} - -// static -int FragmentedMP4Parser::CompareSampleLocation( - const SampleInfo &sample, const MediaDataInfo &mdatInfo) { - if (sample.mOffset + sample.mSize < mdatInfo.mOffset) { - return -1; - } - - if (sample.mOffset >= mdatInfo.mOffset + mdatInfo.mBuffer->size()) { - return 1; - } - - // Otherwise make sure the sample is completely contained within this - // media data block. - - CHECK_GE(sample.mOffset, mdatInfo.mOffset); - - CHECK_LE(sample.mOffset + sample.mSize, - mdatInfo.mOffset + mdatInfo.mBuffer->size()); - - return 0; -} - -void FragmentedMP4Parser::resumeIfNecessary() { - if (!mSuspended) { - return; - } - - ALOGV("resuming."); - - mSuspended = false; - (new AMessage(kWhatProceed, id()))->post(); -} - -status_t FragmentedMP4Parser::getSample( - TrackInfo *info, sp<TrackFragment> *fragment, SampleInfo *sampleInfo) { - for (;;) { - if (info->mFragments.empty()) { - if (mFinalResult != OK) { - return mFinalResult; - } - - resumeIfNecessary(); - return -EWOULDBLOCK; - } - - *fragment = *info->mFragments.begin(); - - status_t err = (*fragment)->getSample(sampleInfo); - - if (err == OK) { - return OK; - } else if (err != ERROR_END_OF_STREAM) { - return err; - } - - // Really, end of this fragment... - - info->mFragments.erase(info->mFragments.begin()); - } -} - -status_t FragmentedMP4Parser::onDequeueAccessUnit( - size_t trackIndex, sp<ABuffer> *accessUnit) { - TrackInfo *info = &mTracks.editValueAt(trackIndex); - - sp<TrackFragment> fragment; - SampleInfo sampleInfo; - status_t err = getSample(info, &fragment, &sampleInfo); - - if (err == -EWOULDBLOCK) { - resumeIfNecessary(); - return err; - } else if (err != OK) { - return err; - } - - err = -EWOULDBLOCK; - - bool checkDroppable = false; - - for (size_t i = 0; i < mMediaData.size(); ++i) { - const MediaDataInfo &mdatInfo = mMediaData.itemAt(i); - - int cmp = CompareSampleLocation(sampleInfo, mdatInfo); - - if (cmp < 0 && !mSource->isSeekable()) { - return -EPIPE; - } else if (cmp == 0) { - if (i > 0) { - checkDroppable = true; - } - - err = makeAccessUnit(info, sampleInfo, mdatInfo, accessUnit); - break; - } - } - - if (err != OK) { - return err; - } - - fragment->advance(); - - if (!mMediaData.empty() && checkDroppable) { - size_t numDroppable = 0; - bool done = false; - - // XXX FIXME: if one of the tracks is not advanced (e.g. if you play an audio+video - // file with sf2), then mMediaData will not be pruned and keeps growing - for (size_t i = 0; !done && i < mMediaData.size(); ++i) { - const MediaDataInfo &mdatInfo = mMediaData.itemAt(i); - - for (size_t j = 0; j < mTracks.size(); ++j) { - TrackInfo *info = &mTracks.editValueAt(j); - - sp<TrackFragment> fragment; - SampleInfo sampleInfo; - err = getSample(info, &fragment, &sampleInfo); - - if (err != OK) { - done = true; - break; - } - - int cmp = CompareSampleLocation(sampleInfo, mdatInfo); - - if (cmp <= 0) { - done = true; - break; - } - } - - if (!done) { - ++numDroppable; - } - } - - if (numDroppable > 0) { - mMediaData.removeItemsAt(0, numDroppable); - - if (mMediaData.size() < 5) { - resumeIfNecessary(); - } - } - } - - return err; -} - -static size_t parseNALSize(size_t nalLengthSize, const uint8_t *data) { - switch (nalLengthSize) { - case 1: - return *data; - case 2: - return U16_AT(data); - case 3: - return ((size_t)data[0] << 16) | U16_AT(&data[1]); - case 4: - return U32_AT(data); - } - - // This cannot happen, mNALLengthSize springs to life by adding 1 to - // a 2-bit integer. - TRESPASS(); - - return 0; -} - -status_t FragmentedMP4Parser::makeAccessUnit( - TrackInfo *info, - const SampleInfo &sample, - const MediaDataInfo &mdatInfo, - sp<ABuffer> *accessUnit) { - if (sample.mSampleDescIndex < 1 - || sample.mSampleDescIndex > info->mSampleDescs.size()) { - return ERROR_MALFORMED; - } - - int64_t presentationTimeUs = - 1000000ll * sample.mPresentationTime / info->mMediaTimeScale; - - const SampleDescription &sampleDesc = - info->mSampleDescs.itemAt(sample.mSampleDescIndex - 1); - - size_t nalLengthSize; - if (!sampleDesc.mFormat->findSize("nal-length-size", &nalLengthSize)) { - *accessUnit = new ABuffer(sample.mSize); - - memcpy((*accessUnit)->data(), - mdatInfo.mBuffer->data() + (sample.mOffset - mdatInfo.mOffset), - sample.mSize); - - (*accessUnit)->meta()->setInt64("timeUs", presentationTimeUs); - if (IsIDR(*accessUnit)) { - (*accessUnit)->meta()->setInt32("is-sync-frame", 1); - } - - return OK; - } - - const uint8_t *srcPtr = - mdatInfo.mBuffer->data() + (sample.mOffset - mdatInfo.mOffset); - - for (int i = 0; i < 2 ; ++i) { - size_t srcOffset = 0; - size_t dstOffset = 0; - - while (srcOffset < sample.mSize) { - if (srcOffset + nalLengthSize > sample.mSize) { - return ERROR_MALFORMED; - } - - size_t nalSize = parseNALSize(nalLengthSize, &srcPtr[srcOffset]); - srcOffset += nalLengthSize; - - if (srcOffset + nalSize > sample.mSize) { - return ERROR_MALFORMED; - } - - if (i == 1) { - memcpy((*accessUnit)->data() + dstOffset, - "\x00\x00\x00\x01", - 4); - - memcpy((*accessUnit)->data() + dstOffset + 4, - srcPtr + srcOffset, - nalSize); - } - - srcOffset += nalSize; - dstOffset += nalSize + 4; - } - - if (i == 0) { - (*accessUnit) = new ABuffer(dstOffset); - (*accessUnit)->meta()->setInt64( - "timeUs", presentationTimeUs); - } - } - if (IsIDR(*accessUnit)) { - (*accessUnit)->meta()->setInt32("is-sync-frame", 1); - } - - return OK; -} - -status_t FragmentedMP4Parser::need(size_t size) { - if (!fitsContainer(size)) { - return -EINVAL; - } - - if (size <= mBuffer->size()) { - return OK; - } - - sp<AMessage> msg = new AMessage(kWhatReadMore, id()); - msg->setSize("needed", size - mBuffer->size()); - msg->post(); - - // ALOGV("need(%d) returning -EAGAIN, only have %d", size, mBuffer->size()); - - return -EAGAIN; -} - -void FragmentedMP4Parser::enter(off64_t offset, uint32_t type, uint64_t size) { - Container container; - container.mOffset = offset; - container.mType = type; - container.mExtendsToEOF = (size == 0); - container.mBytesRemaining = size; - - mStack.push(container); -} - -bool FragmentedMP4Parser::fitsContainer(uint64_t size) const { - CHECK(!mStack.isEmpty()); - const Container &container = mStack.itemAt(mStack.size() - 1); - - return container.mExtendsToEOF || size <= container.mBytesRemaining; -} - -uint16_t FragmentedMP4Parser::readU16(size_t offset) { - CHECK_LE(offset + 2, mBuffer->size()); - - const uint8_t *ptr = mBuffer->data() + offset; - return (ptr[0] << 8) | ptr[1]; -} - -uint32_t FragmentedMP4Parser::readU32(size_t offset) { - CHECK_LE(offset + 4, mBuffer->size()); - - const uint8_t *ptr = mBuffer->data() + offset; - return (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]; -} - -uint64_t FragmentedMP4Parser::readU64(size_t offset) { - return (((uint64_t)readU32(offset)) << 32) | readU32(offset + 4); -} - -void FragmentedMP4Parser::skip(off_t distance) { - CHECK(!mStack.isEmpty()); - for (size_t i = mStack.size(); i-- > 0;) { - Container *container = &mStack.editItemAt(i); - if (!container->mExtendsToEOF) { - CHECK_LE(distance, (off_t)container->mBytesRemaining); - - container->mBytesRemaining -= distance; - - if (container->mBytesRemaining == 0) { - ALOGV("%sleaving box of type '%s'", - IndentString(mStack.size() - 1), - Fourcc2String(container->mType)); - -#if 0 - if (container->mType == FOURCC('s', 't', 's', 'd')) { - TrackInfo *trackInfo = editTrack(mCurrentTrackID); - for (size_t i = 0; - i < trackInfo->mSampleDescs.size(); ++i) { - ALOGI("format #%d: %s", - i, - trackInfo->mSampleDescs.itemAt(i) - .mFormat->debugString().c_str()); - } - } -#endif - - if (container->mType == FOURCC('s', 't', 'b', 'l')) { - TrackInfo *trackInfo = editTrack(mCurrentTrackID); - - trackInfo->mStaticFragment->signalCompletion(); - - CHECK(trackInfo->mFragments.empty()); - trackInfo->mFragments.push_back(trackInfo->mStaticFragment); - trackInfo->mStaticFragment.clear(); - } else if (container->mType == FOURCC('t', 'r', 'a', 'f')) { - TrackInfo *trackInfo = - editTrack(mTrackFragmentHeaderInfo.mTrackID); - - const sp<TrackFragment> &fragment = - *--trackInfo->mFragments.end(); - - static_cast<DynamicTrackFragment *>( - fragment.get())->signalCompletion(); - } else if (container->mType == FOURCC('m', 'o', 'o', 'v')) { - mDoneWithMoov = true; - } - - container = NULL; - mStack.removeItemsAt(i); - } - } - } - - if (distance < (off_t)mBuffer->size()) { - mBuffer->setRange(mBuffer->offset() + distance, mBuffer->size() - distance); - mBufferPos += distance; - return; - } - - mBuffer->setRange(0, 0); - mBufferPos += distance; -} - -status_t FragmentedMP4Parser::parseTrackHeader( - uint32_t type, size_t offset, uint64_t size) { - if (offset + 4 > size) { - return -EINVAL; - } - - uint32_t flags = readU32(offset); - - uint32_t version = flags >> 24; - flags &= 0xffffff; - - uint32_t trackID; - uint64_t duration; - - if (version == 1) { - if (offset + 36 > size) { - return -EINVAL; - } - - trackID = readU32(offset + 20); - duration = readU64(offset + 28); - - offset += 36; - } else if (version == 0) { - if (offset + 24 > size) { - return -EINVAL; - } - - trackID = readU32(offset + 12); - duration = readU32(offset + 20); - - offset += 24; - } else { - return -EINVAL; - } - - TrackInfo *info = editTrack(trackID, true /* createIfNecessary */); - info->mFlags = flags; - info->mDuration = duration; - if (info->mDuration == 0xffffffff) { - // ffmpeg sets this to -1, which is incorrect. - info->mDuration = 0; - } - - info->mStaticFragment = new StaticTrackFragment; - - mCurrentTrackID = trackID; - - return OK; -} - -status_t FragmentedMP4Parser::parseMediaHeader( - uint32_t type, size_t offset, uint64_t size) { - if (offset + 4 > size) { - return -EINVAL; - } - - uint32_t versionAndFlags = readU32(offset); - - if (versionAndFlags & 0xffffff) { - return ERROR_MALFORMED; - } - - uint32_t version = versionAndFlags >> 24; - - TrackInfo *info = editTrack(mCurrentTrackID); - - if (version == 1) { - if (offset + 4 + 32 > size) { - return -EINVAL; - } - info->mMediaTimeScale = U32_AT(mBuffer->data() + offset + 20); - } else if (version == 0) { - if (offset + 4 + 20 > size) { - return -EINVAL; - } - info->mMediaTimeScale = U32_AT(mBuffer->data() + offset + 12); - } else { - return ERROR_MALFORMED; - } - - return OK; -} - -status_t FragmentedMP4Parser::parseMediaHandler( - uint32_t type, size_t offset, uint64_t size) { - if (offset + 12 > size) { - return -EINVAL; - } - - if (readU32(offset) != 0) { - return -EINVAL; - } - - uint32_t handlerType = readU32(offset + 8); - - switch (handlerType) { - case FOURCC('v', 'i', 'd', 'e'): - case FOURCC('s', 'o', 'u', 'n'): - case FOURCC('h', 'i', 'n', 't'): - case FOURCC('m', 'e', 't', 'a'): - break; - - default: - return -EINVAL; - } - - editTrack(mCurrentTrackID)->mMediaHandlerType = handlerType; - - return OK; -} - -status_t FragmentedMP4Parser::parseVisualSampleEntry( - uint32_t type, size_t offset, uint64_t size) { - if (offset + 78 > size) { - return -EINVAL; - } - - TrackInfo *trackInfo = editTrack(mCurrentTrackID); - - trackInfo->mSampleDescs.push(); - SampleDescription *sampleDesc = - &trackInfo->mSampleDescs.editItemAt( - trackInfo->mSampleDescs.size() - 1); - - sampleDesc->mType = type; - sampleDesc->mDataRefIndex = readU16(offset + 6); - - sp<AMessage> format = new AMessage; - - switch (type) { - case FOURCC('a', 'v', 'c', '1'): - format->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC); - break; - case FOURCC('m', 'p', '4', 'v'): - format->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4); - break; - case FOURCC('s', '2', '6', '3'): - case FOURCC('h', '2', '6', '3'): - case FOURCC('H', '2', '6', '3'): - format->setString("mime", MEDIA_MIMETYPE_VIDEO_H263); - break; - default: - format->setString("mime", "application/octet-stream"); - break; - } - - format->setInt32("width", readU16(offset + 8 + 16)); - format->setInt32("height", readU16(offset + 8 + 18)); - - sampleDesc->mFormat = format; - - return OK; -} - -status_t FragmentedMP4Parser::parseAudioSampleEntry( - uint32_t type, size_t offset, uint64_t size) { - if (offset + 28 > size) { - return -EINVAL; - } - - TrackInfo *trackInfo = editTrack(mCurrentTrackID); - - trackInfo->mSampleDescs.push(); - SampleDescription *sampleDesc = - &trackInfo->mSampleDescs.editItemAt( - trackInfo->mSampleDescs.size() - 1); - - sampleDesc->mType = type; - sampleDesc->mDataRefIndex = readU16(offset + 6); - - sp<AMessage> format = new AMessage; - - format->setInt32("channel-count", readU16(offset + 8 + 8)); - format->setInt32("sample-size", readU16(offset + 8 + 10)); - format->setInt32("sample-rate", readU32(offset + 8 + 16) / 65536.0f); - - switch (type) { - case FOURCC('m', 'p', '4', 'a'): - format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC); - break; - - case FOURCC('s', 'a', 'm', 'r'): - format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB); - format->setInt32("channel-count", 1); - format->setInt32("sample-rate", 8000); - break; - - case FOURCC('s', 'a', 'w', 'b'): - format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB); - format->setInt32("channel-count", 1); - format->setInt32("sample-rate", 16000); - break; - default: - format->setString("mime", "application/octet-stream"); - break; - } - - sampleDesc->mFormat = format; - - return OK; -} - -static void addCodecSpecificData( - const sp<AMessage> &format, int32_t index, - const void *data, size_t size, - bool insertStartCode = false) { - sp<ABuffer> csd = new ABuffer(insertStartCode ? size + 4 : size); - - memcpy(csd->data() + (insertStartCode ? 4 : 0), data, size); - - if (insertStartCode) { - memcpy(csd->data(), "\x00\x00\x00\x01", 4); - } - - csd->meta()->setInt32("csd", true); - csd->meta()->setInt64("timeUs", 0ll); - - format->setBuffer(StringPrintf("csd-%d", index).c_str(), csd); -} - -status_t FragmentedMP4Parser::parseSampleSizes( - uint32_t type, size_t offset, uint64_t size) { - return editTrack(mCurrentTrackID)->mStaticFragment->parseSampleSizes( - this, type, offset, size); -} - -status_t FragmentedMP4Parser::parseCompactSampleSizes( - uint32_t type, size_t offset, uint64_t size) { - return editTrack(mCurrentTrackID)->mStaticFragment->parseCompactSampleSizes( - this, type, offset, size); -} - -status_t FragmentedMP4Parser::parseSampleToChunk( - uint32_t type, size_t offset, uint64_t size) { - return editTrack(mCurrentTrackID)->mStaticFragment->parseSampleToChunk( - this, type, offset, size); -} - -status_t FragmentedMP4Parser::parseChunkOffsets( - uint32_t type, size_t offset, uint64_t size) { - return editTrack(mCurrentTrackID)->mStaticFragment->parseChunkOffsets( - this, type, offset, size); -} - -status_t FragmentedMP4Parser::parseChunkOffsets64( - uint32_t type, size_t offset, uint64_t size) { - return editTrack(mCurrentTrackID)->mStaticFragment->parseChunkOffsets64( - this, type, offset, size); -} - -status_t FragmentedMP4Parser::parseAVCCodecSpecificData( - uint32_t type, size_t offset, uint64_t size) { - TrackInfo *trackInfo = editTrack(mCurrentTrackID); - - SampleDescription *sampleDesc = - &trackInfo->mSampleDescs.editItemAt( - trackInfo->mSampleDescs.size() - 1); - - if (sampleDesc->mType != FOURCC('a', 'v', 'c', '1')) { - return -EINVAL; - } - - const uint8_t *ptr = mBuffer->data() + offset; - - size -= offset; - offset = 0; - - if (size < 7 || ptr[0] != 0x01) { - return ERROR_MALFORMED; - } - - sampleDesc->mFormat->setSize("nal-length-size", 1 + (ptr[4] & 3)); - - size_t numSPS = ptr[5] & 31; - - ptr += 6; - size -= 6; - - for (size_t i = 0; i < numSPS; ++i) { - if (size < 2) { - return ERROR_MALFORMED; - } - - size_t length = U16_AT(ptr); - - ptr += 2; - size -= 2; - - if (size < length) { - return ERROR_MALFORMED; - } - - addCodecSpecificData( - sampleDesc->mFormat, i, ptr, length, - true /* insertStartCode */); - - ptr += length; - size -= length; - } - - if (size < 1) { - return ERROR_MALFORMED; - } - - size_t numPPS = *ptr; - ++ptr; - --size; - - for (size_t i = 0; i < numPPS; ++i) { - if (size < 2) { - return ERROR_MALFORMED; - } - - size_t length = U16_AT(ptr); - - ptr += 2; - size -= 2; - - if (size < length) { - return ERROR_MALFORMED; - } - - addCodecSpecificData( - sampleDesc->mFormat, numSPS + i, ptr, length, - true /* insertStartCode */); - - ptr += length; - size -= length; - } - - return OK; -} - -status_t FragmentedMP4Parser::parseESDSCodecSpecificData( - uint32_t type, size_t offset, uint64_t size) { - TrackInfo *trackInfo = editTrack(mCurrentTrackID); - - SampleDescription *sampleDesc = - &trackInfo->mSampleDescs.editItemAt( - trackInfo->mSampleDescs.size() - 1); - - if (sampleDesc->mType != FOURCC('m', 'p', '4', 'a') - && sampleDesc->mType != FOURCC('m', 'p', '4', 'v')) { - return -EINVAL; - } - - const uint8_t *ptr = mBuffer->data() + offset; - - size -= offset; - offset = 0; - - if (size < 4) { - return -EINVAL; - } - - if (U32_AT(ptr) != 0) { - return -EINVAL; - } - - ptr += 4; - size -=4; - - ESDS esds(ptr, size); - - uint8_t objectTypeIndication; - if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) { - return ERROR_MALFORMED; - } - - const uint8_t *csd; - size_t csd_size; - if (esds.getCodecSpecificInfo( - (const void **)&csd, &csd_size) != OK) { - return ERROR_MALFORMED; - } - - addCodecSpecificData(sampleDesc->mFormat, 0, csd, csd_size); - - if (sampleDesc->mType != FOURCC('m', 'p', '4', 'a')) { - return OK; - } - - if (csd_size == 0) { - // There's no further information, i.e. no codec specific data - // Let's assume that the information provided in the mpeg4 headers - // is accurate and hope for the best. - - return OK; - } - - if (csd_size < 2) { - return ERROR_MALFORMED; - } - - uint32_t objectType = csd[0] >> 3; - - if (objectType == 31) { - return ERROR_UNSUPPORTED; - } - - uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7); - int32_t sampleRate = 0; - int32_t numChannels = 0; - if (freqIndex == 15) { - if (csd_size < 5) { - return ERROR_MALFORMED; - } - - sampleRate = (csd[1] & 0x7f) << 17 - | csd[2] << 9 - | csd[3] << 1 - | (csd[4] >> 7); - - numChannels = (csd[4] >> 3) & 15; - } else { - static uint32_t kSamplingRate[] = { - 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, - 16000, 12000, 11025, 8000, 7350 - }; - - if (freqIndex == 13 || freqIndex == 14) { - return ERROR_MALFORMED; - } - - sampleRate = kSamplingRate[freqIndex]; - numChannels = (csd[1] >> 3) & 15; - } - - if (numChannels == 0) { - return ERROR_UNSUPPORTED; - } - - sampleDesc->mFormat->setInt32("sample-rate", sampleRate); - sampleDesc->mFormat->setInt32("channel-count", numChannels); - - return OK; -} - -status_t FragmentedMP4Parser::parseMediaData( - uint32_t type, size_t offset, uint64_t size) { - ALOGV("skipping 'mdat' chunk at offsets 0x%08lx-0x%08llx.", - mBufferPos + offset, mBufferPos + size); - - sp<ABuffer> buffer = new ABuffer(size - offset); - memcpy(buffer->data(), mBuffer->data() + offset, size - offset); - - mMediaData.push(); - MediaDataInfo *info = &mMediaData.editItemAt(mMediaData.size() - 1); - info->mBuffer = buffer; - info->mOffset = mBufferPos + offset; - - if (mMediaData.size() > 10) { - ALOGV("suspending for now."); - mSuspended = true; - } - - return OK; -} - -status_t FragmentedMP4Parser::parseSegmentIndex( - uint32_t type, size_t offset, uint64_t size) { - ALOGV("sidx box type %d, offset %d, size %d", type, int(offset), int(size)); -// AString sidxstr; -// hexdump(mBuffer->data() + offset, size, 0 /* indent */, &sidxstr); -// ALOGV("raw sidx:"); -// ALOGV("%s", sidxstr.c_str()); - if (offset + 12 > size) { - return -EINVAL; - } - - uint32_t flags = readU32(offset); - - uint32_t version = flags >> 24; - flags &= 0xffffff; - - ALOGV("sidx version %d", version); - - uint32_t referenceId = readU32(offset + 4); - uint32_t timeScale = readU32(offset + 8); - ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale); - - uint64_t earliestPresentationTime; - uint64_t firstOffset; - - offset += 12; - - if (version == 0) { - if (offset + 8 > size) { - return -EINVAL; - } - earliestPresentationTime = readU32(offset); - firstOffset = readU32(offset + 4); - offset += 8; - } else { - if (offset + 16 > size) { - return -EINVAL; - } - earliestPresentationTime = readU64(offset); - firstOffset = readU64(offset + 8); - offset += 16; - } - ALOGV("sidx pres/off: %Ld/%Ld", earliestPresentationTime, firstOffset); - - if (offset + 4 > size) { - return -EINVAL; - } - if (readU16(offset) != 0) { // reserved - return -EINVAL; - } - int32_t referenceCount = readU16(offset + 2); - offset += 4; - ALOGV("refcount: %d", referenceCount); - - if (offset + referenceCount * 12 > size) { - return -EINVAL; - } - - TrackInfo *info = editTrack(mCurrentTrackID); - uint64_t total_duration = 0; - for (int i = 0; i < referenceCount; i++) { - uint32_t d1 = readU32(offset); - uint32_t d2 = readU32(offset + 4); - uint32_t d3 = readU32(offset + 8); - - if (d1 & 0x80000000) { - ALOGW("sub-sidx boxes not supported yet"); - } - bool sap = d3 & 0x80000000; - bool saptype = d3 >> 28; - if (!sap || saptype > 2) { - ALOGW("not a stream access point, or unsupported type"); - } - total_duration += d2; - offset += 12; - ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3); - SidxEntry se; - se.mSize = d1 & 0x7fffffff; - se.mDurationUs = 1000000LL * d2 / timeScale; - info->mSidx.add(se); - } - - info->mSidxDuration = total_duration * 1000000 / timeScale; - ALOGV("duration: %lld", info->mSidxDuration); - return OK; -} - -status_t FragmentedMP4Parser::parseTrackExtends( - uint32_t type, size_t offset, uint64_t size) { - if (offset + 24 > size) { - return -EINVAL; - } - - if (readU32(offset) != 0) { - return -EINVAL; - } - - uint32_t trackID = readU32(offset + 4); - - TrackInfo *info = editTrack(trackID, true /* createIfNecessary */); - info->mDefaultSampleDescriptionIndex = readU32(offset + 8); - info->mDefaultSampleDuration = readU32(offset + 12); - info->mDefaultSampleSize = readU32(offset + 16); - info->mDefaultSampleFlags = readU32(offset + 20); - - return OK; -} - -FragmentedMP4Parser::TrackInfo *FragmentedMP4Parser::editTrack( - uint32_t trackID, bool createIfNecessary) { - ssize_t i = mTracks.indexOfKey(trackID); - - if (i >= 0) { - return &mTracks.editValueAt(i); - } - - if (!createIfNecessary) { - return NULL; - } - - TrackInfo info; - info.mTrackID = trackID; - info.mFlags = 0; - info.mDuration = 0xffffffff; - info.mSidxDuration = 0; - info.mMediaTimeScale = 0; - info.mMediaHandlerType = 0; - info.mDefaultSampleDescriptionIndex = 0; - info.mDefaultSampleDuration = 0; - info.mDefaultSampleSize = 0; - info.mDefaultSampleFlags = 0; - - info.mDecodingTime = 0; - - mTracks.add(trackID, info); - return &mTracks.editValueAt(mTracks.indexOfKey(trackID)); -} - -status_t FragmentedMP4Parser::parseTrackFragmentHeader( - uint32_t type, size_t offset, uint64_t size) { - if (offset + 8 > size) { - return -EINVAL; - } - - uint32_t flags = readU32(offset); - - if (flags & 0xff000000) { - return -EINVAL; - } - - mTrackFragmentHeaderInfo.mFlags = flags; - - mTrackFragmentHeaderInfo.mTrackID = readU32(offset + 4); - offset += 8; - - if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) { - if (offset + 8 > size) { - return -EINVAL; - } - - mTrackFragmentHeaderInfo.mBaseDataOffset = readU64(offset); - offset += 8; - } - - if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) { - if (offset + 4 > size) { - return -EINVAL; - } - - mTrackFragmentHeaderInfo.mSampleDescriptionIndex = readU32(offset); - offset += 4; - } - - if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) { - if (offset + 4 > size) { - return -EINVAL; - } - - mTrackFragmentHeaderInfo.mDefaultSampleDuration = readU32(offset); - offset += 4; - } - - if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) { - if (offset + 4 > size) { - return -EINVAL; - } - - mTrackFragmentHeaderInfo.mDefaultSampleSize = readU32(offset); - offset += 4; - } - - if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) { - if (offset + 4 > size) { - return -EINVAL; - } - - mTrackFragmentHeaderInfo.mDefaultSampleFlags = readU32(offset); - offset += 4; - } - - if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) { - // This should point to the position of the first byte of the - // enclosing 'moof' container for the first track and - // the end of the data of the preceding fragment for subsequent - // tracks. - - CHECK_GE(mStack.size(), 2u); - - mTrackFragmentHeaderInfo.mBaseDataOffset = - mStack.itemAt(mStack.size() - 2).mOffset; - - // XXX TODO: This does not do the right thing for the 2nd and - // subsequent tracks yet. - } - - mTrackFragmentHeaderInfo.mDataOffset = - mTrackFragmentHeaderInfo.mBaseDataOffset; - - TrackInfo *trackInfo = editTrack(mTrackFragmentHeaderInfo.mTrackID); - - if (trackInfo->mFragments.empty() - || (*trackInfo->mFragments.begin())->complete()) { - trackInfo->mFragments.push_back(new DynamicTrackFragment); - } - - return OK; -} - -status_t FragmentedMP4Parser::parseTrackFragmentRun( - uint32_t type, size_t offset, uint64_t size) { - if (offset + 8 > size) { - return -EINVAL; - } - - enum { - kDataOffsetPresent = 0x01, - kFirstSampleFlagsPresent = 0x04, - kSampleDurationPresent = 0x100, - kSampleSizePresent = 0x200, - kSampleFlagsPresent = 0x400, - kSampleCompositionTimeOffsetPresent = 0x800, - }; - - uint32_t flags = readU32(offset); - - if (flags & 0xff000000) { - return -EINVAL; - } - - if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) { - // These two shall not be used together. - return -EINVAL; - } - - uint32_t sampleCount = readU32(offset + 4); - offset += 8; - - uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset; - - uint32_t firstSampleFlags = 0; - - if (flags & kDataOffsetPresent) { - if (offset + 4 > size) { - return -EINVAL; - } - - int32_t dataOffsetDelta = (int32_t)readU32(offset); - - dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta; - - offset += 4; - } - - if (flags & kFirstSampleFlagsPresent) { - if (offset + 4 > size) { - return -EINVAL; - } - - firstSampleFlags = readU32(offset); - offset += 4; - } - - TrackInfo *info = editTrack(mTrackFragmentHeaderInfo.mTrackID); - - if (info == NULL) { - return -EINVAL; - } - - uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0, - sampleCtsOffset = 0; - - size_t bytesPerSample = 0; - if (flags & kSampleDurationPresent) { - bytesPerSample += 4; - } else if (mTrackFragmentHeaderInfo.mFlags - & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) { - sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration; - } else { - sampleDuration = info->mDefaultSampleDuration; - } - - if (flags & kSampleSizePresent) { - bytesPerSample += 4; - } else if (mTrackFragmentHeaderInfo.mFlags - & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) { - sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize; - } else { - sampleSize = info->mDefaultSampleSize; - } - - if (flags & kSampleFlagsPresent) { - bytesPerSample += 4; - } else if (mTrackFragmentHeaderInfo.mFlags - & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) { - sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags; - } else { - sampleFlags = info->mDefaultSampleFlags; - } - - if (flags & kSampleCompositionTimeOffsetPresent) { - bytesPerSample += 4; - } else { - sampleCtsOffset = 0; - } - - if (offset + sampleCount * bytesPerSample > size) { - return -EINVAL; - } - - uint32_t sampleDescIndex = - (mTrackFragmentHeaderInfo.mFlags - & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) - ? mTrackFragmentHeaderInfo.mSampleDescriptionIndex - : info->mDefaultSampleDescriptionIndex; - - for (uint32_t i = 0; i < sampleCount; ++i) { - if (flags & kSampleDurationPresent) { - sampleDuration = readU32(offset); - offset += 4; - } - - if (flags & kSampleSizePresent) { - sampleSize = readU32(offset); - offset += 4; - } - - if (flags & kSampleFlagsPresent) { - sampleFlags = readU32(offset); - offset += 4; - } - - if (flags & kSampleCompositionTimeOffsetPresent) { - sampleCtsOffset = readU32(offset); - offset += 4; - } - - ALOGV("adding sample at offset 0x%08llx, size %u, duration %u, " - "sampleDescIndex=%u, flags 0x%08x", - dataOffset, sampleSize, sampleDuration, - sampleDescIndex, - (flags & kFirstSampleFlagsPresent) && i == 0 - ? firstSampleFlags : sampleFlags); - - const sp<TrackFragment> &fragment = *--info->mFragments.end(); - - uint32_t decodingTime = info->mDecodingTime; - info->mDecodingTime += sampleDuration; - uint32_t presentationTime = decodingTime + sampleCtsOffset; - - static_cast<DynamicTrackFragment *>( - fragment.get())->addSample( - dataOffset, - sampleSize, - presentationTime, - sampleDescIndex, - ((flags & kFirstSampleFlagsPresent) && i == 0) - ? firstSampleFlags : sampleFlags); - - dataOffset += sampleSize; - } - - mTrackFragmentHeaderInfo.mDataOffset = dataOffset; - - return OK; -} - -void FragmentedMP4Parser::copyBuffer( - sp<ABuffer> *dst, size_t offset, uint64_t size) const { - sp<ABuffer> buf = new ABuffer(size); - memcpy(buf->data(), mBuffer->data() + offset, size); - - *dst = buf; -} - -} // namespace android diff --git a/media/libstagefright/mp4/TrackFragment.cpp b/media/libstagefright/mp4/TrackFragment.cpp deleted file mode 100644 index 3699038..0000000 --- a/media/libstagefright/mp4/TrackFragment.cpp +++ /dev/null @@ -1,364 +0,0 @@ -/* - * 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 "TrackFragment" -#include <utils/Log.h> - -#include "TrackFragment.h" - -#include <media/stagefright/MediaErrors.h> -#include <media/stagefright/Utils.h> -#include <media/stagefright/foundation/ABuffer.h> -#include <media/stagefright/foundation/ADebug.h> -#include <media/stagefright/foundation/hexdump.h> - -namespace android { - -FragmentedMP4Parser::DynamicTrackFragment::DynamicTrackFragment() - : mComplete(false), - mSampleIndex(0) { -} - -FragmentedMP4Parser::DynamicTrackFragment::~DynamicTrackFragment() { -} - -status_t FragmentedMP4Parser::DynamicTrackFragment::getSample(SampleInfo *info) { - if (mSampleIndex >= mSamples.size()) { - return mComplete ? ERROR_END_OF_STREAM : -EWOULDBLOCK; - } - - *info = mSamples.itemAt(mSampleIndex); - - return OK; -} - -void FragmentedMP4Parser::DynamicTrackFragment::advance() { - ++mSampleIndex; -} - -void FragmentedMP4Parser::DynamicTrackFragment::addSample( - off64_t dataOffset, size_t sampleSize, - uint32_t presentationTime, - size_t sampleDescIndex, - uint32_t flags) { - mSamples.push(); - SampleInfo *sampleInfo = &mSamples.editItemAt(mSamples.size() - 1); - - sampleInfo->mOffset = dataOffset; - sampleInfo->mSize = sampleSize; - sampleInfo->mPresentationTime = presentationTime; - sampleInfo->mSampleDescIndex = sampleDescIndex; - sampleInfo->mFlags = flags; -} - -status_t FragmentedMP4Parser::DynamicTrackFragment::signalCompletion() { - mComplete = true; - - return OK; -} - -bool FragmentedMP4Parser::DynamicTrackFragment::complete() const { - return mComplete; -} - -//////////////////////////////////////////////////////////////////////////////// - -FragmentedMP4Parser::StaticTrackFragment::StaticTrackFragment() - : mSampleIndex(0), - mSampleCount(0), - mChunkIndex(0), - mSampleToChunkIndex(-1), - mSampleToChunkRemaining(0), - mPrevChunkIndex(0xffffffff), - mNextSampleOffset(0) { -} - -FragmentedMP4Parser::StaticTrackFragment::~StaticTrackFragment() { -} - -status_t FragmentedMP4Parser::StaticTrackFragment::getSample(SampleInfo *info) { - if (mSampleIndex >= mSampleCount) { - return ERROR_END_OF_STREAM; - } - - *info = mSampleInfo; - - ALOGV("returning sample %d at [0x%08llx, 0x%08llx)", - mSampleIndex, - info->mOffset, info->mOffset + info->mSize); - - return OK; -} - -void FragmentedMP4Parser::StaticTrackFragment::updateSampleInfo() { - if (mSampleIndex >= mSampleCount) { - return; - } - - if (mSampleSizes != NULL) { - uint32_t defaultSampleSize = U32_AT(mSampleSizes->data() + 4); - if (defaultSampleSize > 0) { - mSampleInfo.mSize = defaultSampleSize; - } else { - mSampleInfo.mSize= U32_AT(mSampleSizes->data() + 12 + 4 * mSampleIndex); - } - } else { - CHECK(mCompactSampleSizes != NULL); - - uint32_t fieldSize = U32_AT(mCompactSampleSizes->data() + 4); - - switch (fieldSize) { - case 4: - { - unsigned byte = mCompactSampleSizes->data()[12 + mSampleIndex / 2]; - mSampleInfo.mSize = (mSampleIndex & 1) ? byte & 0x0f : byte >> 4; - break; - } - - case 8: - { - mSampleInfo.mSize = mCompactSampleSizes->data()[12 + mSampleIndex]; - break; - } - - default: - { - CHECK_EQ(fieldSize, 16); - mSampleInfo.mSize = - U16_AT(mCompactSampleSizes->data() + 12 + mSampleIndex * 2); - break; - } - } - } - - CHECK_GT(mSampleToChunkRemaining, 0); - - // The sample desc index is 1-based... XXX - mSampleInfo.mSampleDescIndex = - U32_AT(mSampleToChunk->data() + 8 + 12 * mSampleToChunkIndex + 8); - - if (mChunkIndex != mPrevChunkIndex) { - mPrevChunkIndex = mChunkIndex; - - if (mChunkOffsets != NULL) { - uint32_t entryCount = U32_AT(mChunkOffsets->data() + 4); - - if (mChunkIndex >= entryCount) { - mSampleIndex = mSampleCount; - return; - } - - mNextSampleOffset = - U32_AT(mChunkOffsets->data() + 8 + 4 * mChunkIndex); - } else { - CHECK(mChunkOffsets64 != NULL); - - uint32_t entryCount = U32_AT(mChunkOffsets64->data() + 4); - - if (mChunkIndex >= entryCount) { - mSampleIndex = mSampleCount; - return; - } - - mNextSampleOffset = - U64_AT(mChunkOffsets64->data() + 8 + 8 * mChunkIndex); - } - } - - mSampleInfo.mOffset = mNextSampleOffset; - - mSampleInfo.mPresentationTime = 0; - mSampleInfo.mFlags = 0; -} - -void FragmentedMP4Parser::StaticTrackFragment::advance() { - mNextSampleOffset += mSampleInfo.mSize; - - ++mSampleIndex; - if (--mSampleToChunkRemaining == 0) { - ++mChunkIndex; - - uint32_t entryCount = U32_AT(mSampleToChunk->data() + 4); - - // If this is the last entry in the sample to chunk table, we will - // stay on this entry. - if ((uint32_t)(mSampleToChunkIndex + 1) < entryCount) { - uint32_t nextChunkIndex = - U32_AT(mSampleToChunk->data() + 8 + 12 * (mSampleToChunkIndex + 1)); - - CHECK_GE(nextChunkIndex, 1u); - --nextChunkIndex; - - if (mChunkIndex >= nextChunkIndex) { - CHECK_EQ(mChunkIndex, nextChunkIndex); - ++mSampleToChunkIndex; - } - } - - mSampleToChunkRemaining = - U32_AT(mSampleToChunk->data() + 8 + 12 * mSampleToChunkIndex + 4); - } - - updateSampleInfo(); -} - -static void setU32At(uint8_t *ptr, uint32_t x) { - ptr[0] = x >> 24; - ptr[1] = (x >> 16) & 0xff; - ptr[2] = (x >> 8) & 0xff; - ptr[3] = x & 0xff; -} - -status_t FragmentedMP4Parser::StaticTrackFragment::signalCompletion() { - mSampleToChunkIndex = 0; - - mSampleToChunkRemaining = - (mSampleToChunk == NULL) - ? 0 - : U32_AT(mSampleToChunk->data() + 8 + 12 * mSampleToChunkIndex + 4); - - updateSampleInfo(); - - return OK; -} - -bool FragmentedMP4Parser::StaticTrackFragment::complete() const { - return true; -} - -status_t FragmentedMP4Parser::StaticTrackFragment::parseSampleSizes( - FragmentedMP4Parser *parser, uint32_t type, size_t offset, uint64_t size) { - if (offset + 12 > size) { - return ERROR_MALFORMED; - } - - if (parser->readU32(offset) != 0) { - return ERROR_MALFORMED; - } - - uint32_t sampleSize = parser->readU32(offset + 4); - uint32_t sampleCount = parser->readU32(offset + 8); - - if (sampleSize == 0 && offset + 12 + sampleCount * 4 != size) { - return ERROR_MALFORMED; - } - - parser->copyBuffer(&mSampleSizes, offset, size); - - mSampleCount = sampleCount; - - return OK; -} - -status_t FragmentedMP4Parser::StaticTrackFragment::parseCompactSampleSizes( - FragmentedMP4Parser *parser, uint32_t type, size_t offset, uint64_t size) { - if (offset + 12 > size) { - return ERROR_MALFORMED; - } - - if (parser->readU32(offset) != 0) { - return ERROR_MALFORMED; - } - - uint32_t fieldSize = parser->readU32(offset + 4); - - if (fieldSize != 4 && fieldSize != 8 && fieldSize != 16) { - return ERROR_MALFORMED; - } - - uint32_t sampleCount = parser->readU32(offset + 8); - - if (offset + 12 + (sampleCount * fieldSize + 4) / 8 != size) { - return ERROR_MALFORMED; - } - - parser->copyBuffer(&mCompactSampleSizes, offset, size); - - mSampleCount = sampleCount; - - return OK; -} - -status_t FragmentedMP4Parser::StaticTrackFragment::parseSampleToChunk( - FragmentedMP4Parser *parser, uint32_t type, size_t offset, uint64_t size) { - if (offset + 8 > size) { - return ERROR_MALFORMED; - } - - if (parser->readU32(offset) != 0) { - return ERROR_MALFORMED; - } - - uint32_t entryCount = parser->readU32(offset + 4); - - if (entryCount == 0) { - return OK; - } - - if (offset + 8 + entryCount * 12 != size) { - return ERROR_MALFORMED; - } - - parser->copyBuffer(&mSampleToChunk, offset, size); - - return OK; -} - -status_t FragmentedMP4Parser::StaticTrackFragment::parseChunkOffsets( - FragmentedMP4Parser *parser, uint32_t type, size_t offset, uint64_t size) { - if (offset + 8 > size) { - return ERROR_MALFORMED; - } - - if (parser->readU32(offset) != 0) { - return ERROR_MALFORMED; - } - - uint32_t entryCount = parser->readU32(offset + 4); - - if (offset + 8 + entryCount * 4 != size) { - return ERROR_MALFORMED; - } - - parser->copyBuffer(&mChunkOffsets, offset, size); - - return OK; -} - -status_t FragmentedMP4Parser::StaticTrackFragment::parseChunkOffsets64( - FragmentedMP4Parser *parser, uint32_t type, size_t offset, uint64_t size) { - if (offset + 8 > size) { - return ERROR_MALFORMED; - } - - if (parser->readU32(offset) != 0) { - return ERROR_MALFORMED; - } - - uint32_t entryCount = parser->readU32(offset + 4); - - if (offset + 8 + entryCount * 8 != size) { - return ERROR_MALFORMED; - } - - parser->copyBuffer(&mChunkOffsets64, offset, size); - - return OK; -} - -} // namespace android - diff --git a/media/libstagefright/mp4/TrackFragment.h b/media/libstagefright/mp4/TrackFragment.h deleted file mode 100644 index e1ad46e..0000000 --- a/media/libstagefright/mp4/TrackFragment.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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. - */ - -#ifndef TRACK_FRAGMENT_H_ - -#define TRACK_FRAGMENT_H_ - -#include "include/FragmentedMP4Parser.h" - -namespace android { - -struct FragmentedMP4Parser::TrackFragment : public RefBase { - TrackFragment() {} - - virtual status_t getSample(SampleInfo *info) = 0; - virtual void advance() = 0; - - virtual status_t signalCompletion() = 0; - virtual bool complete() const = 0; - -protected: - virtual ~TrackFragment() {} - -private: - DISALLOW_EVIL_CONSTRUCTORS(TrackFragment); -}; - -struct FragmentedMP4Parser::DynamicTrackFragment : public FragmentedMP4Parser::TrackFragment { - DynamicTrackFragment(); - - virtual status_t getSample(SampleInfo *info); - virtual void advance(); - - void addSample( - off64_t dataOffset, size_t sampleSize, - uint32_t presentationTime, - size_t sampleDescIndex, - uint32_t flags); - - // No more samples will be added to this fragment. - virtual status_t signalCompletion(); - - virtual bool complete() const; - -protected: - virtual ~DynamicTrackFragment(); - -private: - bool mComplete; - size_t mSampleIndex; - Vector<SampleInfo> mSamples; - - DISALLOW_EVIL_CONSTRUCTORS(DynamicTrackFragment); -}; - -struct FragmentedMP4Parser::StaticTrackFragment : public FragmentedMP4Parser::TrackFragment { - StaticTrackFragment(); - - virtual status_t getSample(SampleInfo *info); - virtual void advance(); - - virtual status_t signalCompletion(); - virtual bool complete() const; - - status_t parseSampleSizes( - FragmentedMP4Parser *parser, uint32_t type, size_t offset, uint64_t size); - - status_t parseCompactSampleSizes( - FragmentedMP4Parser *parser, uint32_t type, size_t offset, uint64_t size); - - status_t parseSampleToChunk( - FragmentedMP4Parser *parser, uint32_t type, size_t offset, uint64_t size); - - status_t parseChunkOffsets( - FragmentedMP4Parser *parser, uint32_t type, size_t offset, uint64_t size); - - status_t parseChunkOffsets64( - FragmentedMP4Parser *parser, uint32_t type, size_t offset, uint64_t size); - -protected: - virtual ~StaticTrackFragment(); - -private: - size_t mSampleIndex; - size_t mSampleCount; - uint32_t mChunkIndex; - - SampleInfo mSampleInfo; - - sp<ABuffer> mSampleSizes; - sp<ABuffer> mCompactSampleSizes; - - sp<ABuffer> mSampleToChunk; - ssize_t mSampleToChunkIndex; - size_t mSampleToChunkRemaining; - - sp<ABuffer> mChunkOffsets; - sp<ABuffer> mChunkOffsets64; - uint32_t mPrevChunkIndex; - uint64_t mNextSampleOffset; - - void updateSampleInfo(); - - DISALLOW_EVIL_CONSTRUCTORS(StaticTrackFragment); -}; - -} // namespace android - -#endif // TRACK_FRAGMENT_H_ diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp index cb57a2f..d039f7d 100644 --- a/media/libstagefright/mpeg2ts/ATSParser.cpp +++ b/media/libstagefright/mpeg2ts/ATSParser.cpp @@ -862,7 +862,7 @@ status_t ATSParser::Stream::flush() { } void ATSParser::Stream::onPayloadData( - unsigned PTS_DTS_flags, uint64_t PTS, uint64_t DTS, + unsigned PTS_DTS_flags, uint64_t PTS, uint64_t /* DTS */, const uint8_t *data, size_t size) { #if 0 ALOGI("payload streamType 0x%02x, PTS = 0x%016llx, dPTS = %lld", @@ -1267,7 +1267,7 @@ bool ATSParser::PTSTimeDeltaEstablished() { } void ATSParser::updatePCR( - unsigned PID, uint64_t PCR, size_t byteOffsetFromStart) { + unsigned /* PID */, uint64_t PCR, size_t byteOffsetFromStart) { ALOGV("PCR 0x%016llx @ %d", PCR, byteOffsetFromStart); if (mNumPCRs == 2) { diff --git a/media/libstagefright/mpeg2ts/Android.mk b/media/libstagefright/mpeg2ts/Android.mk index c1a7a9d..c17a0b7 100644 --- a/media/libstagefright/mpeg2ts/Android.mk +++ b/media/libstagefright/mpeg2ts/Android.mk @@ -13,6 +13,8 @@ LOCAL_C_INCLUDES:= \ $(TOP)/frameworks/av/media/libstagefright \ $(TOP)/frameworks/native/include/media/openmax +LOCAL_CFLAGS += -Werror + LOCAL_MODULE:= libstagefright_mpeg2ts ifeq ($(TARGET_ARCH),arm) diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp index 52fb2a5..6dfaa94 100644 --- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp +++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp @@ -34,7 +34,8 @@ AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta) : mIsAudio(false), mFormat(NULL), mLastQueuedTimeUs(0), - mEOSResult(OK) { + mEOSResult(OK), + mLatestEnqueuedMeta(NULL) { setFormat(meta); } @@ -61,7 +62,7 @@ void AnotherPacketSource::setFormat(const sp<MetaData> &meta) { AnotherPacketSource::~AnotherPacketSource() { } -status_t AnotherPacketSource::start(MetaData *params) { +status_t AnotherPacketSource::start(MetaData * /* params */) { return OK; } @@ -182,12 +183,24 @@ void AnotherPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) { return; } - CHECK(buffer->meta()->findInt64("timeUs", &mLastQueuedTimeUs)); + int64_t lastQueuedTimeUs; + CHECK(buffer->meta()->findInt64("timeUs", &lastQueuedTimeUs)); + mLastQueuedTimeUs = lastQueuedTimeUs; ALOGV("queueAccessUnit timeUs=%lld us (%.2f secs)", mLastQueuedTimeUs, mLastQueuedTimeUs / 1E6); Mutex::Autolock autoLock(mLock); mBuffers.push_back(buffer); mCondition.signal(); + + if (!mLatestEnqueuedMeta.get()) { + mLatestEnqueuedMeta = buffer->meta(); + } else { + int64_t latestTimeUs = 0; + CHECK(mLatestEnqueuedMeta->findInt64("timeUs", &latestTimeUs)); + if (lastQueuedTimeUs > latestTimeUs) { + mLatestEnqueuedMeta = buffer->meta(); + } + } } void AnotherPacketSource::clear() { @@ -197,6 +210,7 @@ void AnotherPacketSource::clear() { mEOSResult = OK; mFormat = NULL; + mLatestEnqueuedMeta = NULL; } void AnotherPacketSource::queueDiscontinuity( @@ -221,6 +235,7 @@ void AnotherPacketSource::queueDiscontinuity( mEOSResult = OK; mLastQueuedTimeUs = 0; + mLatestEnqueuedMeta = NULL; sp<ABuffer> buffer = new ABuffer(0); buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type)); @@ -308,4 +323,9 @@ bool AnotherPacketSource::isFinished(int64_t duration) const { return (mEOSResult != OK); } +sp<AMessage> AnotherPacketSource::getLatestMeta() { + Mutex::Autolock autoLock(mLock); + return mLatestEnqueuedMeta; +} + } // namespace android diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h index e16cf78..9b193a2 100644 --- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h +++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h @@ -62,6 +62,8 @@ struct AnotherPacketSource : public MediaSource { bool isFinished(int64_t duration) const; + sp<AMessage> getLatestMeta(); + protected: virtual ~AnotherPacketSource(); @@ -74,6 +76,7 @@ private: int64_t mLastQueuedTimeUs; List<sp<ABuffer> > mBuffers; status_t mEOSResult; + sp<AMessage> mLatestEnqueuedMeta; bool wasFormatChange(int32_t discontinuityType) const; diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp index 5c7e741..c0c9717 100644 --- a/media/libstagefright/mpeg2ts/ESQueue.cpp +++ b/media/libstagefright/mpeg2ts/ESQueue.cpp @@ -60,7 +60,7 @@ void ElementaryStreamQueue::clear(bool clearFormat) { // update metadata only applicable, and return the payload size static unsigned parseAC3SyncFrame( const uint8_t *ptr, size_t size, sp<MetaData> *metaData) { - static const unsigned channelCountTable[] = {2, 1, 2, 3, 4, 4, 5, 6}; + static const unsigned channelCountTable[] = {2, 1, 2, 3, 3, 4, 4, 5}; static const unsigned samplingRateTable[] = {48000, 44100, 32000}; static const unsigned rates[] = {32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640}; diff --git a/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp index dd714c9..bc2a16d 100644 --- a/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp +++ b/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp @@ -130,7 +130,8 @@ sp<MediaSource> MPEG2PSExtractor::getTrack(size_t index) { return new WrappedTrack(this, mTracks.valueAt(index)); } -sp<MetaData> MPEG2PSExtractor::getTrackMetaData(size_t index, uint32_t flags) { +sp<MetaData> MPEG2PSExtractor::getTrackMetaData( + size_t index, uint32_t /* flags */) { if (index >= mTracks.size()) { return NULL; } @@ -625,7 +626,7 @@ status_t MPEG2PSExtractor::Track::read( status_t MPEG2PSExtractor::Track::appendPESData( unsigned PTS_DTS_flags, - uint64_t PTS, uint64_t DTS, + uint64_t PTS, uint64_t /* DTS */, const uint8_t *data, size_t size) { if (mQueue == NULL) { return OK; diff --git a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp index d449c34..35ca118 100644 --- a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp +++ b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp @@ -141,7 +141,7 @@ sp<MediaSource> MPEG2TSExtractor::getTrack(size_t index) { } sp<MetaData> MPEG2TSExtractor::getTrackMetaData( - size_t index, uint32_t flags) { + size_t index, uint32_t /* flags */) { return index < mSourceImpls.size() ? mSourceImpls.editItemAt(index)->getFormat() : NULL; } diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp index 83f4e0a..b81b116 100644 --- a/media/libstagefright/omx/GraphicBufferSource.cpp +++ b/media/libstagefright/omx/GraphicBufferSource.cpp @@ -41,11 +41,11 @@ GraphicBufferSource::GraphicBufferSource(OMXNodeInstance* nodeInstance, mNumFramesAvailable(0), mEndOfStream(false), mEndOfStreamSent(false), - mRepeatAfterUs(-1ll), mMaxTimestampGapUs(-1ll), mPrevOriginalTimeUs(-1ll), mPrevModifiedTimeUs(-1ll), mSkipFramesBeforeNs(-1ll), + mRepeatAfterUs(-1ll), mRepeatLastFrameGeneration(0), mRepeatLastFrameTimestamp(-1ll), mLatestSubmittedBufferId(-1), diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp index 274f2eb..a608479 100644 --- a/media/libstagefright/omx/OMX.cpp +++ b/media/libstagefright/omx/OMX.cpp @@ -185,7 +185,7 @@ void OMX::binderDied(const wp<IBinder> &the_late_who) { instance->onObserverDied(mMaster); } -bool OMX::livesLocally(node_id node, pid_t pid) { +bool OMX::livesLocally(node_id /* node */, pid_t pid) { return pid == getpid(); } @@ -424,7 +424,7 @@ OMX_ERRORTYPE OMX::OnEvent( OMX_IN OMX_EVENTTYPE eEvent, OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2, - OMX_IN OMX_PTR pEventData) { + OMX_IN OMX_PTR /* pEventData */) { ALOGV("OnEvent(%d, %ld, %ld)", eEvent, nData1, nData2); // Forward to OMXNodeInstance. diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp index f3600ba..0fb38fa 100644 --- a/media/libstagefright/omx/OMXNodeInstance.cpp +++ b/media/libstagefright/omx/OMXNodeInstance.cpp @@ -266,7 +266,7 @@ status_t OMXNodeInstance::sendCommand( } status_t OMXNodeInstance::getParameter( - OMX_INDEXTYPE index, void *params, size_t size) { + OMX_INDEXTYPE index, void *params, size_t /* size */) { Mutex::Autolock autoLock(mLock); OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params); @@ -275,7 +275,7 @@ status_t OMXNodeInstance::getParameter( } status_t OMXNodeInstance::setParameter( - OMX_INDEXTYPE index, const void *params, size_t size) { + OMX_INDEXTYPE index, const void *params, size_t /* size */) { Mutex::Autolock autoLock(mLock); OMX_ERRORTYPE err = OMX_SetParameter( @@ -285,7 +285,7 @@ status_t OMXNodeInstance::setParameter( } status_t OMXNodeInstance::getConfig( - OMX_INDEXTYPE index, void *params, size_t size) { + OMX_INDEXTYPE index, void *params, size_t /* size */) { Mutex::Autolock autoLock(mLock); OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params); @@ -293,7 +293,7 @@ status_t OMXNodeInstance::getConfig( } status_t OMXNodeInstance::setConfig( - OMX_INDEXTYPE index, const void *params, size_t size) { + OMX_INDEXTYPE index, const void *params, size_t /* size */) { Mutex::Autolock autoLock(mLock); OMX_ERRORTYPE err = OMX_SetConfig( @@ -610,7 +610,7 @@ status_t OMXNodeInstance::useGraphicBuffer( } status_t OMXNodeInstance::updateGraphicBufferInMeta( - OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer, + OMX_U32 /* portIndex */, const sp<GraphicBuffer>& graphicBuffer, OMX::buffer_id buffer) { Mutex::Autolock autoLock(mLock); @@ -978,7 +978,7 @@ void OMXNodeInstance::onEvent( // static OMX_ERRORTYPE OMXNodeInstance::OnEvent( - OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_HANDLETYPE /* hComponent */, OMX_IN OMX_PTR pAppData, OMX_IN OMX_EVENTTYPE eEvent, OMX_IN OMX_U32 nData1, @@ -994,7 +994,7 @@ OMX_ERRORTYPE OMXNodeInstance::OnEvent( // static OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone( - OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_HANDLETYPE /* hComponent */, OMX_IN OMX_PTR pAppData, OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); @@ -1006,7 +1006,7 @@ OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone( // static OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone( - OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_HANDLETYPE /* hComponent */, OMX_IN OMX_PTR pAppData, OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); diff --git a/media/libstagefright/omx/SoftOMXComponent.cpp b/media/libstagefright/omx/SoftOMXComponent.cpp index b1c34dc..646cd32 100644 --- a/media/libstagefright/omx/SoftOMXComponent.cpp +++ b/media/libstagefright/omx/SoftOMXComponent.cpp @@ -257,69 +257,69 @@ OMX_ERRORTYPE SoftOMXComponent::GetStateWrapper( //////////////////////////////////////////////////////////////////////////////// OMX_ERRORTYPE SoftOMXComponent::sendCommand( - OMX_COMMANDTYPE cmd, OMX_U32 param, OMX_PTR data) { + OMX_COMMANDTYPE /* cmd */, OMX_U32 /* param */, OMX_PTR /* data */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::getParameter( - OMX_INDEXTYPE index, OMX_PTR params) { + OMX_INDEXTYPE /* index */, OMX_PTR /* params */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::setParameter( - OMX_INDEXTYPE index, const OMX_PTR params) { + OMX_INDEXTYPE /* index */, const OMX_PTR /* params */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::getConfig( - OMX_INDEXTYPE index, OMX_PTR params) { + OMX_INDEXTYPE /* index */, OMX_PTR /* params */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::setConfig( - OMX_INDEXTYPE index, const OMX_PTR params) { + OMX_INDEXTYPE /* index */, const OMX_PTR /* params */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::getExtensionIndex( - const char *name, OMX_INDEXTYPE *index) { + const char * /* name */, OMX_INDEXTYPE * /* index */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::useBuffer( - OMX_BUFFERHEADERTYPE **buffer, - OMX_U32 portIndex, - OMX_PTR appPrivate, - OMX_U32 size, - OMX_U8 *ptr) { + OMX_BUFFERHEADERTYPE ** /* buffer */, + OMX_U32 /* portIndex */, + OMX_PTR /* appPrivate */, + OMX_U32 /* size */, + OMX_U8 * /* ptr */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::allocateBuffer( - OMX_BUFFERHEADERTYPE **buffer, - OMX_U32 portIndex, - OMX_PTR appPrivate, - OMX_U32 size) { + OMX_BUFFERHEADERTYPE ** /* buffer */, + OMX_U32 /* portIndex */, + OMX_PTR /* appPrivate */, + OMX_U32 /* size */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::freeBuffer( - OMX_U32 portIndex, - OMX_BUFFERHEADERTYPE *buffer) { + OMX_U32 /* portIndex */, + OMX_BUFFERHEADERTYPE * /* buffer */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::emptyThisBuffer( - OMX_BUFFERHEADERTYPE *buffer) { + OMX_BUFFERHEADERTYPE * /* buffer */) { return OMX_ErrorUndefined; } OMX_ERRORTYPE SoftOMXComponent::fillThisBuffer( - OMX_BUFFERHEADERTYPE *buffer) { + OMX_BUFFERHEADERTYPE * /* buffer */) { return OMX_ErrorUndefined; } -OMX_ERRORTYPE SoftOMXComponent::getState(OMX_STATETYPE *state) { +OMX_ERRORTYPE SoftOMXComponent::getState(OMX_STATETYPE * /* state */) { return OMX_ErrorUndefined; } diff --git a/media/libstagefright/omx/SoftOMXPlugin.cpp b/media/libstagefright/omx/SoftOMXPlugin.cpp index d6cde73..d49e50b 100644 --- a/media/libstagefright/omx/SoftOMXPlugin.cpp +++ b/media/libstagefright/omx/SoftOMXPlugin.cpp @@ -154,7 +154,7 @@ OMX_ERRORTYPE SoftOMXPlugin::destroyComponentInstance( OMX_ERRORTYPE SoftOMXPlugin::enumerateComponents( OMX_STRING name, - size_t size, + size_t /* size */, OMX_U32 index) { if (index >= kNumComponents) { return OMX_ErrorNoMore; diff --git a/media/libstagefright/omx/tests/Android.mk b/media/libstagefright/omx/tests/Android.mk index 1061c39..8b79af4 100644 --- a/media/libstagefright/omx/tests/Android.mk +++ b/media/libstagefright/omx/tests/Android.mk @@ -11,6 +11,8 @@ LOCAL_C_INCLUDES := \ $(TOP)/frameworks/av/media/libstagefright \ $(TOP)/frameworks/native/include/media/openmax +LOCAL_CFLAGS += -Werror + LOCAL_MODULE := omx_tests LOCAL_MODULE_TAGS := tests diff --git a/media/libstagefright/rtsp/AMPEG2TSAssembler.cpp b/media/libstagefright/rtsp/AMPEG2TSAssembler.cpp index 4c9bf5b..dca5c89 100644 --- a/media/libstagefright/rtsp/AMPEG2TSAssembler.cpp +++ b/media/libstagefright/rtsp/AMPEG2TSAssembler.cpp @@ -34,7 +34,9 @@ namespace android { AMPEG2TSAssembler::AMPEG2TSAssembler( - const sp<AMessage> ¬ify, const char *desc, const AString ¶ms) + const sp<AMessage> ¬ify, + const char * /* desc */, + const AString & /* params */) : mNotifyMsg(notify), mNextExpectedSeqNoValid(false), mNextExpectedSeqNo(0) { diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp index 0d07043..c46d16f 100644 --- a/media/libstagefright/rtsp/ARTPWriter.cpp +++ b/media/libstagefright/rtsp/ARTPWriter.cpp @@ -114,7 +114,7 @@ bool ARTPWriter::reachedEOS() { return (mFlags & kFlagEOS) != 0; } -status_t ARTPWriter::start(MetaData *params) { +status_t ARTPWriter::start(MetaData * /* params */) { Mutex::Autolock autoLock(mLock); if (mFlags & kFlagStarted) { return INVALID_OPERATION; diff --git a/media/libstagefright/rtsp/ARawAudioAssembler.cpp b/media/libstagefright/rtsp/ARawAudioAssembler.cpp index 0da5dd2..167f7a4 100644 --- a/media/libstagefright/rtsp/ARawAudioAssembler.cpp +++ b/media/libstagefright/rtsp/ARawAudioAssembler.cpp @@ -34,7 +34,9 @@ namespace android { ARawAudioAssembler::ARawAudioAssembler( - const sp<AMessage> ¬ify, const char *desc, const AString ¶ms) + const sp<AMessage> ¬ify, + const char * /* desc */, + const AString & /* params */) : mNotifyMsg(notify), mNextExpectedSeqNoValid(false), mNextExpectedSeqNo(0) { diff --git a/media/libstagefright/rtsp/Android.mk b/media/libstagefright/rtsp/Android.mk index 02e44f4..39eedc0 100644 --- a/media/libstagefright/rtsp/Android.mk +++ b/media/libstagefright/rtsp/Android.mk @@ -30,6 +30,8 @@ ifeq ($(TARGET_ARCH),arm) LOCAL_CFLAGS += -Wno-psabi endif +LOCAL_CFLAGS += -Werror + include $(BUILD_STATIC_LIBRARY) ################################################################################ diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h index cd77aa0..45470a3 100644 --- a/media/libstagefright/rtsp/MyHandler.h +++ b/media/libstagefright/rtsp/MyHandler.h @@ -19,7 +19,11 @@ #define MY_HANDLER_H_ //#define LOG_NDEBUG 0 + +#ifndef LOG_TAG #define LOG_TAG "MyHandler" +#endif + #include <utils/Log.h> #include "APacketSource.h" @@ -42,6 +46,12 @@ #include "HTTPBase.h" +#if LOG_NDEBUG +#define UNUSED_UNLESS_VERBOSE(x) (void)(x) +#else +#define UNUSED_UNLESS_VERBOSE(x) +#endif + // If no access units are received within 5 secs, assume that the rtp // stream has ended and signal end of stream. static int64_t kAccessUnitTimeoutUs = 10000000ll; @@ -178,7 +188,7 @@ struct MyHandler : public AHandler { mConn->connect(mOriginalSessionURL.c_str(), reply); } - AString getControlURL(sp<ASessionDescription> desc) { + AString getControlURL() { AString sessionLevelControlURL; if (mSessionDesc->findAttribute( 0, @@ -545,7 +555,7 @@ struct MyHandler : public AHandler { mBaseURL = tmp; } - mControlURL = getControlURL(mSessionDesc); + mControlURL = getControlURL(); if (mSessionDesc->countTracks() < 2) { // There's no actual tracks in this session. @@ -591,7 +601,7 @@ struct MyHandler : public AHandler { mSeekable = !isLiveStream(mSessionDesc); - mControlURL = getControlURL(mSessionDesc); + mControlURL = getControlURL(); if (mSessionDesc->countTracks() < 2) { // There's no actual tracks in this session. @@ -1805,6 +1815,8 @@ private: bool addMediaTimestamp( int32_t trackIndex, const TrackInfo *track, const sp<ABuffer> &accessUnit) { + UNUSED_UNLESS_VERBOSE(trackIndex); + uint32_t rtpTime; CHECK(accessUnit->meta()->findInt32( "rtp-time", (int32_t *)&rtpTime)); diff --git a/media/libstagefright/tests/SurfaceMediaSource_test.cpp b/media/libstagefright/tests/SurfaceMediaSource_test.cpp index ddedad7..aeecdbc 100644 --- a/media/libstagefright/tests/SurfaceMediaSource_test.cpp +++ b/media/libstagefright/tests/SurfaceMediaSource_test.cpp @@ -527,7 +527,8 @@ void SurfaceMediaSourceTest::oneBufferPass(int width, int height ) { } // Dequeuing and queuing the buffer without really filling it in. -void SurfaceMediaSourceTest::oneBufferPassNoFill(int width, int height ) { +void SurfaceMediaSourceTest::oneBufferPassNoFill( + int /* width */, int /* height */) { ANativeWindowBuffer* anb; ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); ASSERT_TRUE(anb != NULL); diff --git a/media/libstagefright/timedtext/Android.mk b/media/libstagefright/timedtext/Android.mk index f099bbd..6a8b9fc 100644 --- a/media/libstagefright/timedtext/Android.mk +++ b/media/libstagefright/timedtext/Android.mk @@ -9,7 +9,8 @@ LOCAL_SRC_FILES:= \ TimedTextSRTSource.cpp \ TimedTextPlayer.cpp -LOCAL_CFLAGS += -Wno-multichar +LOCAL_CFLAGS += -Wno-multichar -Werror + LOCAL_C_INCLUDES:= \ $(TOP)/frameworks/av/include/media/stagefright/timedtext \ $(TOP)/frameworks/av/media/libstagefright diff --git a/media/libstagefright/timedtext/TimedTextDriver.cpp b/media/libstagefright/timedtext/TimedTextDriver.cpp index 05d6d02..71aa21e 100644 --- a/media/libstagefright/timedtext/TimedTextDriver.cpp +++ b/media/libstagefright/timedtext/TimedTextDriver.cpp @@ -45,6 +45,7 @@ TimedTextDriver::TimedTextDriver( const sp<IMediaHTTPService> &httpService) : mLooper(new ALooper), mListener(listener), + mHTTPService(httpService), mState(UNINITIALIZED), mCurrentTrackIndex(UINT_MAX) { mLooper->setName("TimedTextDriver"); diff --git a/media/libstagefright/timedtext/TimedTextSource.h b/media/libstagefright/timedtext/TimedTextSource.h index 756cc31..8c1c1cd 100644 --- a/media/libstagefright/timedtext/TimedTextSource.h +++ b/media/libstagefright/timedtext/TimedTextSource.h @@ -47,7 +47,7 @@ class TimedTextSource : public RefBase { int64_t *endTimeUs, Parcel *parcel, const MediaSource::ReadOptions *options = NULL) = 0; - virtual status_t extractGlobalDescriptions(Parcel *parcel) { + virtual status_t extractGlobalDescriptions(Parcel * /* parcel */) { return INVALID_OPERATION; } virtual sp<MetaData> getFormat(); diff --git a/media/libstagefright/wifi-display/rtp/RTPSender.cpp b/media/libstagefright/wifi-display/rtp/RTPSender.cpp index 1887b8b..e88a3bd 100644 --- a/media/libstagefright/wifi-display/rtp/RTPSender.cpp +++ b/media/libstagefright/wifi-display/rtp/RTPSender.cpp @@ -685,9 +685,8 @@ status_t RTPSender::onRTCPData(const sp<ABuffer> &buffer) { return OK; } -status_t RTPSender::parseReceiverReport(const uint8_t *data, size_t size) { - // hexdump(data, size); - +status_t RTPSender::parseReceiverReport( + const uint8_t *data, size_t /* size */) { float fractionLost = data[12] / 256.0f; ALOGI("lost %.2f %% of packets during report interval.", diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp index 05e4018..da405e2 100644 --- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp +++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp @@ -746,7 +746,7 @@ status_t WifiDisplaySource::sendM16(int32_t sessionID) { } status_t WifiDisplaySource::onReceiveM1Response( - int32_t sessionID, const sp<ParsedMessage> &msg) { + int32_t /* sessionID */, const sp<ParsedMessage> &msg) { int32_t statusCode; if (!msg->getStatusCode(&statusCode)) { return ERROR_MALFORMED; @@ -991,7 +991,7 @@ status_t WifiDisplaySource::onReceiveM4Response( } status_t WifiDisplaySource::onReceiveM5Response( - int32_t sessionID, const sp<ParsedMessage> &msg) { + int32_t /* sessionID */, const sp<ParsedMessage> &msg) { int32_t statusCode; if (!msg->getStatusCode(&statusCode)) { return ERROR_MALFORMED; @@ -1005,7 +1005,7 @@ status_t WifiDisplaySource::onReceiveM5Response( } status_t WifiDisplaySource::onReceiveM16Response( - int32_t sessionID, const sp<ParsedMessage> &msg) { + int32_t sessionID, const sp<ParsedMessage> & /* msg */) { // If only the response was required to include a "Session:" header... CHECK_EQ(sessionID, mClientSessionID); @@ -1680,7 +1680,7 @@ WifiDisplaySource::HDCPObserver::HDCPObserver( } void WifiDisplaySource::HDCPObserver::notify( - int msg, int ext1, int ext2, const Parcel *obj) { + int msg, int ext1, int ext2, const Parcel * /* obj */) { sp<AMessage> notify = mNotify->dup(); notify->setInt32("msg", msg); notify->setInt32("ext1", ext1); diff --git a/media/libstagefright/yuv/Android.mk b/media/libstagefright/yuv/Android.mk index b3f7b1b..bb86dfc 100644 --- a/media/libstagefright/yuv/Android.mk +++ b/media/libstagefright/yuv/Android.mk @@ -12,5 +12,7 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_MODULE:= libstagefright_yuv +LOCAL_CFLAGS += -Werror + include $(BUILD_SHARED_LIBRARY) diff --git a/media/libstagefright/yuv/YUVImage.cpp b/media/libstagefright/yuv/YUVImage.cpp index 7b9000b..bb3e2fd 100644 --- a/media/libstagefright/yuv/YUVImage.cpp +++ b/media/libstagefright/yuv/YUVImage.cpp @@ -226,8 +226,8 @@ void YUVImage::fastCopyRectangle420Planar( &ySrcOffsetIncrement, &uSrcOffsetIncrement, &vSrcOffsetIncrement); int32_t yDestOffsetIncrement; - int32_t uDestOffsetIncrement; - int32_t vDestOffsetIncrement; + int32_t uDestOffsetIncrement = 0; + int32_t vDestOffsetIncrement = 0; destImage.getOffsetIncrementsPerDataRow( &yDestOffsetIncrement, &uDestOffsetIncrement, &vDestOffsetIncrement); @@ -309,7 +309,7 @@ void YUVImage::fastCopyRectangle420SemiPlanar( int32_t yDestOffsetIncrement; int32_t uDestOffsetIncrement; - int32_t vDestOffsetIncrement; + int32_t vDestOffsetIncrement = 0; destImage.getOffsetIncrementsPerDataRow( &yDestOffsetIncrement, &uDestOffsetIncrement, &vDestOffsetIncrement); @@ -393,9 +393,9 @@ bool YUVImage::writeToPPM(const char *filename) const { fprintf(fp, "255\n"); for (int32_t y = 0; y < mHeight; ++y) { for (int32_t x = 0; x < mWidth; ++x) { - uint8_t yValue; - uint8_t uValue; - uint8_t vValue; + uint8_t yValue = 0u; + uint8_t uValue = 0u; + uint8_t vValue = 0u; getPixelValue(x, y, &yValue, &uValue, & vValue); uint8_t rValue; diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 21bd2f4..7615086 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -183,6 +183,7 @@ AudioFlinger::AudioFlinger() (void) property_get("af.tee", value, "0"); teeEnabled = atoi(value); } + // FIXME symbolic constants here if (teeEnabled & 1) { mTeeSinkInputEnabled = true; } @@ -1810,7 +1811,7 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module, kind = TEE_SINK_NEW; } else if (mRecordTeeSink->getStrongCount() != 1) { kind = TEE_SINK_NO; - } else if (format == mRecordTeeSink->format()) { + } else if (Format_isEqual(format, mRecordTeeSink->format())) { kind = TEE_SINK_OLD; } else { kind = TEE_SINK_NEW; @@ -1847,8 +1848,6 @@ audio_io_handle_t AudioFlinger::openInput(audio_module_handle_t module, // pre processing modules RecordThread *thread = new RecordThread(this, input, - reqSamplingRate, - reqChannelMask, id, primaryOutputDevice_l(), *pDevices @@ -1929,18 +1928,21 @@ int AudioFlinger::newAudioSessionId() return nextUniqueId(); } -void AudioFlinger::acquireAudioSessionId(int audioSession) +void AudioFlinger::acquireAudioSessionId(int audioSession, pid_t pid) { Mutex::Autolock _l(mLock); pid_t caller = IPCThreadState::self()->getCallingPid(); - ALOGV("acquiring %d from %d", audioSession, caller); + ALOGV("acquiring %d from %d, for %d", audioSession, caller, pid); + if (pid != -1 && (caller == getpid_cached)) { + caller = pid; + } // Ignore requests received from processes not known as notification client. The request // is likely proxied by mediaserver (e.g CameraService) and releaseAudioSessionId() can be // called from a different pid leaving a stale session reference. Also we don't know how // to clear this reference if the client process dies. if (mNotificationClients.indexOfKey(caller) < 0) { - ALOGV("acquireAudioSessionId() unknown client %d for session %d", caller, audioSession); + ALOGW("acquireAudioSessionId() unknown client %d for session %d", caller, audioSession); return; } @@ -1957,11 +1959,14 @@ void AudioFlinger::acquireAudioSessionId(int audioSession) ALOGV(" added new entry for %d", audioSession); } -void AudioFlinger::releaseAudioSessionId(int audioSession) +void AudioFlinger::releaseAudioSessionId(int audioSession, pid_t pid) { Mutex::Autolock _l(mLock); pid_t caller = IPCThreadState::self()->getCallingPid(); - ALOGV("releasing %d from %d", audioSession, caller); + ALOGV("releasing %d from %d for %d", audioSession, caller, pid); + if (pid != -1 && (caller == getpid_cached)) { + caller = pid; + } size_t num = mAudioSessionRefs.size(); for (size_t i = 0; i< num; i++) { AudioSessionRef *ref = mAudioSessionRefs.itemAt(i); @@ -2090,7 +2095,7 @@ sp<AudioFlinger::SyncEvent> AudioFlinger::createSyncEvent(AudioSystem::sync_even int triggerSession, int listenerSession, sync_event_callback_t callBack, - void *cookie) + wp<RefBase> cookie) { Mutex::Autolock _l(mLock); diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index 459d2ec..21d05d4 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -193,9 +193,9 @@ public: virtual int newAudioSessionId(); - virtual void acquireAudioSessionId(int audioSession); + virtual void acquireAudioSessionId(int audioSession, pid_t pid); - virtual void releaseAudioSessionId(int audioSession); + virtual void releaseAudioSessionId(int audioSession, pid_t pid); virtual status_t queryNumberEffects(uint32_t *numEffects) const; @@ -253,7 +253,7 @@ public: int triggerSession, int listenerSession, sync_event_callback_t callBack, - void *cookie) + wp<RefBase> cookie) : mType(type), mTriggerSession(triggerSession), mListenerSession(listenerSession), mCallback(callBack), mCookie(cookie) {} @@ -266,14 +266,14 @@ public: AudioSystem::sync_event_t type() const { return mType; } int triggerSession() const { return mTriggerSession; } int listenerSession() const { return mListenerSession; } - void *cookie() const { return mCookie; } + wp<RefBase> cookie() const { return mCookie; } private: const AudioSystem::sync_event_t mType; const int mTriggerSession; const int mListenerSession; sync_event_callback_t mCallback; - void * const mCookie; + const wp<RefBase> mCookie; mutable Mutex mLock; }; @@ -281,7 +281,7 @@ public: int triggerSession, int listenerSession, sync_event_callback_t callBack, - void *cookie); + wp<RefBase> cookie); private: class AudioHwDevice; // fwd declaration for findSuitableHwDev_l @@ -638,7 +638,7 @@ public: // 0x200000 stereo 16-bit PCM frames = 47.5 seconds at 44.1 kHz, 8 megabytes static const size_t kTeeSinkInputFramesDefault = 0x200000; static const size_t kTeeSinkOutputFramesDefault = 0x200000; - static const size_t kTeeSinkTrackFramesDefault = 0x1000; + static const size_t kTeeSinkTrackFramesDefault = 0x200000; #endif // This method reads from a variable without mLock, but the variable is updated under mLock. So diff --git a/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp index b206116..ca98f16 100644 --- a/services/audioflinger/AudioResampler.cpp +++ b/services/audioflinger/AudioResampler.cpp @@ -341,7 +341,7 @@ void AudioResamplerOrder1::resampleStereo16(int32_t* out, size_t outFrameCount, uint32_t phaseIncrement = mPhaseIncrement; size_t outputIndex = 0; size_t outputSampleCount = outFrameCount * 2; - size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; + size_t inFrameCount = getInFrameCountRequired(outFrameCount); // ALOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d", // outFrameCount, inputIndex, phaseFraction, phaseIncrement); @@ -439,7 +439,7 @@ void AudioResamplerOrder1::resampleMono16(int32_t* out, size_t outFrameCount, uint32_t phaseIncrement = mPhaseIncrement; size_t outputIndex = 0; size_t outputSampleCount = outFrameCount * 2; - size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; + size_t inFrameCount = getInFrameCountRequired(outFrameCount); // ALOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d", // outFrameCount, inputIndex, phaseFraction, phaseIncrement); diff --git a/services/audioflinger/AudioResampler.h b/services/audioflinger/AudioResampler.h index dc33f29..0592855 100644 --- a/services/audioflinger/AudioResampler.h +++ b/services/audioflinger/AudioResampler.h @@ -110,6 +110,38 @@ protected: uint64_t mLocalTimeFreq; int64_t mPTS; + // returns the inFrameCount required to generate outFrameCount frames. + // + // Placed here to be a consistent for all resamplers. + // + // Right now, we use the upper bound without regards to the current state of the + // input buffer using integer arithmetic, as follows: + // + // (static_cast<uint64_t>(outFrameCount)*mInSampleRate + (mSampleRate - 1))/mSampleRate; + // + // The double precision equivalent (float may not be precise enough): + // ceil(static_cast<double>(outFrameCount) * mInSampleRate / mSampleRate); + // + // this relies on the fact that the mPhaseIncrement is rounded down from + // #phases * mInSampleRate/mSampleRate and the fact that Sum(Floor(x)) <= Floor(Sum(x)). + // http://www.proofwiki.org/wiki/Sum_of_Floors_Not_Greater_Than_Floor_of_Sums + // + // (so long as double precision is computed accurately enough to be considered + // greater than or equal to the Floor(x) value in int32_t arithmetic; thus this + // will not necessarily hold for floats). + // + // TODO: + // Greater accuracy and a tight bound is obtained by: + // 1) subtract and adjust for the current state of the AudioBufferProvider buffer. + // 2) using the exact integer formula where (ignoring 64b casting) + // inFrameCount = (mPhaseIncrement * (outFrameCount - 1) + mPhaseFraction) / phaseWrapLimit; + // phaseWrapLimit is the wraparound (1 << kNumPhaseBits), if not specified explicitly. + // + inline size_t getInFrameCountRequired(size_t outFrameCount) { + return (static_cast<uint64_t>(outFrameCount)*mInSampleRate + + (mSampleRate - 1))/mSampleRate; + } + private: const src_quality mQuality; diff --git a/services/audioflinger/AudioResamplerCubic.cpp b/services/audioflinger/AudioResamplerCubic.cpp index 1f9714b..8f14ff9 100644 --- a/services/audioflinger/AudioResamplerCubic.cpp +++ b/services/audioflinger/AudioResamplerCubic.cpp @@ -60,7 +60,7 @@ void AudioResamplerCubic::resampleStereo16(int32_t* out, size_t outFrameCount, uint32_t phaseIncrement = mPhaseIncrement; size_t outputIndex = 0; size_t outputSampleCount = outFrameCount * 2; - size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; + size_t inFrameCount = getInFrameCountRequired(outFrameCount); // fetch first buffer if (mBuffer.frameCount == 0) { @@ -128,7 +128,7 @@ void AudioResamplerCubic::resampleMono16(int32_t* out, size_t outFrameCount, uint32_t phaseIncrement = mPhaseIncrement; size_t outputIndex = 0; size_t outputSampleCount = outFrameCount * 2; - size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; + size_t inFrameCount = getInFrameCountRequired(outFrameCount); // fetch first buffer if (mBuffer.frameCount == 0) { diff --git a/services/audioflinger/AudioResamplerDyn.cpp b/services/audioflinger/AudioResamplerDyn.cpp index cd67df5..939b128 100644 --- a/services/audioflinger/AudioResamplerDyn.cpp +++ b/services/audioflinger/AudioResamplerDyn.cpp @@ -283,17 +283,25 @@ void AudioResamplerDyn::setSampleRate(int32_t inSampleRate) { // 32b coefficients, 64 length useS32 = true; stopBandAtten = 98.; - halfLength = 32; + if (inSampleRate >= mSampleRate * 4) { + halfLength = 48; + } else if (inSampleRate >= mSampleRate * 2) { + halfLength = 40; + } else { + halfLength = 32; + } } else if (mFilterQuality == DYN_LOW_QUALITY) { // 16b coefficients, 16-32 length useS32 = false; stopBandAtten = 80.; - if (mSampleRate >= inSampleRate * 2) { + if (inSampleRate >= mSampleRate * 4) { + halfLength = 24; + } else if (inSampleRate >= mSampleRate * 2) { halfLength = 16; } else { halfLength = 8; } - if (mSampleRate >= inSampleRate) { + if (inSampleRate <= mSampleRate) { tbwCheat = 1.05; } else { tbwCheat = 1.03; @@ -303,14 +311,14 @@ void AudioResamplerDyn::setSampleRate(int32_t inSampleRate) { // note: > 64 length filters with 16b coefs can have quantization noise problems useS32 = false; stopBandAtten = 84.; - if (mSampleRate >= inSampleRate * 4) { + if (inSampleRate >= mSampleRate * 4) { halfLength = 32; - } else if (mSampleRate >= inSampleRate * 2) { + } else if (inSampleRate >= mSampleRate * 2) { halfLength = 24; } else { halfLength = 16; } - if (mSampleRate >= inSampleRate) { + if (inSampleRate <= mSampleRate) { tbwCheat = 1.03; } else { tbwCheat = 1.01; @@ -458,7 +466,7 @@ void AudioResamplerDyn::resample(int32_t* out, size_t outFrameCount, const uint32_t phaseIncrement = mPhaseIncrement; size_t outputIndex = 0; size_t outputSampleCount = outFrameCount * 2; // stereo output - size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; + size_t inFrameCount = getInFrameCountRequired(outFrameCount); const uint32_t phaseWrapLimit = c.mL << c.mShift; // NOTE: be very careful when modifying the code here. register diff --git a/services/audioflinger/AudioResamplerSinc.cpp b/services/audioflinger/AudioResamplerSinc.cpp index 207f26b..d0a7a58 100644 --- a/services/audioflinger/AudioResamplerSinc.cpp +++ b/services/audioflinger/AudioResamplerSinc.cpp @@ -540,7 +540,7 @@ void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount, uint32_t phaseIncrement = mPhaseIncrement; size_t outputIndex = 0; size_t outputSampleCount = outFrameCount * 2; - size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; + size_t inFrameCount = getInFrameCountRequired(outFrameCount); while (outputIndex < outputSampleCount) { // buffer is empty, fetch a new one diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h index fc3171f..3ec9889 100644 --- a/services/audioflinger/RecordTracks.h +++ b/services/audioflinger/RecordTracks.h @@ -47,6 +47,9 @@ public: static void appendDumpHeader(String8& result); void dump(char* buffer, size_t size, bool active); + void handleSyncStartEvent(const sp<SyncEvent>& event); + void clearSyncStartEvent(); + private: friend class AudioFlinger; // for mState @@ -59,4 +62,33 @@ private: // releaseBuffer() not overridden bool mOverflow; // overflow on most recent attempt to fill client buffer + + // updated by RecordThread::readInputParameters_l() + AudioResampler *mResampler; + + // interleaved stereo pairs of fixed-point signed Q19.12 + int32_t *mRsmpOutBuffer; + // current allocated frame count for the above, which may be larger than needed + size_t mRsmpOutFrameCount; + + size_t mRsmpInUnrel; // unreleased frames remaining from + // most recent getNextBuffer + // for debug only + + // rolling counter that is never cleared + int32_t mRsmpInFront; // next available frame + + AudioBufferProvider::Buffer mSink; // references client's buffer sink in shared memory + + // sync event triggering actual audio capture. Frames read before this event will + // be dropped and therefore not read by the application. + sp<SyncEvent> mSyncStartEvent; + + // number of captured frames to drop after the start sync event has been received. + // when < 0, maximum frames to drop before starting capture even if sync event is + // not received + ssize_t mFramesToDrop; + + // used by resampler to find source frames + ResamplerBufferProvider *mResamplerBufferProvider; }; diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index b064e89..3e8c133 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -274,7 +274,8 @@ AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio mType(type), mAudioFlinger(audioFlinger), // mSampleRate, mFrameCount, mChannelMask, mChannelCount, mFrameSize, mFormat, mBufferSize - // are set by PlaybackThread::readOutputParameters() or RecordThread::readInputParameters() + // are set by PlaybackThread::readOutputParameters_l() or + // RecordThread::readInputParameters_l() mParamStatus(NO_ERROR), //FIXME: mStandby should be true here. Is this some kind of hack? mStandby(false), mOutDevice(outDevice), mInDevice(inDevice), @@ -1108,7 +1109,7 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge } } - readOutputParameters(); + readOutputParameters_l(); // mStreamTypes[AUDIO_STREAM_CNT] is initialized by stream_type_t default constructor // There is no AUDIO_STREAM_MIN, and ++ operator does not compile @@ -1677,7 +1678,7 @@ int AudioFlinger::PlaybackThread::asyncCallback(stream_callback_event_t event, return 0; } -void AudioFlinger::PlaybackThread::readOutputParameters() +void AudioFlinger::PlaybackThread::readOutputParameters_l() { // unfortunately we have no way of recovering from errors here, hence the LOG_FATAL mSampleRate = mOutput->stream->common.get_sample_rate(&mOutput->stream->common); @@ -1765,7 +1766,7 @@ void AudioFlinger::PlaybackThread::readOutputParameters() // force reconfiguration of effect chains and engines to take new buffer size and audio // parameters into account - // Note that mLock is not held when readOutputParameters() is called from the constructor + // Note that mLock is not held when readOutputParameters_l() is called from the constructor // but in this case nothing is done below as no audio sessions have effect yet so it doesn't // matter. // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains @@ -3485,7 +3486,7 @@ bool AudioFlinger::MixerThread::checkForNewParameters_l() keyValuePair.string()); } if (status == NO_ERROR && reconfig) { - readOutputParameters(); + readOutputParameters_l(); delete mAudioMixer; mAudioMixer = new AudioMixer(mNormalFrameCount, mSampleRate); for (size_t i = 0; i < mTracks.size() ; i++) { @@ -3827,7 +3828,7 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameters_l() keyValuePair.string()); } if (status == NO_ERROR && reconfig) { - readOutputParameters(); + readOutputParameters_l(); sendIoConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED); } } @@ -4450,8 +4451,6 @@ void AudioFlinger::DuplicatingThread::cacheParameters_l() AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, - uint32_t sampleRate, - audio_channel_mask_t channelMask, audio_io_handle_t id, audio_devices_t outDevice, audio_devices_t inDevice @@ -4460,14 +4459,9 @@ AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, #endif ) : ThreadBase(audioFlinger, id, outDevice, inDevice, RECORD), - mInput(input), mActiveTracksGen(0), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpInBuffer(NULL), - // mRsmpInFrames, mRsmpInFramesP2, mRsmpInUnrel, mRsmpInFront, and mRsmpInRear - // are set by readInputParameters() - // mRsmpInIndex LEGACY - mReqChannelCount(popcount(channelMask)), - mReqSampleRate(sampleRate) - // mBytesRead is only meaningful while active, and so is cleared in start() - // (but might be better to also clear here for dump?) + mInput(input), mActiveTracksGen(0), mRsmpInBuffer(NULL), + // mRsmpInFrames and mRsmpInFramesP2 are set by readInputParameters_l() + mRsmpInRear(0) #ifdef TEE_SINK , mTeeSink(teeSink) #endif @@ -4475,7 +4469,7 @@ AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, snprintf(mName, kNameLength, "AudioIn_%X", id); mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mName); - readInputParameters(); + readInputParameters_l(); } @@ -4483,8 +4477,6 @@ AudioFlinger::RecordThread::~RecordThread() { mAudioFlinger->unregisterWriter(mNBLogWriter); delete[] mRsmpInBuffer; - delete mResampler; - delete[] mRsmpOutBuffer; } void AudioFlinger::RecordThread::onFirstRef() @@ -4498,12 +4490,6 @@ bool AudioFlinger::RecordThread::threadLoop() inputStandBy(); - // used to verify we've read at least once before evaluating how many bytes were read - bool readOnce = false; - - // used to request a deferred sleep, to be executed later while mutex is unlocked - bool doSleep = false; - reacquire_wakelock: sp<RecordTrack> activeTrack; int activeTracksGen; @@ -4527,17 +4513,22 @@ reacquire_wakelock: } } - // start recording + // used to request a deferred sleep, to be executed later while mutex is unlocked + uint32_t sleepUs = 0; + + // loop while there is work to do for (;;) { - TrackBase::track_state activeTrackState; Vector< sp<EffectChain> > effectChains; // sleep with mutex unlocked - if (doSleep) { - doSleep = false; - usleep(kRecordThreadSleepUs); + if (sleepUs > 0) { + usleep(sleepUs); + sleepUs = 0; } + // activeTracks accumulates a copy of a subset of mActiveTracks + Vector< sp<RecordTrack> > activeTracks; + { // scope for mLock Mutex::Autolock _l(mLock); @@ -4571,236 +4562,307 @@ reacquire_wakelock: tmp.add(mActiveTracks[i]->uid()); } updateWakeLockUids_l(tmp); - // FIXME an arbitrary choice - activeTrack = mActiveTracks[0]; - } - - if (activeTrack->isTerminated()) { - removeTrack_l(activeTrack); - mActiveTracks.remove(activeTrack); - mActiveTracksGen++; - continue; } - activeTrackState = activeTrack->mState; - switch (activeTrackState) { - case TrackBase::PAUSING: - standbyIfNotAlreadyInStandby(); - mActiveTracks.remove(activeTrack); - mActiveTracksGen++; - mStartStopCond.broadcast(); - doSleep = true; - continue; + bool doBroadcast = false; + for (size_t i = 0; i < size; ) { - case TrackBase::RESUMING: - mStandby = false; - if (mReqChannelCount != activeTrack->channelCount()) { + activeTrack = mActiveTracks[i]; + if (activeTrack->isTerminated()) { + removeTrack_l(activeTrack); mActiveTracks.remove(activeTrack); mActiveTracksGen++; - mStartStopCond.broadcast(); + size--; continue; } - if (readOnce) { - mStartStopCond.broadcast(); - // record start succeeds only if first read from audio input succeeds - if (mBytesRead < 0) { - mActiveTracks.remove(activeTrack); - mActiveTracksGen++; - continue; - } + + TrackBase::track_state activeTrackState = activeTrack->mState; + switch (activeTrackState) { + + case TrackBase::PAUSING: + mActiveTracks.remove(activeTrack); + mActiveTracksGen++; + doBroadcast = true; + size--; + continue; + + case TrackBase::STARTING_1: + sleepUs = 10000; + i++; + continue; + + case TrackBase::STARTING_2: + doBroadcast = true; + mStandby = false; activeTrack->mState = TrackBase::ACTIVE; + break; + + case TrackBase::ACTIVE: + break; + + case TrackBase::IDLE: + i++; + continue; + + default: + LOG_FATAL("Unexpected activeTrackState %d", activeTrackState); } - break; - case TrackBase::ACTIVE: - break; + activeTracks.add(activeTrack); + i++; - case TrackBase::IDLE: - doSleep = true; - continue; + } + if (doBroadcast) { + mStartStopCond.broadcast(); + } - default: - LOG_FATAL("Unexpected activeTrackState %d", activeTrackState); + // sleep if there are no active tracks to process + if (activeTracks.size() == 0) { + if (sleepUs == 0) { + sleepUs = kRecordThreadSleepUs; + } + continue; } + sleepUs = 0; lockEffectChains_l(effectChains); } - // thread mutex is now unlocked, mActiveTracks unknown, activeTrack != 0, kept, immutable - // activeTrack->mState unknown, activeTrackState immutable and is ACTIVE or RESUMING + // thread mutex is now unlocked, mActiveTracks unknown, activeTracks.size() > 0 - for (size_t i = 0; i < effectChains.size(); i ++) { + size_t size = effectChains.size(); + for (size_t i = 0; i < size; i++) { // thread mutex is not locked, but effect chain is locked effectChains[i]->process_l(); } - AudioBufferProvider::Buffer buffer; - buffer.frameCount = mFrameCount; - status_t status = activeTrack->getNextBuffer(&buffer); - if (status == NO_ERROR) { - readOnce = true; - size_t framesOut = buffer.frameCount; - if (mResampler == NULL) { - // no resampling - while (framesOut) { - size_t framesIn = mFrameCount - mRsmpInIndex; - if (framesIn > 0) { - int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize; - int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * - activeTrack->mFrameSize; - if (framesIn > framesOut) { - framesIn = framesOut; + // Read from HAL to keep up with fastest client if multiple active tracks, not slowest one. + // Only the client(s) that are too slow will overrun. But if even the fastest client is too + // slow, then this RecordThread will overrun by not calling HAL read often enough. + // If destination is non-contiguous, first read past the nominal end of buffer, then + // copy to the right place. Permitted because mRsmpInBuffer was over-allocated. + + int32_t rear = mRsmpInRear & (mRsmpInFramesP2 - 1); + ssize_t bytesRead = mInput->stream->read(mInput->stream, + &mRsmpInBuffer[rear * mChannelCount], mBufferSize); + if (bytesRead <= 0) { + ALOGE("read failed: bytesRead=%d < %u", bytesRead, mBufferSize); + // Force input into standby so that it tries to recover at next read attempt + inputStandBy(); + sleepUs = kRecordThreadSleepUs; + continue; + } + ALOG_ASSERT((size_t) bytesRead <= mBufferSize); + size_t framesRead = bytesRead / mFrameSize; + ALOG_ASSERT(framesRead > 0); + if (mTeeSink != 0) { + (void) mTeeSink->write(&mRsmpInBuffer[rear * mChannelCount], framesRead); + } + // If destination is non-contiguous, we now correct for reading past end of buffer. + size_t part1 = mRsmpInFramesP2 - rear; + if (framesRead > part1) { + memcpy(mRsmpInBuffer, &mRsmpInBuffer[mRsmpInFramesP2 * mChannelCount], + (framesRead - part1) * mFrameSize); + } + rear = mRsmpInRear += framesRead; + + size = activeTracks.size(); + // loop over each active track + for (size_t i = 0; i < size; i++) { + activeTrack = activeTracks[i]; + + enum { + OVERRUN_UNKNOWN, + OVERRUN_TRUE, + OVERRUN_FALSE + } overrun = OVERRUN_UNKNOWN; + + // loop over getNextBuffer to handle circular sink + for (;;) { + + activeTrack->mSink.frameCount = ~0; + status_t status = activeTrack->getNextBuffer(&activeTrack->mSink); + size_t framesOut = activeTrack->mSink.frameCount; + LOG_ALWAYS_FATAL_IF((status == OK) != (framesOut > 0)); + + int32_t front = activeTrack->mRsmpInFront; + ssize_t filled = rear - front; + size_t framesIn; + + if (filled < 0) { + // should not happen, but treat like a massive overrun and re-sync + framesIn = 0; + activeTrack->mRsmpInFront = rear; + overrun = OVERRUN_TRUE; + } else if ((size_t) filled <= mRsmpInFrames) { + framesIn = (size_t) filled; + } else { + // client is not keeping up with server, but give it latest data + framesIn = mRsmpInFrames; + activeTrack->mRsmpInFront = front = rear - framesIn; + overrun = OVERRUN_TRUE; + } + + if (framesOut == 0 || framesIn == 0) { + break; + } + + if (activeTrack->mResampler == NULL) { + // no resampling + if (framesIn > framesOut) { + framesIn = framesOut; + } else { + framesOut = framesIn; + } + int8_t *dst = activeTrack->mSink.i8; + while (framesIn > 0) { + front &= mRsmpInFramesP2 - 1; + size_t part1 = mRsmpInFramesP2 - front; + if (part1 > framesIn) { + part1 = framesIn; } - mRsmpInIndex += framesIn; - framesOut -= framesIn; - if (mChannelCount == mReqChannelCount) { - memcpy(dst, src, framesIn * mFrameSize); + int8_t *src = (int8_t *)mRsmpInBuffer + (front * mFrameSize); + if (mChannelCount == activeTrack->mChannelCount) { + memcpy(dst, src, part1 * mFrameSize); + } else if (mChannelCount == 1) { + upmix_to_stereo_i16_from_mono_i16((int16_t *)dst, (int16_t *)src, + part1); } else { - if (mChannelCount == 1) { - upmix_to_stereo_i16_from_mono_i16((int16_t *)dst, - (int16_t *)src, framesIn); - } else { - downmix_to_mono_i16_from_stereo_i16((int16_t *)dst, - (int16_t *)src, framesIn); - } + downmix_to_mono_i16_from_stereo_i16((int16_t *)dst, (int16_t *)src, + part1); } + dst += part1 * activeTrack->mFrameSize; + front += part1; + framesIn -= part1; } - if (framesOut > 0 && mFrameCount == mRsmpInIndex) { - void *readInto; - if (framesOut == mFrameCount && mChannelCount == mReqChannelCount) { - readInto = buffer.raw; - framesOut = 0; - } else { - readInto = mRsmpInBuffer; - mRsmpInIndex = 0; - } - mBytesRead = mInput->stream->read(mInput->stream, readInto, mBufferSize); - if (mBytesRead <= 0) { - // TODO: verify that it's benign to use a stale track state - if ((mBytesRead < 0) && (activeTrackState == TrackBase::ACTIVE)) - { - ALOGE("Error reading audio input"); - // Force input into standby so that it tries to - // recover at next read attempt - inputStandBy(); - doSleep = true; - } - mRsmpInIndex = mFrameCount; - framesOut = 0; - buffer.frameCount = 0; - } -#ifdef TEE_SINK - else if (mTeeSink != 0) { - (void) mTeeSink->write(readInto, - mBytesRead >> Format_frameBitShift(mTeeSink->format())); + activeTrack->mRsmpInFront += framesOut; + + } else { + // resampling + // FIXME framesInNeeded should really be part of resampler API, and should + // depend on the SRC ratio + // to keep mRsmpInBuffer full so resampler always has sufficient input + size_t framesInNeeded; + // FIXME only re-calculate when it changes, and optimize for common ratios + double inOverOut = (double) mSampleRate / activeTrack->mSampleRate; + double outOverIn = (double) activeTrack->mSampleRate / mSampleRate; + framesInNeeded = ceil(framesOut * inOverOut) + 1; + ALOGV("need %u frames in to produce %u out given in/out ratio of %.4g", + framesInNeeded, framesOut, inOverOut); + // Although we theoretically have framesIn in circular buffer, some of those are + // unreleased frames, and thus must be discounted for purpose of budgeting. + size_t unreleased = activeTrack->mRsmpInUnrel; + framesIn = framesIn > unreleased ? framesIn - unreleased : 0; + if (framesIn < framesInNeeded) { + ALOGV("not enough to resample: have %u frames in but need %u in to " + "produce %u out given in/out ratio of %.4g", + framesIn, framesInNeeded, framesOut, inOverOut); + size_t newFramesOut = framesIn > 0 ? floor((framesIn - 1) * outOverIn) : 0; + LOG_ALWAYS_FATAL_IF(newFramesOut >= framesOut); + if (newFramesOut == 0) { + break; } -#endif - } - } - } else { - // resampling - - // avoid busy-waiting if client doesn't keep up - bool madeProgress = false; - - // keep mRsmpInBuffer full so resampler always has sufficient input - for (;;) { - int32_t rear = mRsmpInRear; - ssize_t filled = rear - mRsmpInFront; - ALOG_ASSERT(0 <= filled && (size_t) filled <= mRsmpInFramesP2); - // exit once there is enough data in buffer for resampler - if ((size_t) filled >= mRsmpInFrames) { - break; - } - size_t avail = mRsmpInFramesP2 - filled; - // Only try to read full HAL buffers. - // But if the HAL read returns a partial buffer, use it. - if (avail < mFrameCount) { - ALOGE("insufficient space to read: avail %d < mFrameCount %d", - avail, mFrameCount); - break; + framesInNeeded = ceil(newFramesOut * inOverOut) + 1; + ALOGV("now need %u frames in to produce %u out given out/in ratio of %.4g", + framesInNeeded, newFramesOut, outOverIn); + LOG_ALWAYS_FATAL_IF(framesIn < framesInNeeded); + ALOGV("success 2: have %u frames in and need %u in to produce %u out " + "given in/out ratio of %.4g", + framesIn, framesInNeeded, newFramesOut, inOverOut); + framesOut = newFramesOut; + } else { + ALOGV("success 1: have %u in and need %u in to produce %u out " + "given in/out ratio of %.4g", + framesIn, framesInNeeded, framesOut, inOverOut); } - // If 'avail' is non-contiguous, first read past the nominal end of buffer, then - // copy to the right place. Permitted because mRsmpInBuffer was over-allocated. - rear &= mRsmpInFramesP2 - 1; - mBytesRead = mInput->stream->read(mInput->stream, - &mRsmpInBuffer[rear * mChannelCount], mBufferSize); - if (mBytesRead <= 0) { - ALOGE("read failed: mBytesRead=%d < %u", mBytesRead, mBufferSize); - break; + + // reallocate mRsmpOutBuffer as needed; we will grow but never shrink + if (activeTrack->mRsmpOutFrameCount < framesOut) { + // FIXME why does each track need it's own mRsmpOutBuffer? can't they share? + delete[] activeTrack->mRsmpOutBuffer; + // resampler always outputs stereo + activeTrack->mRsmpOutBuffer = new int32_t[framesOut * FCC_2]; + activeTrack->mRsmpOutFrameCount = framesOut; } - ALOG_ASSERT((size_t) mBytesRead <= mBufferSize); - size_t framesRead = mBytesRead / mFrameSize; - ALOG_ASSERT(framesRead > 0); - madeProgress = true; - // If 'avail' was non-contiguous, we now correct for reading past end of buffer. - size_t part1 = mRsmpInFramesP2 - rear; - if (framesRead > part1) { - memcpy(mRsmpInBuffer, &mRsmpInBuffer[mRsmpInFramesP2 * mChannelCount], - (framesRead - part1) * mFrameSize); + + // resampler accumulates, but we only have one source track + memset(activeTrack->mRsmpOutBuffer, 0, framesOut * FCC_2 * sizeof(int32_t)); + activeTrack->mResampler->resample(activeTrack->mRsmpOutBuffer, framesOut, + // FIXME how about having activeTrack implement this interface itself? + activeTrack->mResamplerBufferProvider + /*this*/ /* AudioBufferProvider* */); + // ditherAndClamp() works as long as all buffers returned by + // activeTrack->getNextBuffer() are 32 bit aligned which should be always true. + if (activeTrack->mChannelCount == 1) { + // temporarily type pun mRsmpOutBuffer from Q19.12 to int16_t + ditherAndClamp(activeTrack->mRsmpOutBuffer, activeTrack->mRsmpOutBuffer, + framesOut); + // the resampler always outputs stereo samples: + // do post stereo to mono conversion + downmix_to_mono_i16_from_stereo_i16(activeTrack->mSink.i16, + (int16_t *)activeTrack->mRsmpOutBuffer, framesOut); + } else { + ditherAndClamp((int32_t *)activeTrack->mSink.raw, + activeTrack->mRsmpOutBuffer, framesOut); } - mRsmpInRear += framesRead; - } + // now done with mRsmpOutBuffer - if (!madeProgress) { - ALOGV("Did not make progress"); - usleep(((mFrameCount * 1000) / mSampleRate) * 1000); } - // resampler accumulates, but we only have one source track - memset(mRsmpOutBuffer, 0, framesOut * FCC_2 * sizeof(int32_t)); - mResampler->resample(mRsmpOutBuffer, framesOut, - this /* AudioBufferProvider* */); - // ditherAndClamp() works as long as all buffers returned by - // activeTrack->getNextBuffer() are 32 bit aligned which should be always true. - if (mReqChannelCount == 1) { - // temporarily type pun mRsmpOutBuffer from Q19.12 to int16_t - ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut); - // the resampler always outputs stereo samples: - // do post stereo to mono conversion - downmix_to_mono_i16_from_stereo_i16(buffer.i16, (int16_t *)mRsmpOutBuffer, - framesOut); - } else { - ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut); + if (framesOut > 0 && (overrun == OVERRUN_UNKNOWN)) { + overrun = OVERRUN_FALSE; } - // now done with mRsmpOutBuffer - } - if (mFramestoDrop == 0) { - activeTrack->releaseBuffer(&buffer); - } else { - if (mFramestoDrop > 0) { - mFramestoDrop -= buffer.frameCount; - if (mFramestoDrop <= 0) { - clearSyncStartEvent(); + if (activeTrack->mFramesToDrop == 0) { + if (framesOut > 0) { + activeTrack->mSink.frameCount = framesOut; + activeTrack->releaseBuffer(&activeTrack->mSink); } } else { - mFramestoDrop += buffer.frameCount; - if (mFramestoDrop >= 0 || mSyncStartEvent == 0 || - mSyncStartEvent->isCancelled()) { - ALOGW("Synced record %s, session %d, trigger session %d", - (mFramestoDrop >= 0) ? "timed out" : "cancelled", - activeTrack->sessionId(), - (mSyncStartEvent != 0) ? mSyncStartEvent->triggerSession() : 0); - clearSyncStartEvent(); + // FIXME could do a partial drop of framesOut + if (activeTrack->mFramesToDrop > 0) { + activeTrack->mFramesToDrop -= framesOut; + if (activeTrack->mFramesToDrop <= 0) { + activeTrack->clearSyncStartEvent(); + } + } else { + activeTrack->mFramesToDrop += framesOut; + if (activeTrack->mFramesToDrop >= 0 || activeTrack->mSyncStartEvent == 0 || + activeTrack->mSyncStartEvent->isCancelled()) { + ALOGW("Synced record %s, session %d, trigger session %d", + (activeTrack->mFramesToDrop >= 0) ? "timed out" : "cancelled", + activeTrack->sessionId(), + (activeTrack->mSyncStartEvent != 0) ? + activeTrack->mSyncStartEvent->triggerSession() : 0); + activeTrack->clearSyncStartEvent(); + } } } + + if (framesOut == 0) { + break; + } } - activeTrack->clearOverflow(); - } - // client isn't retrieving buffers fast enough - else { - if (!activeTrack->setOverflow()) { - nsecs_t now = systemTime(); - if ((now - lastWarning) > kWarningThrottleNs) { - ALOGW("RecordThread: buffer overflow"); - lastWarning = now; + + switch (overrun) { + case OVERRUN_TRUE: + // client isn't retrieving buffers fast enough + if (!activeTrack->setOverflow()) { + nsecs_t now = systemTime(); + // FIXME should lastWarning per track? + if ((now - lastWarning) > kWarningThrottleNs) { + ALOGW("RecordThread: buffer overflow"); + lastWarning = now; + } } + break; + case OVERRUN_FALSE: + activeTrack->clearOverflow(); + break; + case OVERRUN_UNKNOWN: + break; } - // Release the processor for a while before asking for a new buffer. - // This will give the application more chance to read from the buffer and - // clear the overflow. - doSleep = true; + } // enable changes in effect chain @@ -4959,114 +5021,92 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac status_t status = NO_ERROR; if (event == AudioSystem::SYNC_EVENT_NONE) { - clearSyncStartEvent(); + recordTrack->clearSyncStartEvent(); } else if (event != AudioSystem::SYNC_EVENT_SAME) { - mSyncStartEvent = mAudioFlinger->createSyncEvent(event, + recordTrack->mSyncStartEvent = mAudioFlinger->createSyncEvent(event, triggerSession, recordTrack->sessionId(), syncStartEventCallback, - this); + recordTrack); // Sync event can be cancelled by the trigger session if the track is not in a // compatible state in which case we start record immediately - if (mSyncStartEvent->isCancelled()) { - clearSyncStartEvent(); + if (recordTrack->mSyncStartEvent->isCancelled()) { + recordTrack->clearSyncStartEvent(); } else { // do not wait for the event for more than AudioSystem::kSyncRecordStartTimeOutMs - mFramestoDrop = - ((AudioSystem::kSyncRecordStartTimeOutMs * mReqSampleRate) / 1000); + recordTrack->mFramesToDrop = - + ((AudioSystem::kSyncRecordStartTimeOutMs * recordTrack->mSampleRate) / 1000); } } { // This section is a rendezvous between binder thread executing start() and RecordThread AutoMutex lock(mLock); - if (mActiveTracks.size() > 0) { - // FIXME does not work for multiple active tracks - if (mActiveTracks.indexOf(recordTrack) != 0) { - status = -EBUSY; - } else if (recordTrack->mState == TrackBase::PAUSING) { + if (mActiveTracks.indexOf(recordTrack) >= 0) { + if (recordTrack->mState == TrackBase::PAUSING) { + ALOGV("active record track PAUSING -> ACTIVE"); recordTrack->mState = TrackBase::ACTIVE; + } else { + ALOGV("active record track state %d", recordTrack->mState); } return status; } - // FIXME why? already set in constructor, 'STARTING_1' would be more accurate - recordTrack->mState = TrackBase::IDLE; + // TODO consider other ways of handling this, such as changing the state to :STARTING and + // adding the track to mActiveTracks after returning from AudioSystem::startInput(), + // or using a separate command thread + recordTrack->mState = TrackBase::STARTING_1; mActiveTracks.add(recordTrack); mActiveTracksGen++; mLock.unlock(); status_t status = AudioSystem::startInput(mId); mLock.lock(); - // FIXME should verify that mActiveTrack is still == recordTrack + // FIXME should verify that recordTrack is still in mActiveTracks if (status != NO_ERROR) { mActiveTracks.remove(recordTrack); mActiveTracksGen++; - clearSyncStartEvent(); + recordTrack->clearSyncStartEvent(); return status; } - // FIXME LEGACY - mRsmpInIndex = mFrameCount; - mRsmpInFront = 0; - mRsmpInRear = 0; - mRsmpInUnrel = 0; - mBytesRead = 0; - if (mResampler != NULL) { - mResampler->reset(); - } - // FIXME hijacking a playback track state name which was intended for start after pause; - // here 'STARTING_2' would be more accurate - recordTrack->mState = TrackBase::RESUMING; + // Catch up with current buffer indices if thread is already running. + // This is what makes a new client discard all buffered data. If the track's mRsmpInFront + // was initialized to some value closer to the thread's mRsmpInFront, then the track could + // see previously buffered data before it called start(), but with greater risk of overrun. + + recordTrack->mRsmpInFront = mRsmpInRear; + recordTrack->mRsmpInUnrel = 0; + // FIXME why reset? + if (recordTrack->mResampler != NULL) { + recordTrack->mResampler->reset(); + } + recordTrack->mState = TrackBase::STARTING_2; // signal thread to start - ALOGV("Signal record thread"); mWaitWorkCV.broadcast(); - // do not wait for mStartStopCond if exiting - if (exitPending()) { - mActiveTracks.remove(recordTrack); - mActiveTracksGen++; - status = INVALID_OPERATION; - goto startError; - } - // FIXME incorrect usage of wait: no explicit predicate or loop - mStartStopCond.wait(mLock); if (mActiveTracks.indexOf(recordTrack) < 0) { ALOGV("Record failed to start"); status = BAD_VALUE; goto startError; } - ALOGV("Record started OK"); return status; } startError: AudioSystem::stopInput(mId); - clearSyncStartEvent(); + recordTrack->clearSyncStartEvent(); + // FIXME I wonder why we do not reset the state here? return status; } -void AudioFlinger::RecordThread::clearSyncStartEvent() -{ - if (mSyncStartEvent != 0) { - mSyncStartEvent->cancel(); - } - mSyncStartEvent.clear(); - mFramestoDrop = 0; -} - void AudioFlinger::RecordThread::syncStartEventCallback(const wp<SyncEvent>& event) { sp<SyncEvent> strongEvent = event.promote(); if (strongEvent != 0) { - RecordThread *me = (RecordThread *)strongEvent->cookie(); - me->handleSyncStartEvent(strongEvent); - } -} - -void AudioFlinger::RecordThread::handleSyncStartEvent(const sp<SyncEvent>& event) -{ - if (event == mSyncStartEvent) { - // TODO: use actual buffer filling status instead of 2 buffers when info is available - // from audio HAL - mFramestoDrop = mFrameCount * 2; + sp<RefBase> ptr = strongEvent->cookie().promote(); + if (ptr != 0) { + RecordTrack *recordTrack = (RecordTrack *)ptr.get(); + recordTrack->handleSyncStartEvent(strongEvent); + } } } @@ -5151,13 +5191,9 @@ void AudioFlinger::RecordThread::dumpInternals(int fd, const Vector<String16>& a fdprintf(fd, "\nInput thread %p:\n", this); if (mActiveTracks.size() > 0) { - fdprintf(fd, " In index: %zu\n", mRsmpInIndex); fdprintf(fd, " Buffer size: %zu bytes\n", mBufferSize); - fdprintf(fd, " Resampling: %d\n", (mResampler != NULL)); - fdprintf(fd, " Out channel count: %u\n", mReqChannelCount); - fdprintf(fd, " Out sample rate: %u\n", mReqSampleRate); } else { - fdprintf(fd, " No active record client\n"); + fdprintf(fd, " No active record clients\n"); } dumpBase(fd, args); @@ -5209,15 +5245,26 @@ void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args } // AudioBufferProvider interface -status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts __unused) +status_t AudioFlinger::RecordThread::ResamplerBufferProvider::getNextBuffer( + AudioBufferProvider::Buffer* buffer, int64_t pts __unused) { - int32_t rear = mRsmpInRear; - int32_t front = mRsmpInFront; + RecordTrack *activeTrack = mRecordTrack; + sp<ThreadBase> threadBase = activeTrack->mThread.promote(); + if (threadBase == 0) { + buffer->frameCount = 0; + buffer->raw = NULL; + return NOT_ENOUGH_DATA; + } + RecordThread *recordThread = (RecordThread *) threadBase.get(); + int32_t rear = recordThread->mRsmpInRear; + int32_t front = activeTrack->mRsmpInFront; ssize_t filled = rear - front; - ALOG_ASSERT(0 <= filled && (size_t) filled <= mRsmpInFramesP2); + // FIXME should not be P2 (don't want to increase latency) + // FIXME if client not keeping up, discard + LOG_ALWAYS_FATAL_IF(!(0 <= filled && (size_t) filled <= recordThread->mRsmpInFrames)); // 'filled' may be non-contiguous, so return only the first contiguous chunk - front &= mRsmpInFramesP2 - 1; - size_t part1 = mRsmpInFramesP2 - front; + front &= recordThread->mRsmpInFramesP2 - 1; + size_t part1 = recordThread->mRsmpInFramesP2 - front; if (part1 > (size_t) filled) { part1 = filled; } @@ -5228,29 +5275,31 @@ status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* } if (part1 == 0) { // Higher-level should keep mRsmpInBuffer full, and not call resampler if empty - ALOGE("RecordThread::getNextBuffer() starved"); + LOG_ALWAYS_FATAL("RecordThread::getNextBuffer() starved"); buffer->raw = NULL; buffer->frameCount = 0; - mRsmpInUnrel = 0; + activeTrack->mRsmpInUnrel = 0; return NOT_ENOUGH_DATA; } - buffer->raw = mRsmpInBuffer + front * mChannelCount; + buffer->raw = recordThread->mRsmpInBuffer + front * recordThread->mChannelCount; buffer->frameCount = part1; - mRsmpInUnrel = part1; + activeTrack->mRsmpInUnrel = part1; return NO_ERROR; } // AudioBufferProvider interface -void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer) +void AudioFlinger::RecordThread::ResamplerBufferProvider::releaseBuffer( + AudioBufferProvider::Buffer* buffer) { + RecordTrack *activeTrack = mRecordTrack; size_t stepCount = buffer->frameCount; if (stepCount == 0) { return; } - ALOG_ASSERT(stepCount <= mRsmpInUnrel); - mRsmpInUnrel -= stepCount; - mRsmpInFront += stepCount; + ALOG_ASSERT(stepCount <= activeTrack->mRsmpInUnrel); + activeTrack->mRsmpInUnrel -= stepCount; + activeTrack->mRsmpInFront += stepCount; buffer->raw = NULL; buffer->frameCount = 0; } @@ -5265,11 +5314,14 @@ bool AudioFlinger::RecordThread::checkForNewParameters_l() AudioParameter param = AudioParameter(keyValuePair); int value; audio_format_t reqFormat = mFormat; - uint32_t reqSamplingRate = mReqSampleRate; - audio_channel_mask_t reqChannelMask = audio_channel_in_mask_from_count(mReqChannelCount); + uint32_t samplingRate = mSampleRate; + audio_channel_mask_t channelMask = audio_channel_in_mask_from_count(mChannelCount); + // TODO Investigate when this code runs. Check with audio policy when a sample rate and + // channel count change can be requested. Do we mandate the first client defines the + // HAL sampling rate and channel count or do we allow changes on the fly? if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) { - reqSamplingRate = value; + samplingRate = value; reconfig = true; } if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) { @@ -5285,7 +5337,7 @@ bool AudioFlinger::RecordThread::checkForNewParameters_l() if (mask != AUDIO_CHANNEL_IN_MONO && mask != AUDIO_CHANNEL_IN_STEREO) { status = BAD_VALUE; } else { - reqChannelMask = mask; + channelMask = mask; reconfig = true; } } @@ -5350,15 +5402,15 @@ bool AudioFlinger::RecordThread::checkForNewParameters_l() reqFormat == mInput->stream->common.get_format(&mInput->stream->common) && reqFormat == AUDIO_FORMAT_PCM_16_BIT && (mInput->stream->common.get_sample_rate(&mInput->stream->common) - <= (2 * reqSamplingRate)) && + <= (2 * samplingRate)) && popcount(mInput->stream->common.get_channels(&mInput->stream->common)) <= FCC_2 && - (reqChannelMask == AUDIO_CHANNEL_IN_MONO || - reqChannelMask == AUDIO_CHANNEL_IN_STEREO)) { + (channelMask == AUDIO_CHANNEL_IN_MONO || + channelMask == AUDIO_CHANNEL_IN_STEREO)) { status = NO_ERROR; } if (status == NO_ERROR) { - readInputParameters(); + readInputParameters_l(); sendIoConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED); } } @@ -5410,15 +5462,8 @@ void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param __unu mAudioFlinger->audioConfigChanged_l(event, mId, param2); } -void AudioFlinger::RecordThread::readInputParameters() +void AudioFlinger::RecordThread::readInputParameters_l() { - delete[] mRsmpInBuffer; - // mRsmpInBuffer is always assigned a new[] below - delete[] mRsmpOutBuffer; - mRsmpOutBuffer = NULL; - delete mResampler; - mResampler = NULL; - mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common); mChannelMask = mInput->stream->common.get_channels(&mInput->stream->common); mChannelCount = popcount(mChannelMask); @@ -5429,24 +5474,20 @@ void AudioFlinger::RecordThread::readInputParameters() mFrameSize = audio_stream_frame_size(&mInput->stream->common); mBufferSize = mInput->stream->common.get_buffer_size(&mInput->stream->common); mFrameCount = mBufferSize / mFrameSize; + // This is the formula for calculating the temporary buffer size. // With 3 HAL buffers, we can guarantee ability to down-sample the input by ratio of 2:1 to // 1 full output buffer, regardless of the alignment of the available input. + // The "3" is somewhat arbitrary, and could probably be larger. + // A larger value should allow more old data to be read after a track calls start(), + // without increasing latency. mRsmpInFrames = mFrameCount * 3; mRsmpInFramesP2 = roundup(mRsmpInFrames); + delete[] mRsmpInBuffer; // Over-allocate beyond mRsmpInFramesP2 to permit a HAL read past end of buffer mRsmpInBuffer = new int16_t[(mRsmpInFramesP2 + mFrameCount - 1) * mChannelCount]; - mRsmpInFront = 0; - mRsmpInRear = 0; - mRsmpInUnrel = 0; - - if (mSampleRate != mReqSampleRate && mChannelCount <= FCC_2 && mReqChannelCount <= FCC_2) { - mResampler = AudioResampler::create(16, (int) mChannelCount, mReqSampleRate); - mResampler->setSampleRate(mSampleRate); - mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN); - // resampler always outputs stereo - mRsmpOutBuffer = new int32_t[mFrameCount * FCC_2]; - } - mRsmpInIndex = mFrameCount; + + // AudioRecord mSampleRate and mChannelCount are constant due to AudioRecord API constraints. + // But if thread's mSampleRate or mChannelCount changes, how will that affect active tracks? } uint32_t AudioFlinger::RecordThread::getInputFramesLost() diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h index 999fea3..fa3563c 100644 --- a/services/audioflinger/Threads.h +++ b/services/audioflinger/Threads.h @@ -270,8 +270,8 @@ protected: const sp<AudioFlinger> mAudioFlinger; - // updated by PlaybackThread::readOutputParameters() or - // RecordThread::readInputParameters() + // updated by PlaybackThread::readOutputParameters_l() or + // RecordThread::readInputParameters_l() uint32_t mSampleRate; size_t mFrameCount; // output HAL, direct output, record audio_channel_mask_t mChannelMask; @@ -478,7 +478,7 @@ public: status_t getTimestamp_l(AudioTimestamp& timestamp); protected: - // updated by readOutputParameters() + // updated by readOutputParameters_l() size_t mNormalFrameCount; // normal mixer and effects int16_t* mMixBuffer; // frame size aligned mix buffer @@ -541,7 +541,7 @@ private: void removeTrack_l(const sp<Track>& track); void broadcast_l(); - void readOutputParameters(); + void readOutputParameters_l(); virtual void dumpInternals(int fd, const Vector<String16>& args); void dumpTracks(int fd, const Vector<String16>& args); @@ -839,17 +839,28 @@ public: // record thread -class RecordThread : public ThreadBase, public AudioBufferProvider - // derives from AudioBufferProvider interface for use by resampler +class RecordThread : public ThreadBase { public: + class RecordTrack; + class ResamplerBufferProvider : public AudioBufferProvider + // derives from AudioBufferProvider interface for use by resampler + { + public: + ResamplerBufferProvider(RecordTrack* recordTrack) : mRecordTrack(recordTrack) { } + virtual ~ResamplerBufferProvider() { } + // AudioBufferProvider interface + virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts); + virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); + private: + RecordTrack * const mRecordTrack; + }; + #include "RecordTracks.h" RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, - uint32_t sampleRate, - audio_channel_mask_t channelMask, audio_io_handle_t id, audio_devices_t outDevice, audio_devices_t inDevice @@ -898,14 +909,11 @@ public: AudioStreamIn* clearInput(); virtual audio_stream_t* stream() const; - // AudioBufferProvider interface - virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts); - virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); virtual bool checkForNewParameters_l(); virtual String8 getParameters(const String8& keys); virtual void audioConfigChanged_l(int event, int param = 0); - void readInputParameters(); + void readInputParameters_l(); virtual uint32_t getInputFramesLost(); virtual status_t addEffectChain_l(const sp<EffectChain>& chain); @@ -921,14 +929,11 @@ public: virtual bool isValidSyncEvent(const sp<SyncEvent>& event) const; static void syncStartEventCallback(const wp<SyncEvent>& event); - void handleSyncStartEvent(const sp<SyncEvent>& event); virtual size_t frameCount() const { return mFrameCount; } bool hasFastRecorder() const { return false; } private: - void clearSyncStartEvent(); - // Enter standby if not already in standby, and set mStandby flag void standbyIfNotAlreadyInStandby(); @@ -944,34 +949,13 @@ private: int mActiveTracksGen; Condition mStartStopCond; - // updated by RecordThread::readInputParameters() - AudioResampler *mResampler; - // interleaved stereo pairs of fixed-point signed Q19.12 - int32_t *mRsmpOutBuffer; - // resampler converts input at HAL Hz to output at AudioRecord client Hz int16_t *mRsmpInBuffer; // see new[] for details on the size size_t mRsmpInFrames; // size of resampler input in frames size_t mRsmpInFramesP2;// size rounded up to a power-of-2 - size_t mRsmpInUnrel; // unreleased frames remaining from - // most recent getNextBuffer - // these are rolling counters that are never cleared - int32_t mRsmpInFront; // next available frame + + // rolling index that is never cleared int32_t mRsmpInRear; // last filled frame + 1 - size_t mRsmpInIndex; // FIXME legacy - - // client's requested configuration, which may differ from the HAL configuration - const uint32_t mReqChannelCount; - const uint32_t mReqSampleRate; - - ssize_t mBytesRead; - // sync event triggering actual audio capture. Frames read before this event will - // be dropped and therefore not read by the application. - sp<SyncEvent> mSyncStartEvent; - // number of captured frames to drop after the start sync event has been received. - // when < 0, maximum frames to drop before starting capture even if sync event is - // not received - ssize_t mFramestoDrop; // For dumpsys const sp<NBAIO_Sink> mTeeSink; diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h index 05fde7c..58705c4 100644 --- a/services/audioflinger/TrackBase.h +++ b/services/audioflinger/TrackBase.h @@ -34,7 +34,9 @@ public: RESUMING, ACTIVE, PAUSING, - PAUSED + PAUSED, + STARTING_1, // for RecordTrack only + STARTING_2, // for RecordTrack only }; TrackBase(ThreadBase *thread, diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index e5152b8..92ed46a 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -1785,17 +1785,34 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( int uid) : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, 0 /*sharedBuffer*/, sessionId, uid, false /*isOut*/), - mOverflow(false) + mOverflow(false), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpOutFrameCount(0), + // See real initialization of mRsmpInFront at RecordThread::start() + mRsmpInUnrel(0), mRsmpInFront(0), mFramesToDrop(0), mResamplerBufferProvider(NULL) { ALOGV("RecordTrack constructor"); if (mCblk != NULL) { mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount, mFrameSize); } + + uint32_t channelCount = popcount(channelMask); + // FIXME I don't understand either of the channel count checks + if (thread->mSampleRate != sampleRate && thread->mChannelCount <= FCC_2 && + channelCount <= FCC_2) { + // sink SR + mResampler = AudioResampler::create(16, thread->mChannelCount, sampleRate); + // source SR + mResampler->setSampleRate(thread->mSampleRate); + mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN); + mResamplerBufferProvider = new ResamplerBufferProvider(this); + } } AudioFlinger::RecordThread::RecordTrack::~RecordTrack() { ALOGV("%s", __func__); + delete mResampler; + delete[] mRsmpOutBuffer; + delete mResamplerBufferProvider; } // AudioBufferProvider interface @@ -1868,12 +1885,12 @@ void AudioFlinger::RecordThread::RecordTrack::invalidate() /*static*/ void AudioFlinger::RecordThread::RecordTrack::appendDumpHeader(String8& result) { - result.append(" Active Client Fmt Chn mask Session S Server fCount\n"); + result.append(" Active Client Fmt Chn mask Session S Server fCount Resampling\n"); } void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size, bool active) { - snprintf(buffer, size, " %6s %6u %3u %08X %7u %1d %08X %6zu\n", + snprintf(buffer, size, " %6s %6u %3u %08X %7u %1d %08X %6zu %10d\n", active ? "yes" : "no", (mClient == 0) ? getpid_cached : mClient->pid(), mFormat, @@ -1881,7 +1898,32 @@ void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size, bo mSessionId, mState, mCblk->mServer, - mFrameCount); + mFrameCount, + mResampler != NULL); + +} + +void AudioFlinger::RecordThread::RecordTrack::handleSyncStartEvent(const sp<SyncEvent>& event) +{ + if (event == mSyncStartEvent) { + ssize_t framesToDrop = 0; + sp<ThreadBase> threadBase = mThread.promote(); + if (threadBase != 0) { + // TODO: use actual buffer filling status instead of 2 buffers when info is available + // from audio HAL + framesToDrop = threadBase->mFrameCount * 2; + } + mFramesToDrop = framesToDrop; + } +} + +void AudioFlinger::RecordThread::RecordTrack::clearSyncStartEvent() +{ + if (mSyncStartEvent != 0) { + mSyncStartEvent->cancel(); + mSyncStartEvent.clear(); + } + mFramesToDrop = 0; } }; // namespace android diff --git a/services/audioflinger/test-resample.cpp b/services/audioflinger/test-resample.cpp index 66fcd90..74d5702 100644 --- a/services/audioflinger/test-resample.cpp +++ b/services/audioflinger/test-resample.cpp @@ -34,7 +34,7 @@ bool gVerbose = false; static int usage(const char* name) { fprintf(stderr,"Usage: %s [-p] [-h] [-v] [-s] [-q {dq|lq|mq|hq|vhq|dlq|dmq|dhq}]" - " [-i input-sample-rate] [-o output-sample-rate] [<input-file>]" + " [-i input-sample-rate] [-o output-sample-rate] [-O #] [<input-file>]" " <output-file>\n", name); fprintf(stderr," -p enable profiling\n"); fprintf(stderr," -h create wav file\n"); @@ -51,6 +51,7 @@ static int usage(const char* name) { fprintf(stderr," dhq : dynamic high quality\n"); fprintf(stderr," -i input file sample rate (ignored if input file is specified)\n"); fprintf(stderr," -o output file sample rate\n"); + fprintf(stderr," -O # frames output per call to resample()\n"); return -1; } @@ -64,9 +65,10 @@ int main(int argc, char* argv[]) { int input_freq = 0; int output_freq = 0; AudioResampler::src_quality quality = AudioResampler::DEFAULT_QUALITY; + size_t framesPerCall = 0; int ch; - while ((ch = getopt(argc, argv, "pfhvsq:i:o:")) != -1) { + while ((ch = getopt(argc, argv, "pfhvsq:i:o:O:")) != -1) { switch (ch) { case 'p': profileResample = true; @@ -111,6 +113,9 @@ int main(int argc, char* argv[]) { case 'o': output_freq = atoi(optarg); break; + case 'O': + framesPerCall = atoi(optarg); + break; case '?': default: usage(progname); @@ -343,7 +348,14 @@ int main(int argc, char* argv[]) { if (gVerbose) { printf("resample() %u output frames\n", out_frames); } - resampler->resample((int*) output_vaddr, out_frames, &provider); + if (framesPerCall == 0 || framesPerCall > out_frames) { + framesPerCall = out_frames; + } + for (size_t i = 0; i < out_frames; ) { + size_t thisFrames = framesPerCall <= out_frames - i ? framesPerCall : out_frames - i; + resampler->resample((int*) output_vaddr + 2*i, thisFrames, &provider); + i += thisFrames; + } if (gVerbose) { printf("resample() complete\n"); } |