diff options
Diffstat (limited to 'include/media/stagefright')
23 files changed, 650 insertions, 51 deletions
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h index cba8a6b..e796ab3 100644 --- a/include/media/stagefright/ACodec.h +++ b/include/media/stagefright/ACodec.h @@ -43,7 +43,10 @@ struct ACodec : public AHierarchicalStateMachine { kWhatError = 'erro', kWhatComponentAllocated = 'cAll', kWhatComponentConfigured = 'cCon', + kWhatInputSurfaceCreated = 'isfc', + kWhatSignaledInputEOS = 'seos', kWhatBuffersAllocated = 'allc', + kWhatOMXDied = 'OMXd', }; ACodec(); @@ -54,8 +57,12 @@ struct ACodec : public AHierarchicalStateMachine { void signalResume(); void initiateShutdown(bool keepComponentAllocated = false); + void signalSetParameters(const sp<AMessage> &msg); + void signalEndOfInputStream(); + void initiateAllocateComponent(const sp<AMessage> &msg); void initiateConfigureComponent(const sp<AMessage> &msg); + void initiateCreateInputSurface(); void initiateStart(); void signalRequestIDRFrame(); @@ -91,6 +98,7 @@ private: struct ExecutingToIdleState; struct IdleToLoadedState; struct FlushingState; + struct DeathNotifier; enum { kWhatSetup = 'setu', @@ -103,8 +111,11 @@ private: kWhatDrainDeferredMessages = 'drai', kWhatAllocateComponent = 'allo', kWhatConfigureComponent = 'conf', + kWhatCreateInputSurface = 'cisf', + kWhatSignalEndOfInputStream = 'eois', kWhatStart = 'star', kWhatRequestIDRFrame = 'ridr', + kWhatSetParameters = 'setP', }; enum { @@ -113,7 +124,8 @@ private: }; enum { - kFlagIsSecure = 1, + kFlagIsSecure = 1, + kFlagPushBlankBuffersToNativeWindowOnShutdown = 2, }; struct BufferInfo { @@ -127,6 +139,7 @@ private: IOMX::buffer_id mBufferID; Status mStatus; + unsigned mDequeuedAt; sp<ABuffer> mData; sp<GraphicBuffer> mGraphicBuffer; @@ -171,7 +184,7 @@ private: bool mSentFormat; bool mIsEncoder; - + bool mUseMetadataOnEncoderOutput; bool mShutdownInProgress; // If "mKeepComponentAllocated" we only transition back to Loaded state @@ -183,11 +196,22 @@ private: bool mChannelMaskPresent; int32_t mChannelMask; + unsigned mDequeueCounter; + bool mStoreMetaDataInOutputBuffers; + int32_t mMetaDataBuffersToSubmit; + + int64_t mRepeatFrameDelayUs; + status_t setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode); status_t allocateBuffersOnPort(OMX_U32 portIndex); status_t freeBuffersOnPort(OMX_U32 portIndex); status_t freeBuffer(OMX_U32 portIndex, size_t i); + status_t configureOutputBuffersFromNativeWindow( + OMX_U32 *nBufferCount, OMX_U32 *nBufferSize, + OMX_U32 *nMinUndequeuedBuffers); + status_t allocateOutputMetaDataBuffers(); + status_t submitOutputMetaDataBuffer(); status_t allocateOutputBuffersFromNativeWindow(); status_t cancelBufferToNativeWindow(BufferInfo *info); status_t freeOutputBuffersNotOwnedByComponent(); @@ -240,6 +264,7 @@ private: status_t setupMPEG4EncoderParameters(const sp<AMessage> &msg); status_t setupH263EncoderParameters(const sp<AMessage> &msg); status_t setupAVCEncoderParameters(const sp<AMessage> &msg); + status_t setupVPXEncoderParameters(const sp<AMessage> &msg); status_t verifySupportForProfileAndLevel(int32_t profile, int32_t level); @@ -252,23 +277,31 @@ private: status_t pushBlankBuffersToNativeWindow(); - // Returns true iff all buffers on the given port have status OWNED_BY_US. + // Returns true iff all buffers on the given port have status + // OWNED_BY_US or OWNED_BY_NATIVE_WINDOW. bool allYourBuffersAreBelongToUs(OMX_U32 portIndex); bool allYourBuffersAreBelongToUs(); + void waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs(); + size_t countBuffersOwnedByComponent(OMX_U32 portIndex) const; + size_t countBuffersOwnedByNativeWindow() const; void deferMessage(const sp<AMessage> &msg); void processDeferredMessages(); - void sendFormatChange(); + void sendFormatChange(const sp<AMessage> &reply); void signalError( OMX_ERRORTYPE error = OMX_ErrorUndefined, status_t internalError = UNKNOWN_ERROR); status_t requestIDRFrame(); + status_t setParameters(const sp<AMessage> ¶ms); + + // Send EOS on input stream. + void onSignalEndOfInputStream(); DISALLOW_EVIL_CONSTRUCTORS(ACodec); }; diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h index 1dc408f..14afb85 100644 --- a/include/media/stagefright/AudioPlayer.h +++ b/include/media/stagefright/AudioPlayer.h @@ -36,8 +36,16 @@ public: SEEK_COMPLETE }; + enum { + ALLOW_DEEP_BUFFERING = 0x01, + USE_OFFLOAD = 0x02, + HAS_VIDEO = 0x1000, + IS_STREAMING = 0x2000 + + }; + AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink, - bool allowDeepBuffering = false, + uint32_t flags = 0, AwesomePlayer *audioObserver = NULL); virtual ~AudioPlayer(); @@ -51,7 +59,7 @@ public: status_t start(bool sourceAlreadyStarted = false); void pause(bool playPendingSamples = false); - void resume(); + status_t resume(); // Returns the timestamp of the last buffer played (in us). int64_t getMediaTimeUs(); @@ -67,10 +75,12 @@ public: status_t setPlaybackRatePermille(int32_t ratePermille); + void notifyAudioEOS(); + private: friend class VideoEditorAudioPlayer; sp<MediaSource> mSource; - AudioTrack *mAudioTrack; + sp<AudioTrack> mAudioTrack; MediaBuffer *mInputBuffer; @@ -97,17 +107,20 @@ private: MediaBuffer *mFirstBuffer; sp<MediaPlayerBase::AudioSink> mAudioSink; - bool mAllowDeepBuffering; // allow audio deep audio buffers. Helps with low power audio - // playback but implies high latency AwesomePlayer *mObserver; int64_t mPinnedTimeUs; + bool mPlaying; + int64_t mStartPosUs; + const uint32_t mCreateFlags; + static void AudioCallback(int event, void *user, void *info); void AudioCallback(int event, void *info); static size_t AudioSinkCallback( MediaPlayerBase::AudioSink *audioSink, - void *data, size_t size, void *me); + void *data, size_t size, void *me, + MediaPlayerBase::AudioSink::cb_event_t event); size_t fillBuffer(void *data, size_t size); @@ -116,6 +129,10 @@ private: void reset(); uint32_t getNumFramesPendingPlayout() const; + int64_t getOutputPlayPositionUs_l(); + + bool allowDeepBuffering() const { return (mCreateFlags & ALLOW_DEEP_BUFFERING) != 0; } + bool useOffload() const { return (mCreateFlags & USE_OFFLOAD) != 0; } AudioPlayer(const AudioPlayer &); AudioPlayer &operator=(const AudioPlayer &); diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h index 99f3c3b..4c9aaad 100644 --- a/include/media/stagefright/AudioSource.h +++ b/include/media/stagefright/AudioSource.h @@ -73,7 +73,7 @@ private: Condition mFrameAvailableCondition; Condition mFrameEncodingCompletionCondition; - AudioRecord *mRecord; + sp<AudioRecord> mRecord; status_t mInitCheck; bool mStarted; int32_t mSampleRate; diff --git a/include/media/stagefright/BufferProducerWrapper.h b/include/media/stagefright/BufferProducerWrapper.h new file mode 100644 index 0000000..d8acf30 --- /dev/null +++ b/include/media/stagefright/BufferProducerWrapper.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2013 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 BUFFER_PRODUCER_WRAPPER_H_ + +#define BUFFER_PRODUCER_WRAPPER_H_ + +#include <gui/IGraphicBufferProducer.h> + +namespace android { + +// Can't use static_cast to cast a RefBase back to an IGraphicBufferProducer, +// because IGBP's parent (IInterface) uses virtual inheritance. This class +// wraps IGBP while we pass it through AMessage. + +struct BufferProducerWrapper : RefBase { + BufferProducerWrapper( + const sp<IGraphicBufferProducer>& bufferProducer) : + mBufferProducer(bufferProducer) { } + + sp<IGraphicBufferProducer> getBufferProducer() const { + return mBufferProducer; + } + +private: + const sp<IGraphicBufferProducer> mBufferProducer; + + DISALLOW_EVIL_CONSTRUCTORS(BufferProducerWrapper); +}; + +} // namespace android + +#endif // BUFFER_PRODUCER_WRAPPER_H_ diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h index 6d6b8a9..a829916 100644 --- a/include/media/stagefright/CameraSource.h +++ b/include/media/stagefright/CameraSource.h @@ -25,6 +25,7 @@ #include <camera/CameraParameters.h> #include <utils/List.h> #include <utils/RefBase.h> +#include <utils/String16.h> namespace android { @@ -39,9 +40,11 @@ public: * settings (such as video size, frame rate, color format, etc) * from the default camera. * + * @param clientName The package/process name of the client application. + * This is used for permissions checking. * @return NULL on error. */ - static CameraSource *Create(); + static CameraSource *Create(const String16 &clientName); /** * Factory method to create a new CameraSource. @@ -52,7 +55,11 @@ public: * * @param cameraId the id of the camera that the source will connect * to if camera is NULL; otherwise ignored. - * + * @param clientName the package/process name of the camera-using + * application if camera is NULL; otherwise ignored. Used for + * permissions checking. + * @param clientUid the UID of the camera-using application if camera is + * NULL; otherwise ignored. Used for permissions checking. * @param videoSize the dimension (in pixels) of the video frame * @param frameRate the target frames per second * @param surface the preview surface for display where preview @@ -71,9 +78,11 @@ public: static CameraSource *CreateFromCamera(const sp<ICamera> &camera, const sp<ICameraRecordingProxy> &proxy, int32_t cameraId, + const String16& clientName, + uid_t clientUid, Size videoSize, int32_t frameRate, - const sp<Surface>& surface, + const sp<IGraphicBufferProducer>& surface, bool storeMetaDataInVideoBuffers = false); virtual ~CameraSource(); @@ -145,7 +154,7 @@ protected: sp<Camera> mCamera; sp<ICameraRecordingProxy> mCameraRecordingProxy; sp<DeathNotifier> mDeathNotifier; - sp<Surface> mSurface; + sp<IGraphicBufferProducer> mSurface; sp<MetaData> mMeta; int64_t mStartTimeUs; @@ -158,9 +167,9 @@ protected: int64_t mTimeBetweenFrameCaptureUs; CameraSource(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy, - int32_t cameraId, + int32_t cameraId, const String16& clientName, uid_t clientUid, Size videoSize, int32_t frameRate, - const sp<Surface>& surface, + const sp<IGraphicBufferProducer>& surface, bool storeMetaDataInVideoBuffers); virtual void startCameraRecording(); @@ -198,17 +207,20 @@ private: status_t init(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy, - int32_t cameraId, Size videoSize, int32_t frameRate, - bool storeMetaDataInVideoBuffers); + int32_t cameraId, const String16& clientName, uid_t clientUid, + Size videoSize, int32_t frameRate, bool storeMetaDataInVideoBuffers); status_t initWithCameraAccess( const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy, - int32_t cameraId, Size videoSize, int32_t frameRate, - bool storeMetaDataInVideoBuffers); + int32_t cameraId, const String16& clientName, uid_t clientUid, + Size videoSize, int32_t frameRate, bool storeMetaDataInVideoBuffers); status_t isCameraAvailable(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy, - int32_t cameraId); + int32_t cameraId, + const String16& clientName, + uid_t clientUid); + status_t isCameraColorFormatSupported(const CameraParameters& params); status_t configureCamera(CameraParameters* params, int32_t width, int32_t height, diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h index 0936da2..34213be 100644 --- a/include/media/stagefright/CameraSourceTimeLapse.h +++ b/include/media/stagefright/CameraSourceTimeLapse.h @@ -22,6 +22,7 @@ #include <utils/RefBase.h> #include <utils/threads.h> +#include <utils/String16.h> namespace android { @@ -35,10 +36,13 @@ public: const sp<ICamera> &camera, const sp<ICameraRecordingProxy> &proxy, int32_t cameraId, + const String16& clientName, + uid_t clientUid, Size videoSize, int32_t videoFrameRate, - const sp<Surface>& surface, - int64_t timeBetweenTimeLapseFrameCaptureUs); + const sp<IGraphicBufferProducer>& surface, + int64_t timeBetweenTimeLapseFrameCaptureUs, + bool storeMetaDataInVideoBuffers = true); virtual ~CameraSourceTimeLapse(); @@ -108,10 +112,13 @@ private: const sp<ICamera> &camera, const sp<ICameraRecordingProxy> &proxy, int32_t cameraId, + const String16& clientName, + uid_t clientUid, Size videoSize, int32_t videoFrameRate, - const sp<Surface>& surface, - int64_t timeBetweenTimeLapseFrameCaptureUs); + const sp<IGraphicBufferProducer>& surface, + int64_t timeBetweenTimeLapseFrameCaptureUs, + bool storeMetaDataInVideoBuffers = true); // Wrapper over CameraSource::signalBufferReturned() to implement quick stop. // It only handles the case when mLastReadBufferCopy is signalled. Otherwise diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h index 00d583e..157b1aa 100644 --- a/include/media/stagefright/DataSource.h +++ b/include/media/stagefright/DataSource.h @@ -54,6 +54,9 @@ public: // Convenience methods: bool getUInt16(off64_t offset, uint16_t *x); + bool getUInt24(off64_t offset, uint32_t *x); // 3 byte int, returned as a 32-bit int + bool getUInt32(off64_t offset, uint32_t *x); + bool getUInt64(off64_t offset, uint64_t *x); // May return ERROR_UNSUPPORTED. virtual status_t getSize(off64_t *size); @@ -77,7 +80,6 @@ public: const sp<DataSource> &source, String8 *mimeType, float *confidence, sp<AMessage> *meta); - static void RegisterSniffer(SnifferFunc func); static void RegisterDefaultSniffers(); // for DRM @@ -98,6 +100,9 @@ protected: private: static Mutex gSnifferMutex; static List<SnifferFunc> gSniffers; + static bool gSniffersRegistered; + + static void RegisterSniffer_l(SnifferFunc func); DataSource(const DataSource &); DataSource &operator=(const DataSource &); diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h index 3596b38..3ef6b9a 100644 --- a/include/media/stagefright/MPEG4Writer.h +++ b/include/media/stagefright/MPEG4Writer.h @@ -35,7 +35,13 @@ public: MPEG4Writer(const char *filename); MPEG4Writer(int fd); + // Limitations + // 1. No more than 2 tracks can be added + // 2. Only video or audio source can be added + // 3. No more than one video and/or one audio source can be added. virtual status_t addSource(const sp<MediaSource> &source); + + // Returns INVALID_OPERATION if there is no source or track. virtual status_t start(MetaData *param = NULL); virtual status_t stop() { return reset(); } virtual status_t pause(); @@ -68,6 +74,7 @@ private: int mFd; status_t mInitCheck; + bool mIsRealTimeRecording; bool mUse4ByteNalLength; bool mUse32BitOffset; bool mIsFileSizeLimitExplicitlyRequested; @@ -162,6 +169,13 @@ private: // Only makes sense for H.264/AVC bool useNalLengthFour(); + // Return whether the writer is used for real time recording. + // In real time recording mode, new samples will be allowed to buffered into + // chunks in higher priority thread, even though the file writer has not + // drained the chunks yet. + // By default, real time recording is on. + bool isRealTimeRecording() const; + void lock(); void unlock(); diff --git a/include/media/stagefright/MediaAdapter.h b/include/media/stagefright/MediaAdapter.h new file mode 100644 index 0000000..369fce6 --- /dev/null +++ b/include/media/stagefright/MediaAdapter.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MEDIA_ADAPTER_H +#define MEDIA_ADAPTER_H + +#include <media/stagefright/foundation/ABase.h> +#include <media/stagefright/MediaSource.h> +#include <media/stagefright/MediaBuffer.h> +#include <media/stagefright/MetaData.h> +#include <utils/threads.h> + +namespace android { + +// Convert the MediaMuxer's push model into MPEG4Writer's pull model. +// Used only by the MediaMuxer for now. +struct MediaAdapter : public MediaSource, public MediaBufferObserver { +public: + // MetaData is used to set the format and returned at getFormat. + MediaAdapter(const sp<MetaData> &meta); + virtual ~MediaAdapter(); + ///////////////////////////////////////////////// + // Inherited functions from MediaSource + ///////////////////////////////////////////////// + + virtual status_t start(MetaData *params = NULL); + virtual status_t stop(); + virtual sp<MetaData> getFormat(); + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options = NULL); + + ///////////////////////////////////////////////// + // Inherited functions from MediaBufferObserver + ///////////////////////////////////////////////// + + virtual void signalBufferReturned(MediaBuffer *buffer); + + ///////////////////////////////////////////////// + // Non-inherited functions: + ///////////////////////////////////////////////// + + // pushBuffer() will wait for the read() finish, and read() will have a + // deep copy, such that after pushBuffer return, the buffer can be re-used. + status_t pushBuffer(MediaBuffer *buffer); + +private: + Mutex mAdapterLock; + // Make sure the read() wait for the incoming buffer. + Condition mBufferReadCond; + // Make sure the pushBuffer() wait for the current buffer consumed. + Condition mBufferReturnedCond; + + MediaBuffer *mCurrentMediaBuffer; + + bool mStarted; + sp<MetaData> mOutputFormat; + + DISALLOW_EVIL_CONSTRUCTORS(MediaAdapter); +}; + +} // namespace android + +#endif // MEDIA_ADAPTER_H diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h index b1e57cf..76aa503 100644 --- a/include/media/stagefright/MediaCodec.h +++ b/include/media/stagefright/MediaCodec.h @@ -18,7 +18,7 @@ #define MEDIA_CODEC_H_ -#include <gui/ISurfaceTexture.h> +#include <gui/IGraphicBufferProducer.h> #include <media/hardware/CryptoAPI.h> #include <media/stagefright/foundation/AHandler.h> #include <utils/Vector.h> @@ -31,7 +31,7 @@ struct AMessage; struct AString; struct ICrypto; struct SoftwareRenderer; -struct SurfaceTextureClient; +struct Surface; struct MediaCodec : public AHandler { enum ConfigureFlags { @@ -52,10 +52,12 @@ struct MediaCodec : public AHandler { status_t configure( const sp<AMessage> &format, - const sp<SurfaceTextureClient> &nativeWindow, + const sp<Surface> &nativeWindow, const sp<ICrypto> &crypto, uint32_t flags); + status_t createInputSurface(sp<IGraphicBufferProducer>* bufferProducer); + status_t start(); // Returns to a state in which the component remains allocated but @@ -101,6 +103,8 @@ struct MediaCodec : public AHandler { status_t renderOutputBufferAndRelease(size_t index); status_t releaseOutputBuffer(size_t index); + status_t signalEndOfInputStream(); + status_t getOutputFormat(sp<AMessage> *format) const; status_t getInputBuffers(Vector<sp<ABuffer> > *buffers) const; @@ -115,6 +119,8 @@ struct MediaCodec : public AHandler { status_t getName(AString *componentName) const; + status_t setParameters(const sp<AMessage> ¶ms); + protected: virtual ~MediaCodec(); virtual void onMessageReceived(const sp<AMessage> &msg); @@ -141,6 +147,7 @@ private: enum { kWhatInit = 'init', kWhatConfigure = 'conf', + kWhatCreateInputSurface = 'cisf', kWhatStart = 'strt', kWhatStop = 'stop', kWhatRelease = 'rele', @@ -148,6 +155,7 @@ private: kWhatQueueInputBuffer = 'queI', kWhatDequeueOutputBuffer = 'deqO', kWhatReleaseOutputBuffer = 'relO', + kWhatSignalEndOfInputStream = 'eois', kWhatGetBuffers = 'getB', kWhatFlush = 'flus', kWhatGetOutputFormat = 'getO', @@ -157,6 +165,7 @@ private: kWhatRequestIDRFrame = 'ridr', kWhatRequestActivityNotification = 'racN', kWhatGetName = 'getN', + kWhatSetParameters = 'setP', }; enum { @@ -167,6 +176,9 @@ private: kFlagDequeueInputPending = 16, kFlagDequeueOutputPending = 32, kFlagIsSecure = 64, + kFlagSawMediaServerDie = 128, + kFlagIsEncoder = 256, + kFlagGatherCodecSpecificData = 512, }; struct BufferInfo { @@ -184,7 +196,7 @@ private: AString mComponentName; uint32_t mReplyID; uint32_t mFlags; - sp<SurfaceTextureClient> mNativeWindow; + sp<Surface> mNativeWindow; SoftwareRenderer *mSoftRenderer; sp<AMessage> mOutputFormat; @@ -203,6 +215,8 @@ private: sp<AMessage> mActivityNotify; + bool mHaveInputSurface; + MediaCodec(const sp<ALooper> &looper); static status_t PostAndAwaitResponse( @@ -226,10 +240,14 @@ private: status_t queueCSDInputBuffer(size_t bufferIndex); status_t setNativeWindow( - const sp<SurfaceTextureClient> &surfaceTextureClient); + const sp<Surface> &surface); void postActivityNotificationIfPossible(); + status_t onSetParameters(const sp<AMessage> ¶ms); + + status_t amendOutputFormatWithCodecSpecificData(const sp<ABuffer> &buffer); + DISALLOW_EVIL_CONSTRUCTORS(MediaCodec); }; diff --git a/include/media/stagefright/MediaCodecList.h b/include/media/stagefright/MediaCodecList.h index dfb845b..590623b 100644 --- a/include/media/stagefright/MediaCodecList.h +++ b/include/media/stagefright/MediaCodecList.h @@ -50,7 +50,8 @@ struct MediaCodecList { status_t getCodecCapabilities( size_t index, const char *type, Vector<ProfileLevel> *profileLevels, - Vector<uint32_t> *colorFormats) const; + Vector<uint32_t> *colorFormats, + uint32_t *flags) const; private: enum Section { diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h index 457d5d7..85693d4 100644 --- a/include/media/stagefright/MediaDefs.h +++ b/include/media/stagefright/MediaDefs.h @@ -22,7 +22,8 @@ namespace android { extern const char *MEDIA_MIMETYPE_IMAGE_JPEG; -extern const char *MEDIA_MIMETYPE_VIDEO_VPX; +extern const char *MEDIA_MIMETYPE_VIDEO_VP8; +extern const char *MEDIA_MIMETYPE_VIDEO_VP9; extern const char *MEDIA_MIMETYPE_VIDEO_AVC; extern const char *MEDIA_MIMETYPE_VIDEO_MPEG4; extern const char *MEDIA_MIMETYPE_VIDEO_H263; @@ -42,6 +43,7 @@ extern const char *MEDIA_MIMETYPE_AUDIO_G711_MLAW; extern const char *MEDIA_MIMETYPE_AUDIO_RAW; extern const char *MEDIA_MIMETYPE_AUDIO_FLAC; extern const char *MEDIA_MIMETYPE_AUDIO_AAC_ADTS; +extern const char *MEDIA_MIMETYPE_AUDIO_MSGSM; extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG4; extern const char *MEDIA_MIMETYPE_CONTAINER_WAV; diff --git a/include/media/stagefright/MediaErrors.h b/include/media/stagefright/MediaErrors.h index bb01467..686f286 100644 --- a/include/media/stagefright/MediaErrors.h +++ b/include/media/stagefright/MediaErrors.h @@ -54,14 +54,13 @@ enum { ERROR_DRM_DECRYPT = DRM_ERROR_BASE - 5, ERROR_DRM_CANNOT_HANDLE = DRM_ERROR_BASE - 6, ERROR_DRM_TAMPER_DETECTED = DRM_ERROR_BASE - 7, + ERROR_DRM_NOT_PROVISIONED = DRM_ERROR_BASE - 8, + ERROR_DRM_DEVICE_REVOKED = DRM_ERROR_BASE - 9, + ERROR_DRM_RESOURCE_BUSY = DRM_ERROR_BASE - 10, ERROR_DRM_VENDOR_MAX = DRM_ERROR_BASE - 500, ERROR_DRM_VENDOR_MIN = DRM_ERROR_BASE - 999, - // Deprecated - ERROR_DRM_WV_VENDOR_MAX = ERROR_DRM_VENDOR_MAX, - ERROR_DRM_WV_VENDOR_MIN = ERROR_DRM_VENDOR_MIN, - // Heartbeat Error Codes HEARTBEAT_ERROR_BASE = -3000, ERROR_HEARTBEAT_TERMINATE_REQUESTED = HEARTBEAT_ERROR_BASE, diff --git a/include/media/stagefright/MediaMuxer.h b/include/media/stagefright/MediaMuxer.h new file mode 100644 index 0000000..ff6a66e --- /dev/null +++ b/include/media/stagefright/MediaMuxer.h @@ -0,0 +1,138 @@ +/* + * Copyright 2013, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MEDIA_MUXER_H_ +#define MEDIA_MUXER_H_ + +#include <utils/Errors.h> +#include <utils/RefBase.h> +#include <utils/Vector.h> +#include <utils/threads.h> + +namespace android { + +struct ABuffer; +struct AMessage; +struct MediaAdapter; +struct MediaBuffer; +struct MediaSource; +struct MetaData; +struct MPEG4Writer; + +// MediaMuxer is used to mux multiple tracks into a video. Currently, we only +// support a mp4 file as the output. +// The expected calling order of the functions is: +// Constructor -> addTrack+ -> start -> writeSampleData+ -> stop +// If muxing operation need to be cancelled, the app is responsible for +// deleting the output file after stop. +struct MediaMuxer : public RefBase { +public: + // Please update media/java/android/media/MediaMuxer.java if the + // OutputFormat is updated. + enum OutputFormat { + OUTPUT_FORMAT_MPEG_4 = 0, + OUTPUT_FORMAT_LIST_END // must be last - used to validate format type + }; + + // Construct the muxer with the output file path. + MediaMuxer(const char *path, OutputFormat format); + + // Construct the muxer with the file descriptor. Note that the MediaMuxer + // will close this file at stop(). + MediaMuxer(int fd, OutputFormat format); + + virtual ~MediaMuxer(); + + /** + * Add a track with its format information. This should be + * called before start(). + * @param format the track's format. + * @return the track's index or negative number if error. + */ + ssize_t addTrack(const sp<AMessage> &format); + + /** + * Start muxing. Make sure all the tracks have been added before + * calling this. + */ + status_t start(); + + /** + * Set the orientation hint. + * @param degrees The rotation degrees. It has to be either 0, + * 90, 180 or 270. + * @return OK if no error. + */ + status_t setOrientationHint(int degrees); + + /** + * Set the location. + * @param latitude The latitude in degree x 1000. Its value must be in the range + * [-900000, 900000]. + * @param longitude The longitude in degree x 1000. Its value must be in the range + * [-1800000, 1800000]. + * @return OK if no error. + */ + status_t setLocation(int latitude, int longitude); + + /** + * Stop muxing. + * This method is a blocking call. Depending on how + * much data is bufferred internally, the time needed for stopping + * the muxer may be time consuming. UI thread is + * not recommended for launching this call. + * @return OK if no error. + */ + status_t stop(); + + /** + * Send a sample buffer for muxing. + * The buffer can be reused once this method returns. Typically, + * this function won't be blocked for very long, and thus there + * is no need to use a separate thread calling this method to + * push a buffer. + * @param buffer the incoming sample buffer. + * @param trackIndex the buffer's track index number. + * @param timeUs the buffer's time stamp. + * @param flags the only supported flag for now is + * MediaCodec::BUFFER_FLAG_SYNCFRAME. + * @return OK if no error. + */ + status_t writeSampleData(const sp<ABuffer> &buffer, size_t trackIndex, + int64_t timeUs, uint32_t flags) ; + +private: + sp<MPEG4Writer> mWriter; + Vector< sp<MediaAdapter> > mTrackList; // Each track has its MediaAdapter. + sp<MetaData> mFileMeta; // Metadata for the whole file. + + Mutex mMuxerLock; + + enum State { + UNINITIALIZED, + INITIALIZED, + STARTED, + STOPPED + }; + State mState; + + DISALLOW_EVIL_CONSTRUCTORS(MediaMuxer); +}; + +} // namespace android + +#endif // MEDIA_MUXER_H_ + diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h index e91904c..db8216b 100644 --- a/include/media/stagefright/MetaData.h +++ b/include/media/stagefright/MetaData.h @@ -35,6 +35,8 @@ enum { kKeyHeight = 'heig', // int32_t, image pixel kKeyDisplayWidth = 'dWid', // int32_t, display/presentation kKeyDisplayHeight = 'dHgt', // int32_t, display/presentation + kKeySARWidth = 'sarW', // int32_t, sampleAspectRatio width + kKeySARHeight = 'sarH', // int32_t, sampleAspectRatio height // a rectangle, if absent assumed to be (0, 0, width - 1, height - 1) kKeyCropRect = 'crop', @@ -110,7 +112,7 @@ enum { // kKeyTrackTimeStatus is used to track progress in elapsed time kKeyTrackTimeStatus = 'tktm', // int64_t - kKeyNotRealTime = 'ntrt', // bool (int32_t) + kKeyRealTimeRecording = 'rtrc', // bool (int32_t) kKeyNumBuffers = 'nbbf', // int32_t // Ogg files can be tagged to be automatically looping... @@ -132,6 +134,7 @@ enum { kKeyRequiresSecureBuffers = 'secu', // bool (int32_t) kKeyIsADTS = 'adts', // bool (int32_t) + kKeyAACAOT = 'aaot', // int32_t // If a MediaBuffer's data represents (at least partially) encrypted // data, the following fields aid in decryption. @@ -155,6 +158,10 @@ enum { kKeyCryptoKey = 'cryK', // uint8_t[16] kKeyCryptoIV = 'cryI', // uint8_t[16] kKeyCryptoMode = 'cryM', // int32_t + + kKeyCryptoDefaultIVSize = 'cryS', // int32_t + + kKeyPssh = 'pssh', // raw data }; enum { @@ -208,6 +215,8 @@ public: bool findData(uint32_t key, uint32_t *type, const void **data, size_t *size) const; + bool hasData(uint32_t key) const; + void dumpToLog() const; protected: diff --git a/include/media/stagefright/NativeWindowWrapper.h b/include/media/stagefright/NativeWindowWrapper.h index 97cc0ce..cfeec22 100644 --- a/include/media/stagefright/NativeWindowWrapper.h +++ b/include/media/stagefright/NativeWindowWrapper.h @@ -18,29 +18,29 @@ #define NATIVE_WINDOW_WRAPPER_H_ -#include <gui/SurfaceTextureClient.h> +#include <gui/Surface.h> namespace android { -// SurfaceTextureClient derives from ANativeWindow which derives from multiple +// Surface derives from ANativeWindow which derives from multiple // base classes, in order to carry it in AMessages, we'll temporarily wrap it // into a NativeWindowWrapper. struct NativeWindowWrapper : RefBase { NativeWindowWrapper( - const sp<SurfaceTextureClient> &surfaceTextureClient) : + const sp<Surface> &surfaceTextureClient) : mSurfaceTextureClient(surfaceTextureClient) { } sp<ANativeWindow> getNativeWindow() const { return mSurfaceTextureClient; } - sp<SurfaceTextureClient> getSurfaceTextureClient() const { + sp<Surface> getSurfaceTextureClient() const { return mSurfaceTextureClient; } private: - const sp<SurfaceTextureClient> mSurfaceTextureClient; + const sp<Surface> mSurfaceTextureClient; DISALLOW_EVIL_CONSTRUCTORS(NativeWindowWrapper); }; diff --git a/include/media/stagefright/NuMediaExtractor.h b/include/media/stagefright/NuMediaExtractor.h index 0833110..5ae6f6b 100644 --- a/include/media/stagefright/NuMediaExtractor.h +++ b/include/media/stagefright/NuMediaExtractor.h @@ -55,6 +55,8 @@ struct NuMediaExtractor : public RefBase { size_t countTracks() const; status_t getTrackFormat(size_t index, sp<AMessage> *format) const; + status_t getFileFormat(sp<AMessage> *format) const; + status_t selectTrack(size_t index); status_t unselectTrack(size_t index); diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h index 583c3b3..daaf20f 100644 --- a/include/media/stagefright/OMXCodec.h +++ b/include/media/stagefright/OMXCodec.h @@ -361,9 +361,14 @@ private: }; struct CodecCapabilities { + enum { + kFlagSupportsAdaptivePlayback = 1 << 0, + }; + String8 mComponentName; Vector<CodecProfileLevel> mProfileLevels; Vector<OMX_U32> mColorFormats; + uint32_t mFlags; }; // Return a vector of componentNames with supported profile/level pairs diff --git a/include/media/stagefright/SurfaceMediaSource.h b/include/media/stagefright/SurfaceMediaSource.h index e56527d..db5f947 100644 --- a/include/media/stagefright/SurfaceMediaSource.h +++ b/include/media/stagefright/SurfaceMediaSource.h @@ -17,7 +17,7 @@ #ifndef ANDROID_GUI_SURFACEMEDIASOURCE_H #define ANDROID_GUI_SURFACEMEDIASOURCE_H -#include <gui/ISurfaceTexture.h> +#include <gui/IGraphicBufferProducer.h> #include <gui/BufferQueue.h> #include <utils/threads.h> @@ -35,7 +35,7 @@ class GraphicBuffer; // ASSUMPTIONS // 1. SurfaceMediaSource is initialized with width*height which // can never change. However, deqeueue buffer does not currently -// enforce this as in BufferQueue, dequeue can be used by SurfaceTexture +// enforce this as in BufferQueue, dequeue can be used by Surface // which can modify the default width and heght. Also neither the width // nor height can be 0. // 2. setSynchronousMode is never used (basically no one should call @@ -56,7 +56,7 @@ class GraphicBuffer; class SurfaceMediaSource : public MediaSource, public MediaBufferObserver, - protected BufferQueue::ConsumerListener { + protected ConsumerListener { public: enum { MIN_UNDEQUEUED_BUFFERS = 4}; @@ -122,7 +122,7 @@ public: protected: // Implementation of the BufferQueue::ConsumerListener interface. These - // calls are used to notify the SurfaceTexture of asynchronous events in the + // calls are used to notify the Surface of asynchronous events in the // BufferQueue. virtual void onFrameAvailable(); @@ -146,9 +146,13 @@ private: // this consumer sp<BufferQueue> mBufferQueue; - // mBufferSlot caches GraphicBuffers from the buffer queue - sp<GraphicBuffer> mBufferSlot[BufferQueue::NUM_BUFFER_SLOTS]; + struct SlotData { + sp<GraphicBuffer> mGraphicBuffer; + uint64_t mFrameNumber; + }; + // mSlots caches GraphicBuffers and frameNumbers from the buffer queue + SlotData mSlots[BufferQueue::NUM_BUFFER_SLOTS]; // The permenent width and height of SMS buffers int mWidth; @@ -157,7 +161,7 @@ private: // mCurrentSlot is the buffer slot index of the buffer that is currently // being used by buffer consumer // (e.g. StageFrightRecorder in the case of SurfaceMediaSource or GLTexture - // in the case of SurfaceTexture). + // in the case of Surface). // It is initialized to INVALID_BUFFER_SLOT, // indicating that no buffer slot is currently bound to the texture. Note, // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean diff --git a/include/media/stagefright/Utils.h b/include/media/stagefright/Utils.h index 8213af9..bbad271 100644 --- a/include/media/stagefright/Utils.h +++ b/include/media/stagefright/Utils.h @@ -18,9 +18,12 @@ #define UTILS_H_ +#include <media/stagefright/foundation/AString.h> #include <stdint.h> #include <utils/Errors.h> #include <utils/RefBase.h> +#include <system/audio.h> +#include <media/MediaPlayerInterface.h> namespace android { @@ -45,6 +48,18 @@ status_t convertMetaDataToMessage( void convertMessageToMetaData( const sp<AMessage> &format, sp<MetaData> &meta); +AString MakeUserAgent(); + +// Convert a MIME type to a AudioSystem::audio_format +status_t mapMimeToAudioFormat(audio_format_t& format, const char* mime); + +// Send information from MetaData to the HAL via AudioSink +status_t sendMetaDataToHal(sp<MediaPlayerBase::AudioSink>& sink, const sp<MetaData>& meta); + +// Check whether the stream defined by meta can be offloaded to hardware +bool canOffloadStream(const sp<MetaData>& meta, bool hasVideo, + bool isStreaming, audio_stream_type_t streamType); + } // namespace android #endif // UTILS_H_ diff --git a/include/media/stagefright/foundation/ALooperRoster.h b/include/media/stagefright/foundation/ALooperRoster.h index 2e5fd73..940fc55 100644 --- a/include/media/stagefright/foundation/ALooperRoster.h +++ b/include/media/stagefright/foundation/ALooperRoster.h @@ -30,6 +30,7 @@ struct ALooperRoster { const sp<ALooper> looper, const sp<AHandler> &handler); void unregisterHandler(ALooper::handler_id handlerID); + void unregisterStaleHandlers(); status_t postMessage(const sp<AMessage> &msg, int64_t delayUs = 0); void deliverMessage(const sp<AMessage> &msg); diff --git a/include/media/stagefright/foundation/ANetworkSession.h b/include/media/stagefright/foundation/ANetworkSession.h new file mode 100644 index 0000000..fd3ebaa --- /dev/null +++ b/include/media/stagefright/foundation/ANetworkSession.h @@ -0,0 +1,135 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef A_NETWORK_SESSION_H_ + +#define A_NETWORK_SESSION_H_ + +#include <media/stagefright/foundation/ABase.h> +#include <utils/KeyedVector.h> +#include <utils/RefBase.h> +#include <utils/Thread.h> + +#include <netinet/in.h> + +namespace android { + +struct AMessage; + +// Helper class to manage a number of live sockets (datagram and stream-based) +// on a single thread. Clients are notified about activity through AMessages. +struct ANetworkSession : public RefBase { + ANetworkSession(); + + status_t start(); + status_t stop(); + + status_t createRTSPClient( + const char *host, unsigned port, const sp<AMessage> ¬ify, + int32_t *sessionID); + + status_t createRTSPServer( + const struct in_addr &addr, unsigned port, + const sp<AMessage> ¬ify, int32_t *sessionID); + + status_t createUDPSession( + unsigned localPort, const sp<AMessage> ¬ify, int32_t *sessionID); + + status_t createUDPSession( + unsigned localPort, + const char *remoteHost, + unsigned remotePort, + const sp<AMessage> ¬ify, + int32_t *sessionID); + + status_t connectUDPSession( + int32_t sessionID, const char *remoteHost, unsigned remotePort); + + // passive + status_t createTCPDatagramSession( + const struct in_addr &addr, unsigned port, + const sp<AMessage> ¬ify, int32_t *sessionID); + + // active + status_t createTCPDatagramSession( + unsigned localPort, + const char *remoteHost, + unsigned remotePort, + const sp<AMessage> ¬ify, + int32_t *sessionID); + + status_t destroySession(int32_t sessionID); + + status_t sendRequest( + int32_t sessionID, const void *data, ssize_t size = -1, + bool timeValid = false, int64_t timeUs = -1ll); + + status_t switchToWebSocketMode(int32_t sessionID); + + enum NotificationReason { + kWhatError, + kWhatConnected, + kWhatClientConnected, + kWhatData, + kWhatDatagram, + kWhatBinaryData, + kWhatWebSocketMessage, + kWhatNetworkStall, + }; + +protected: + virtual ~ANetworkSession(); + +private: + struct NetworkThread; + struct Session; + + Mutex mLock; + sp<Thread> mThread; + + int32_t mNextSessionID; + + int mPipeFd[2]; + + KeyedVector<int32_t, sp<Session> > mSessions; + + enum Mode { + kModeCreateUDPSession, + kModeCreateTCPDatagramSessionPassive, + kModeCreateTCPDatagramSessionActive, + kModeCreateRTSPServer, + kModeCreateRTSPClient, + }; + status_t createClientOrServer( + Mode mode, + const struct in_addr *addr, + unsigned port, + const char *remoteHost, + unsigned remotePort, + const sp<AMessage> ¬ify, + int32_t *sessionID); + + void threadLoop(); + void interrupt(); + + static status_t MakeSocketNonBlocking(int s); + + DISALLOW_EVIL_CONSTRUCTORS(ANetworkSession); +}; + +} // namespace android + +#endif // A_NETWORK_SESSION_H_ diff --git a/include/media/stagefright/foundation/ParsedMessage.h b/include/media/stagefright/foundation/ParsedMessage.h new file mode 100644 index 0000000..9d43a93 --- /dev/null +++ b/include/media/stagefright/foundation/ParsedMessage.h @@ -0,0 +1,60 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <media/stagefright/foundation/ABase.h> +#include <media/stagefright/foundation/AString.h> +#include <utils/KeyedVector.h> +#include <utils/RefBase.h> + +namespace android { + +// Encapsulates an "HTTP/RTSP style" response, i.e. a status line, +// key/value pairs making up the headers and an optional body/content. +struct ParsedMessage : public RefBase { + static sp<ParsedMessage> Parse( + const char *data, size_t size, bool noMoreData, size_t *length); + + bool findString(const char *name, AString *value) const; + bool findInt32(const char *name, int32_t *value) const; + + const char *getContent() const; + + bool getRequestField(size_t index, AString *field) const; + bool getStatusCode(int32_t *statusCode) const; + + AString debugString() const; + + static bool GetAttribute(const char *s, const char *key, AString *value); + + static bool GetInt32Attribute( + const char *s, const char *key, int32_t *value); + + +protected: + virtual ~ParsedMessage(); + +private: + KeyedVector<AString, AString> mDict; + AString mContent; + + ParsedMessage(); + + ssize_t parse(const char *data, size_t size, bool noMoreData); + + DISALLOW_EVIL_CONSTRUCTORS(ParsedMessage); +}; + +} // namespace android |