diff options
118 files changed, 1646 insertions, 917 deletions
diff --git a/camera/Camera.cpp b/camera/Camera.cpp index d43cb0b..3aaacaf 100644 --- a/camera/Camera.cpp +++ b/camera/Camera.cpp @@ -27,7 +27,7 @@ #include <camera/ICameraRecordingProxyListener.h> #include <camera/ICameraService.h> -#include <gui/ISurfaceTexture.h> +#include <gui/IGraphicBufferProducer.h> #include <gui/Surface.h> namespace android { @@ -184,14 +184,14 @@ status_t Camera::setPreviewDisplay(const sp<Surface>& surface) } } -// pass the buffered ISurfaceTexture to the camera service -status_t Camera::setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture) +// pass the buffered IGraphicBufferProducer to the camera service +status_t Camera::setPreviewTexture(const sp<IGraphicBufferProducer>& bufferProducer) { - ALOGV("setPreviewTexture(%p)", surfaceTexture.get()); + ALOGV("setPreviewTexture(%p)", bufferProducer.get()); sp <ICamera> c = mCamera; if (c == 0) return NO_INIT; - if (surfaceTexture != 0) { - return c->setPreviewTexture(surfaceTexture); + if (bufferProducer != 0) { + return c->setPreviewTexture(bufferProducer); } else { ALOGD("app passed NULL surface"); return c->setPreviewTexture(0); diff --git a/camera/ICamera.cpp b/camera/ICamera.cpp index 8d8408c..5d210e7 100644 --- a/camera/ICamera.cpp +++ b/camera/ICamera.cpp @@ -22,7 +22,7 @@ #include <sys/types.h> #include <binder/Parcel.h> #include <camera/ICamera.h> -#include <gui/ISurfaceTexture.h> +#include <gui/IGraphicBufferProducer.h> #include <gui/Surface.h> namespace android { @@ -79,13 +79,13 @@ public: return reply.readInt32(); } - // pass the buffered SurfaceTexture to the camera service - status_t setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture) + // pass the buffered IGraphicBufferProducer to the camera service + status_t setPreviewTexture(const sp<IGraphicBufferProducer>& bufferProducer) { ALOGV("setPreviewTexture"); Parcel data, reply; data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - sp<IBinder> b(surfaceTexture->asBinder()); + sp<IBinder> b(bufferProducer->asBinder()); data.writeStrongBinder(b); remote()->transact(SET_PREVIEW_TEXTURE, data, &reply); return reply.readInt32(); @@ -292,7 +292,8 @@ status_t BnCamera::onTransact( case SET_PREVIEW_TEXTURE: { ALOGV("SET_PREVIEW_TEXTURE"); CHECK_INTERFACE(ICamera, data, reply); - sp<ISurfaceTexture> st = interface_cast<ISurfaceTexture>(data.readStrongBinder()); + sp<IGraphicBufferProducer> st = + interface_cast<IGraphicBufferProducer>(data.readStrongBinder()); reply->writeInt32(setPreviewTexture(st)); return NO_ERROR; } break; diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk index f60b1a4..a59186a 100644 --- a/cmds/stagefright/Android.mk +++ b/cmds/stagefright/Android.mk @@ -9,7 +9,7 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := \ libstagefright libmedia libutils libbinder libstagefright_foundation \ - libjpeg libgui + libjpeg libgui libcutils LOCAL_C_INCLUDES:= \ frameworks/av/media/libstagefright \ diff --git a/cmds/stagefright/SimplePlayer.cpp b/cmds/stagefright/SimplePlayer.cpp index eb3296e..93de112 100644 --- a/cmds/stagefright/SimplePlayer.cpp +++ b/cmds/stagefright/SimplePlayer.cpp @@ -64,12 +64,12 @@ status_t SimplePlayer::setDataSource(const char *path) { return PostAndAwaitResponse(msg, &response); } -status_t SimplePlayer::setSurface(const sp<ISurfaceTexture> &surfaceTexture) { +status_t SimplePlayer::setSurface(const sp<IGraphicBufferProducer> &bufferProducer) { sp<AMessage> msg = new AMessage(kWhatSetSurface, id()); sp<SurfaceTextureClient> surfaceTextureClient; - if (surfaceTexture != NULL) { - surfaceTextureClient = new SurfaceTextureClient(surfaceTexture); + if (bufferProducer != NULL) { + surfaceTextureClient = new SurfaceTextureClient(bufferProducer); } msg->setObject( diff --git a/cmds/stagefright/SimplePlayer.h b/cmds/stagefright/SimplePlayer.h index 2548252..0a06059 100644 --- a/cmds/stagefright/SimplePlayer.h +++ b/cmds/stagefright/SimplePlayer.h @@ -23,7 +23,7 @@ namespace android { struct ABuffer; struct ALooper; struct AudioTrack; -struct ISurfaceTexture; +struct IGraphicBufferProducer; struct MediaCodec; struct NativeWindowWrapper; struct NuMediaExtractor; @@ -32,7 +32,7 @@ struct SimplePlayer : public AHandler { SimplePlayer(); status_t setDataSource(const char *path); - status_t setSurface(const sp<ISurfaceTexture> &surfaceTexture); + status_t setSurface(const sp<IGraphicBufferProducer> &bufferProducer); status_t prepare(); status_t start(); status_t stop(); diff --git a/cmds/stagefright/recordvideo.cpp b/cmds/stagefright/recordvideo.cpp index e02f111..c30c122 100644 --- a/cmds/stagefright/recordvideo.cpp +++ b/cmds/stagefright/recordvideo.cpp @@ -44,7 +44,7 @@ static void usage(const char *me) { fprintf(stderr, " -p encoder profile. see omx il header (default: encoder specific)\n"); fprintf(stderr, " -v video codec: [0] AVC [1] M4V [2] H263 (default: 0)\n"); fprintf(stderr, " -s(oftware) prefer software codec\n"); - fprintf(stderr, "The output file is /sdcard/output.mp4\n"); + fprintf(stderr, " -o filename: output file (default: /sdcard/output.mp4)\n"); exit(1); } @@ -162,12 +162,12 @@ int main(int argc, char **argv) { int level = -1; // Encoder specific default int profile = -1; // Encoder specific default int codec = 0; - const char *fileName = "/sdcard/output.mp4"; + char *fileName = "/sdcard/output.mp4"; bool preferSoftwareCodec = false; android::ProcessState::self()->startThreadPool(); int res; - while ((res = getopt(argc, argv, "b:c:f:i:n:w:t:l:p:v:hs")) >= 0) { + while ((res = getopt(argc, argv, "b:c:f:i:n:w:t:l:p:v:o:hs")) >= 0) { switch (res) { case 'b': { @@ -235,6 +235,12 @@ int main(int argc, char **argv) { break; } + case 'o': + { + fileName = optarg; + break; + } + case 's': { preferSoftwareCodec = true; diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp index 1e0e7f8..1002ac4 100644 --- a/cmds/stagefright/stagefright.cpp +++ b/cmds/stagefright/stagefright.cpp @@ -940,8 +940,8 @@ int main(int argc, char **argv) { } else { CHECK(useSurfaceTexAlloc); - sp<SurfaceTexture> texture = new SurfaceTexture(0 /* tex */); - gSurface = new SurfaceTextureClient(texture); + sp<GLConsumer> texture = new GLConsumer(0 /* tex */); + gSurface = new SurfaceTextureClient(texture->getBufferQueue()); } CHECK_EQ((status_t)OK, diff --git a/include/camera/Camera.h b/include/camera/Camera.h index 234e165..43dae1c 100644 --- a/include/camera/Camera.h +++ b/include/camera/Camera.h @@ -18,7 +18,7 @@ #define ANDROID_HARDWARE_CAMERA_H #include <utils/Timers.h> -#include <gui/ISurfaceTexture.h> +#include <gui/IGraphicBufferProducer.h> #include <system/camera.h> #include <camera/ICameraClient.h> #include <camera/ICameraRecordingProxy.h> @@ -86,8 +86,8 @@ public: // pass the buffered Surface to the camera service status_t setPreviewDisplay(const sp<Surface>& surface); - // pass the buffered ISurfaceTexture to the camera service - status_t setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture); + // pass the buffered IGraphicBufferProducer to the camera service + status_t setPreviewTexture(const sp<IGraphicBufferProducer>& bufferProducer); // start preview mode, must call setPreviewDisplay first status_t startPreview(); diff --git a/include/camera/ICamera.h b/include/camera/ICamera.h index 3d18837..eccaa41 100644 --- a/include/camera/ICamera.h +++ b/include/camera/ICamera.h @@ -27,7 +27,7 @@ namespace android { class ICameraClient; -class ISurfaceTexture; +class IGraphicBufferProducer; class Surface; class ICamera: public IInterface @@ -49,9 +49,9 @@ public: // pass the buffered Surface to the camera service virtual status_t setPreviewDisplay(const sp<Surface>& surface) = 0; - // pass the buffered ISurfaceTexture to the camera service + // pass the buffered IGraphicBufferProducer to the camera service virtual status_t setPreviewTexture( - const sp<ISurfaceTexture>& surfaceTexture) = 0; + const sp<IGraphicBufferProducer>& bufferProducer) = 0; // set the preview callback flag to affect how the received frames from // preview are handled. diff --git a/include/media/AudioBufferProvider.h b/include/media/AudioBufferProvider.h index 43e4de7..865ed7e 100644 --- a/include/media/AudioBufferProvider.h +++ b/include/media/AudioBufferProvider.h @@ -36,8 +36,11 @@ public: size_t frameCount; }; - virtual ~AudioBufferProvider() {} +protected: + AudioBufferProvider() : mValid(kValid) { } + virtual ~AudioBufferProvider() { mValid = kDead; } +public: // value representing an invalid presentation timestamp static const int64_t kInvalidPTS = 0x7FFFFFFFFFFFFFFFLL; // <stdint.h> is too painful @@ -47,6 +50,13 @@ public: virtual status_t getNextBuffer(Buffer* buffer, int64_t pts = kInvalidPTS) = 0; virtual void releaseBuffer(Buffer* buffer) = 0; + + int getValid() const { return mValid; } + static const int kValid = 'GOOD'; + static const int kDead = 'DEAD'; + +private: + int mValid; }; // ---------------------------------------------------------------------------- diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index f1b77ab..6f85527 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -52,8 +52,11 @@ public: * Keep in sync with frameworks/base/media/java/android/media/AudioTrack.java NATIVE_EVENT_*. */ enum event_type { - EVENT_MORE_DATA = 0, // Request to write more data to PCM buffer. - EVENT_UNDERRUN = 1, // PCM buffer underrun occurred. + EVENT_MORE_DATA = 0, // Request to write more data to buffer. + // If this event is delivered but the callback handler + // does not want to write more data, the handler must explicitly + // ignore the event by setting frameCount to zero. + EVENT_UNDERRUN = 1, // Buffer underrun occurred. EVENT_LOOP_END = 2, // Sample loop end was reached; playback restarted from // loop start if loop count was not 0. EVENT_MARKER = 3, // Playback head is at the specified marker position @@ -115,14 +118,16 @@ public: uint32_t sampleRate = 0); /* Constructs an uninitialized AudioTrack. No connection with - * AudioFlinger takes place. + * AudioFlinger takes place. Use set() after this. */ AudioTrack(); /* Creates an AudioTrack object and registers it with AudioFlinger. * Once created, the track needs to be started before it can be used. - * Unspecified values are set to the audio hardware's current - * values. + * Unspecified values are set to appropriate default values. + * With this constructor, the track is configured for streaming mode. + * Data to be rendered is supplied by write() or by the callback EVENT_MORE_DATA. + * Intermixing a combination of write() and non-ignored EVENT_MORE_DATA is deprecated. * * Parameters: * @@ -136,10 +141,10 @@ public: * application's contribution to the * latency of the track. The actual size selected by the AudioTrack could be * larger if the requested size is not compatible with current audio HAL - * latency. Zero means to use a default value. + * configuration. Zero means to use a default value. * flags: See comments on audio_output_flags_t in <system/audio.h>. * cbf: Callback function. If not null, this function is called periodically - * to provide new PCM data. + * to provide new data and inform of marker, position updates, etc. * user: Context for use by the callback receiver. * notificationFrames: The callback function is called each time notificationFrames PCM * frames have been consumed from track input buffer. @@ -159,13 +164,16 @@ public: int notificationFrames = 0, int sessionId = 0); - /* Creates an audio track and registers it with AudioFlinger. With this constructor, - * the PCM data to be rendered by AudioTrack is passed in a shared memory buffer - * identified by the argument sharedBuffer. This prototype is for static buffer playback. - * PCM data must be present in memory before the AudioTrack is started. - * The write() and flush() methods are not supported in this case. + /* Creates an audio track and registers it with AudioFlinger. + * With this constructor, the track is configured for static buffer mode. + * The format must not be 8-bit linear PCM. + * Data to be rendered is passed in a shared memory buffer + * identified by the argument sharedBuffer, which must be non-0. + * The memory should be initialized to the desired data before calling start(). + * The write() method is not supported in this case. * It is recommended to pass a callback function to be notified of playback end by an * EVENT_UNDERRUN event. + * FIXME EVENT_MORE_DATA still occurs; it must be ignored. */ AudioTrack( audio_stream_type_t streamType, @@ -184,13 +192,14 @@ public: */ ~AudioTrack(); - /* Initialize an uninitialized AudioTrack. * Returned status (from utils/Errors.h) can be: * - NO_ERROR: successful initialization * - INVALID_OPERATION: AudioTrack is already initialized * - BAD_VALUE: invalid parameter (channelMask, format, sampleRate...) * - NO_INIT: audio server or audio hardware not initialized + * If sharedBuffer is non-0, the frameCount parameter is ignored and + * replaced by the shared buffer's total allocated size in frame units. */ status_t set(audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT, uint32_t sampleRate = 0, @@ -205,64 +214,68 @@ public: bool threadCanCallJava = false, int sessionId = 0); - /* Result of constructing the AudioTrack. This must be checked * before using any AudioTrack API (except for set()), because using * an uninitialized AudioTrack produces undefined results. * See set() method above for possible return codes. */ - status_t initCheck() const; + status_t initCheck() const { return mStatus; } /* Returns this track's estimated latency in milliseconds. * This includes the latency due to AudioTrack buffer size, AudioMixer (if any) * and audio hardware driver. */ - uint32_t latency() const; + uint32_t latency() const { return mLatency; } /* getters, see constructors and set() */ - audio_stream_type_t streamType() const; - audio_format_t format() const; - uint32_t channelCount() const; - uint32_t frameCount() const; + audio_stream_type_t streamType() const { return mStreamType; } + audio_format_t format() const { return mFormat; } - /* Return channelCount * (bit depth per channel / 8). + /* Return frame size in bytes, which for linear PCM is channelCount * (bit depth per channel / 8). * channelCount is determined from channelMask, and bit depth comes from format. + * For non-linear formats, the frame size is typically 1 byte. */ - size_t frameSize() const { return mFrameSize; } + uint32_t channelCount() const { return mChannelCount; } - sp<IMemory>& sharedBuffer(); + uint32_t frameCount() const { return mFrameCount; } + size_t frameSize() const { return mFrameSize; } + /* Return the static buffer specified in constructor or set(), or 0 for streaming mode */ + sp<IMemory> sharedBuffer() const { return mSharedBuffer; } /* After it's created the track is not active. Call start() to * make it active. If set, the callback will start being called. + * If the track was previously paused, volume is ramped up over the first mix buffer. */ void start(); - /* Stop a track. If set, the callback will cease being called and + /* Stop a track. + * In static buffer mode, the track is stopped immediately. + * In streaming mode, the callback will cease being called and * obtainBuffer returns STOPPED. Note that obtainBuffer() still works * and will fill up buffers until the pool is exhausted. + * The stop does not occur immediately: any data remaining in the buffer + * is first drained, mixed, and output, and only then is the track marked as stopped. */ void stop(); bool stopped() const; - /* Flush a stopped track. All pending buffers are discarded. - * This function has no effect if the track is not stopped. + /* Flush a stopped or paused track. All previously buffered data is discarded immediately. + * This has the effect of draining the buffers without mixing or output. + * Flush is intended for streaming mode, for example before switching to non-contiguous content. + * This function is a no-op if the track is not stopped or paused, or uses a static buffer. */ void flush(); - /* Pause a track. If set, the callback will cease being called and + /* Pause a track. After pause, the callback will cease being called and * obtainBuffer returns STOPPED. Note that obtainBuffer() still works * and will fill up buffers until the pool is exhausted. + * Volume is ramped down over the next mix buffer following the pause request, + * and then the track is marked as paused. It can be resumed with ramp up by start(). */ void pause(); - /* Mute or unmute this track. - * While muted, the callback, if set, is still called. - */ - void mute(bool); - bool muted() const; - /* Set volume for this track, mostly used for games' sound effects * left and right volumes. Levels must be >= 0.0 and <= 1.0. * This is the older API. New applications should use setVolume(float) when possible. @@ -288,6 +301,7 @@ public: uint32_t getSampleRate() const; /* Enables looping and sets the start and end points of looping. + * Only supported for static buffer mode. * * Parameters: * @@ -303,13 +317,15 @@ public: /* Sets marker position. When playback reaches the number of frames specified, a callback with * event type EVENT_MARKER is called. Calling setMarkerPosition with marker == 0 cancels marker - * notification callback. + * notification callback. To set a marker at a position which would compute as 0, + * a workaround is to the set the marker at a nearby position such as -1 or 1. * If the AudioTrack has been opened with no callback function associated, the operation will * fail. * * Parameters: * - * marker: marker position expressed in frames. + * marker: marker position expressed in wrapping (overflow) frame units, + * like the return value of getPosition(). * * Returned status (from utils/Errors.h) can be: * - NO_ERROR: successful operation @@ -318,13 +334,13 @@ public: status_t setMarkerPosition(uint32_t marker); status_t getMarkerPosition(uint32_t *marker) const; - /* Sets position update period. Every time the number of frames specified has been played, * a callback with event type EVENT_NEW_POS is called. * Calling setPositionUpdatePeriod with updatePeriod == 0 cancels new position notification * callback. * If the AudioTrack has been opened with no callback function associated, the operation will * fail. + * Extremely small values may be rounded up to a value the implementation can support. * * Parameters: * @@ -352,20 +368,26 @@ public: * * Returned status (from utils/Errors.h) can be: * - NO_ERROR: successful operation - * - INVALID_OPERATION: the AudioTrack is not stopped. + * - INVALID_OPERATION: the AudioTrack is not stopped or paused, or is streaming mode. * - BAD_VALUE: The specified position is beyond the number of frames present in AudioTrack * buffer */ status_t setPosition(uint32_t position); + + /* Return the total number of frames played since playback start. + * The counter will wrap (overflow) periodically, e.g. every ~27 hours at 44.1 kHz. + * It is reset to zero by flush(), reload(), and stop(). + */ status_t getPosition(uint32_t *position); /* Forces AudioTrack buffer full condition. When playing a static buffer, this method avoids * rewriting the buffer before restarting playback after a stop. * This method must be called with the AudioTrack in paused or stopped state. + * Not allowed in streaming mode. * * Returned status (from utils/Errors.h) can be: * - NO_ERROR: successful operation - * - INVALID_OPERATION: the AudioTrack is not stopped. + * - INVALID_OPERATION: the AudioTrack is not stopped or paused, or is streaming mode. */ status_t reload(); @@ -387,7 +409,7 @@ public: * Returned value: * AudioTrack session ID. */ - int getSessionId() const; + int getSessionId() const { return mSessionId; } /* Attach track auxiliary output to specified effect. Use effectId = 0 * to detach track from effect. @@ -413,6 +435,9 @@ public: * or return WOULD_BLOCK depending on the value of the "blocking" * parameter. * + * obtainBuffer() and releaseBuffer() are deprecated for direct use by applications, + * which should use write() or callback EVENT_MORE_DATA instead. + * * Interpretation of waitCount: * +n limits wait time to n * WAIT_PERIOD_MS, * -1 causes an (almost) infinite wait time, @@ -450,6 +475,7 @@ public: * STOPPED AudioTrack was stopped during the write * NO_MORE_BUFFERS when obtainBuffer() returns same * or any other error code returned by IAudioTrack::start() or restoreTrack_l(). + * Not supported for static buffer mode. */ ssize_t write(const void* buffer, size_t size); @@ -497,7 +523,10 @@ protected: audio_output_flags_t flags, const sp<IMemory>& sharedBuffer, audio_io_handle_t output); + + // can only be called when !mActive void flush_l(); + status_t setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount); audio_io_handle_t getOutput_l(); status_t restoreTrack_l(audio_track_cblk_t*& cblk, bool fromStart); @@ -523,9 +552,7 @@ protected: audio_format_t mFormat; // as requested by client, not forced to 16-bit audio_stream_type_t mStreamType; - uint8_t mChannelCount; - uint8_t mMuted; - uint8_t mReserved; + uint32_t mChannelCount; audio_channel_mask_t mChannelMask; // mFrameSize is equal to mFrameSizeAF for non-PCM or 16-bit PCM data. @@ -550,7 +577,7 @@ protected: sp<IMemory> mSharedBuffer; int mLoopCount; uint32_t mRemainingFrames; - uint32_t mMarkerPosition; // in frames + uint32_t mMarkerPosition; // in wrapping (overflow) frame units bool mMarkerReached; uint32_t mNewPosition; // in frames uint32_t mUpdatePeriod; // in frames diff --git a/include/media/IAudioTrack.h b/include/media/IAudioTrack.h index 9e0e389..144be0e 100644 --- a/include/media/IAudioTrack.h +++ b/include/media/IAudioTrack.h @@ -54,11 +54,6 @@ public: */ virtual void flush() = 0; - /* Mute or unmute this track. - * While muted, the callback, if set, is still called. - */ - virtual void mute(bool) = 0; - /* Pause a track. If set, the callback will cease being called and * obtainBuffer will return an error. Buffers that are already released * will continue to be processed, unless/until flush() is called. diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h index 4ed1863..0cbd269 100644 --- a/include/media/IMediaPlayer.h +++ b/include/media/IMediaPlayer.h @@ -32,7 +32,7 @@ namespace android { class Parcel; class Surface; class IStreamSource; -class ISurfaceTexture; +class IGraphicBufferProducer; class IMediaPlayer: public IInterface { @@ -46,7 +46,7 @@ public: virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; virtual status_t setDataSource(const sp<IStreamSource>& source) = 0; virtual status_t setVideoSurfaceTexture( - const sp<ISurfaceTexture>& surfaceTexture) = 0; + const sp<IGraphicBufferProducer>& bufferProducer) = 0; virtual status_t prepareAsync() = 0; virtual status_t start() = 0; virtual status_t stop() = 0; diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h index ec84e25..54af0d3 100644 --- a/include/media/IMediaRecorder.h +++ b/include/media/IMediaRecorder.h @@ -26,7 +26,7 @@ class Surface; class ICamera; class ICameraRecordingProxy; class IMediaRecorderClient; -class ISurfaceTexture; +class IGraphicBufferProducer; class IMediaRecorder: public IInterface { @@ -55,7 +55,7 @@ public: virtual status_t init() = 0; virtual status_t close() = 0; virtual status_t release() = 0; - virtual sp<ISurfaceTexture> querySurfaceMediaSource() = 0; + virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/media/IRemoteDisplay.h b/include/media/IRemoteDisplay.h index a61704e..c8baae9 100644 --- a/include/media/IRemoteDisplay.h +++ b/include/media/IRemoteDisplay.h @@ -39,6 +39,9 @@ class IRemoteDisplay : public IInterface public: DECLARE_META_INTERFACE(RemoteDisplay); + virtual status_t pause() = 0; + virtual status_t resume() = 0; + // Disconnects the remote display and stops listening for new connections. virtual status_t dispose() = 0; }; diff --git a/include/media/IRemoteDisplayClient.h b/include/media/IRemoteDisplayClient.h index 252b401..7b0fa9e 100644 --- a/include/media/IRemoteDisplayClient.h +++ b/include/media/IRemoteDisplayClient.h @@ -26,7 +26,7 @@ namespace android { -class ISurfaceTexture; +class IGraphicBufferProducer; class IRemoteDisplayClient : public IInterface { @@ -48,7 +48,7 @@ public: // Indicates that the remote display has been connected successfully. // Provides a surface texture that the client should use to stream buffers to // the remote display. - virtual void onDisplayConnected(const sp<ISurfaceTexture>& surfaceTexture, + virtual void onDisplayConnected(const sp<IGraphicBufferProducer>& bufferProducer, uint32_t width, uint32_t height, uint32_t flags) = 0; // one-way // Indicates that the remote display has been disconnected normally. diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index b7bee3f..8fc72c3 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -37,7 +37,7 @@ namespace android { class Parcel; class Surface; -class ISurfaceTexture; +class IGraphicBufferProducer; template<typename T> class SortedVector; @@ -131,9 +131,9 @@ public: return INVALID_OPERATION; } - // pass the buffered ISurfaceTexture to the media player service + // pass the buffered IGraphicBufferProducer to the media player service virtual status_t setVideoSurfaceTexture( - const sp<ISurfaceTexture>& surfaceTexture) = 0; + const sp<IGraphicBufferProducer>& bufferProducer) = 0; virtual status_t prepare() = 0; virtual status_t prepareAsync() = 0; diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h index ef799f5..803bc64 100644 --- a/include/media/MediaRecorderBase.h +++ b/include/media/MediaRecorderBase.h @@ -26,7 +26,7 @@ namespace android { class ICameraRecordingProxy; class Surface; -class ISurfaceTexture; +class IGraphicBufferProducer; struct MediaRecorderBase { MediaRecorderBase() {} @@ -55,7 +55,7 @@ struct MediaRecorderBase { virtual status_t reset() = 0; virtual status_t getMaxAmplitude(int *max) = 0; virtual status_t dump(int fd, const Vector<String16>& args) const = 0; - virtual sp<ISurfaceTexture> querySurfaceMediaSource() const = 0; + virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() const = 0; private: MediaRecorderBase(const MediaRecorderBase &); diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h index d753eba..e5aa033 100644 --- a/include/media/mediaplayer.h +++ b/include/media/mediaplayer.h @@ -33,7 +33,7 @@ class ANativeWindow; namespace android { class Surface; -class ISurfaceTexture; +class IGraphicBufferProducer; enum media_event_type { MEDIA_NOP = 0, // interface test message @@ -199,7 +199,7 @@ public: status_t setDataSource(int fd, int64_t offset, int64_t length); status_t setDataSource(const sp<IStreamSource> &source); status_t setVideoSurfaceTexture( - const sp<ISurfaceTexture>& surfaceTexture); + const sp<IGraphicBufferProducer>& bufferProducer); status_t setListener(const sp<MediaPlayerListener>& listener); status_t prepare(); status_t prepareAsync(); diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h index 6d304e0..2882c41 100644 --- a/include/media/mediarecorder.h +++ b/include/media/mediarecorder.h @@ -31,7 +31,7 @@ class Surface; class IMediaRecorder; class ICamera; class ICameraRecordingProxy; -class ISurfaceTexture; +class IGraphicBufferProducer; class SurfaceTextureClient; typedef void (*media_completion_f)(status_t status, void *cookie); @@ -228,7 +228,7 @@ public: status_t close(); status_t release(); void notify(int msg, int ext1, int ext2); - sp<ISurfaceTexture> querySurfaceMediaSourceFromMediaServer(); + sp<IGraphicBufferProducer> querySurfaceMediaSourceFromMediaServer(); private: void doCleanUp(); @@ -237,10 +237,10 @@ private: sp<IMediaRecorder> mMediaRecorder; sp<MediaRecorderListener> mListener; - // Reference toISurfaceTexture + // Reference to IGraphicBufferProducer // for encoding GL Frames. That is useful only when the // video source is set to VIDEO_SOURCE_GRALLOC_BUFFER - sp<ISurfaceTexture> mSurfaceMediaSource; + sp<IGraphicBufferProducer> mSurfaceMediaSource; media_recorder_states mCurrentState; bool mIsAudioSourceSet; diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h index cba8a6b..df1c46b 100644 --- a/include/media/stagefright/ACodec.h +++ b/include/media/stagefright/ACodec.h @@ -184,6 +184,7 @@ private: bool mChannelMaskPresent; int32_t mChannelMask; + 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); diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h index b1e57cf..88aabf6 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> diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h index e91904c..be08c19 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', diff --git a/include/media/stagefright/SurfaceMediaSource.h b/include/media/stagefright/SurfaceMediaSource.h index e56527d..609d84f 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 SurfaceTextureClient // 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 @@ -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 SurfaceTextureClient of asynchronous events in the // BufferQueue. virtual void onFrameAvailable(); @@ -157,7 +157,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 SurfaceTextureClient). // 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/private/media/VideoFrame.h b/include/private/media/VideoFrame.h index 0ecc348..a211ed9 100644 --- a/include/private/media/VideoFrame.h +++ b/include/private/media/VideoFrame.h @@ -88,7 +88,8 @@ public: class VideoFrame { public: - VideoFrame(): mWidth(0), mHeight(0), mDisplayWidth(0), mDisplayHeight(0), mSize(0), mData(0) {} + VideoFrame(): mWidth(0), mHeight(0), mDisplayWidth(0), mDisplayHeight(0), mSize(0), mData(0), + mRotationAngle(0) {} VideoFrame(const VideoFrame& copy) { mWidth = copy.mWidth; @@ -105,6 +106,7 @@ public: mSize = 0; } } + mRotationAngle = copy.mRotationAngle; } ~VideoFrame() { diff --git a/libvideoeditor/lvpp/NativeWindowRenderer.cpp b/libvideoeditor/lvpp/NativeWindowRenderer.cpp index 2e15ff9..114f0f6 100755 --- a/libvideoeditor/lvpp/NativeWindowRenderer.cpp +++ b/libvideoeditor/lvpp/NativeWindowRenderer.cpp @@ -20,7 +20,7 @@ #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> #include <cutils/log.h> -#include <gui/SurfaceTexture.h> +#include <gui/GLConsumer.h> #include <gui/SurfaceTextureClient.h> #include <media/stagefright/MediaBuffer.h> #include <media/stagefright/MetaData.h> @@ -315,7 +315,7 @@ NativeWindowRenderer::~NativeWindowRenderer() { } void NativeWindowRenderer::render(RenderInput* input) { - sp<SurfaceTexture> ST = input->mST; + sp<GLConsumer> ST = input->mST; sp<SurfaceTextureClient> STC = input->mSTC; if (input->mIsExternalBuffer) { @@ -568,8 +568,8 @@ void NativeWindowRenderer::destroyRenderInput(RenderInput* input) { RenderInput::RenderInput(NativeWindowRenderer* renderer, GLuint textureId) : mRenderer(renderer) , mTextureId(textureId) { - mST = new SurfaceTexture(mTextureId); - mSTC = new SurfaceTextureClient(mST); + mST = new GLConsumer(mTextureId); + mSTC = new SurfaceTextureClient(mST->getBufferQueue()); native_window_connect(mSTC.get(), NATIVE_WINDOW_API_MEDIA); } diff --git a/libvideoeditor/lvpp/NativeWindowRenderer.h b/libvideoeditor/lvpp/NativeWindowRenderer.h index 8fbb4f9..b0623ba 100755 --- a/libvideoeditor/lvpp/NativeWindowRenderer.h +++ b/libvideoeditor/lvpp/NativeWindowRenderer.h @@ -37,15 +37,15 @@ // we only expect that happens briefly when one clip is about to finish // and the next clip is about to start. // -// We allocate a SurfaceTexture for each RenderInput and the user can use +// We allocate a SurfaceTextureClient for each RenderInput and the user can use // the getTargetWindow() function to get the corresponding ANativeWindow -// for that SurfaceTexture. The intention is that the user can pass that +// for that SurfaceTextureClient. The intention is that the user can pass that // ANativeWindow to OMXCodec::Create() so the codec can decode directly // to buffers provided by the texture. namespace android { -class SurfaceTexture; +class GLConsumer; class SurfaceTextureClient; class RenderInput; @@ -110,7 +110,7 @@ private: // destination aspect ratio. GLfloat mPositionCoordinates[8]; - // We use a different GL id for each SurfaceTexture. + // We use a different GL id for each SurfaceTextureClient. GLuint mNextTextureId; // Number of existing RenderInputs, just for debugging. @@ -146,7 +146,7 @@ private: class RenderInput { public: - // Returns the ANativeWindow corresponds to the SurfaceTexture. + // Returns the ANativeWindow corresponds to the SurfaceTextureClient. ANativeWindow* getTargetWindow(); // Updates video frame size from the MediaSource's metadata. Specifically @@ -156,7 +156,7 @@ public: // Renders the buffer with the given video effect and rending mode. // The video effets are defined in VideoEditorTools.h // Set isExternalBuffer to true only when the buffer given is not - // provided by the SurfaceTexture. + // provided by the SurfaceTextureClient. void render(MediaBuffer *buffer, uint32_t videoEffect, M4xVSS_MediaRendering renderingMode, bool isExternalBuffer); private: @@ -164,7 +164,7 @@ private: ~RenderInput(); NativeWindowRenderer* mRenderer; GLuint mTextureId; - sp<SurfaceTexture> mST; + sp<GLConsumer> mST; sp<SurfaceTextureClient> mSTC; int mWidth, mHeight; diff --git a/libvideoeditor/lvpp/PreviewPlayer.cpp b/libvideoeditor/lvpp/PreviewPlayer.cpp index 34731d7..754c5a9 100755 --- a/libvideoeditor/lvpp/PreviewPlayer.cpp +++ b/libvideoeditor/lvpp/PreviewPlayer.cpp @@ -31,7 +31,7 @@ #include <media/stagefright/OMXCodec.h> #include <media/stagefright/foundation/ADebug.h> #include <gui/Surface.h> -#include <gui/ISurfaceTexture.h> +#include <gui/IGraphicBufferProducer.h> #include <gui/SurfaceTextureClient.h> #include "VideoEditorPreviewController.h" @@ -1775,12 +1775,12 @@ void PreviewPlayer::setSurface(const sp<Surface> &surface) { setNativeWindow_l(surface); } -void PreviewPlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) { +void PreviewPlayer::setSurfaceTexture(const sp<IGraphicBufferProducer> &bufferProducer) { Mutex::Autolock autoLock(mLock); mSurface.clear(); - if (surfaceTexture != NULL) { - setNativeWindow_l(new SurfaceTextureClient(surfaceTexture)); + if (bufferProducer != NULL) { + setNativeWindow_l(new SurfaceTextureClient(bufferProducer)); } } diff --git a/libvideoeditor/lvpp/PreviewPlayer.h b/libvideoeditor/lvpp/PreviewPlayer.h index 177853f..5a13b58 100755 --- a/libvideoeditor/lvpp/PreviewPlayer.h +++ b/libvideoeditor/lvpp/PreviewPlayer.h @@ -44,7 +44,7 @@ struct PreviewPlayer { bool isPlaying() const; void setSurface(const sp<Surface> &surface); - void setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture); + void setSurfaceTexture(const sp<IGraphicBufferProducer> &bufferProducer); status_t seekTo(int64_t timeUs); status_t getVideoDimensions(int32_t *width, int32_t *height) const; diff --git a/libvideoeditor/lvpp/VideoEditorPlayer.cpp b/libvideoeditor/lvpp/VideoEditorPlayer.cpp index a47fc15..91a4415 100755 --- a/libvideoeditor/lvpp/VideoEditorPlayer.cpp +++ b/libvideoeditor/lvpp/VideoEditorPlayer.cpp @@ -81,10 +81,10 @@ status_t VideoEditorPlayer::setVideoSurface(const sp<Surface> &surface) { return OK; } -status_t VideoEditorPlayer::setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) { +status_t VideoEditorPlayer::setVideoSurfaceTexture(const sp<IGraphicBufferProducer> &bufferProducer) { ALOGV("setVideoSurfaceTexture"); - mPlayer->setSurfaceTexture(surfaceTexture); + mPlayer->setSurfaceTexture(bufferProducer); return OK; } diff --git a/libvideoeditor/lvpp/VideoEditorPlayer.h b/libvideoeditor/lvpp/VideoEditorPlayer.h index 2ab4eef..77194ab 100755 --- a/libvideoeditor/lvpp/VideoEditorPlayer.h +++ b/libvideoeditor/lvpp/VideoEditorPlayer.h @@ -99,7 +99,7 @@ public: virtual status_t setDataSource(int fd, int64_t offset, int64_t length); virtual status_t setVideoSurface(const sp<Surface> &surface); - virtual status_t setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture); + virtual status_t setVideoSurfaceTexture(const sp<IGraphicBufferProducer> &bufferProducer); virtual status_t prepare(); virtual status_t prepareAsync(); virtual status_t start(); diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index f2b6441..a35d562 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -13,6 +13,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ AudioTrack.cpp \ + AudioTrackShared.cpp \ IAudioFlinger.cpp \ IAudioFlingerClient.cpp \ IAudioTrack.cpp \ diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index e40895a..1d87ff8 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -138,6 +138,11 @@ AudioTrack::AudioTrack( mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) { + if (sharedBuffer == 0) { + ALOGE("sharedBuffer must be non-0"); + mStatus = BAD_VALUE; + return; + } mStatus = set(streamType, sampleRate, format, channelMask, 0 /*frameCount*/, flags, cbf, user, notificationFrames, sharedBuffer, false /*threadCanCallJava*/, sessionId); @@ -304,7 +309,6 @@ status_t AudioTrack::set( } mSharedBuffer = sharedBuffer; - mMuted = false; mActive = false; mUserData = user; mLoopCount = 0; @@ -317,43 +321,6 @@ status_t AudioTrack::set( return NO_ERROR; } -status_t AudioTrack::initCheck() const -{ - return mStatus; -} - -// ------------------------------------------------------------------------- - -uint32_t AudioTrack::latency() const -{ - return mLatency; -} - -audio_stream_type_t AudioTrack::streamType() const -{ - return mStreamType; -} - -audio_format_t AudioTrack::format() const -{ - return mFormat; -} - -uint32_t AudioTrack::channelCount() const -{ - return mChannelCount; -} - -size_t AudioTrack::frameCount() const -{ - return mFrameCount; -} - -sp<IMemory>& AudioTrack::sharedBuffer() -{ - return mSharedBuffer; -} - // ------------------------------------------------------------------------- void AudioTrack::start() @@ -435,6 +402,7 @@ void AudioTrack::stop() mMarkerReached = false; // Force flush if a shared buffer is used otherwise audioflinger // will not stop before end of buffer is reached. + // It may be needed to make sure that we stop playback, likely in case looping is on. if (mSharedBuffer != 0) { flush_l(); } @@ -457,26 +425,26 @@ bool AudioTrack::stopped() const void AudioTrack::flush() { AutoMutex lock(mLock); - flush_l(); + if (!mActive && mSharedBuffer == 0) { + flush_l(); + } } -// must be called with mLock held void AudioTrack::flush_l() { ALOGV("flush"); + ALOG_ASSERT(!mActive); // clear playback marker and periodic update counter mMarkerPosition = 0; mMarkerReached = false; mUpdatePeriod = 0; - if (!mActive) { - mFlushed = true; - mAudioTrack->flush(); - // Release AudioTrack callback thread in case it was waiting for new buffers - // in AudioTrack::obtainBuffer() - mCblk->cv.signal(); - } + mFlushed = true; + mAudioTrack->flush(); + // Release AudioTrack callback thread in case it was waiting for new buffers + // in AudioTrack::obtainBuffer() + mCblk->cv.signal(); } void AudioTrack::pause() @@ -490,17 +458,6 @@ void AudioTrack::pause() } } -void AudioTrack::mute(bool e) -{ - mAudioTrack->mute(e); - mMuted = e; -} - -bool AudioTrack::muted() const -{ - return mMuted; -} - status_t AudioTrack::setVolume(float left, float right) { if (left < 0.0f || left > 1.0f || right < 0.0f || right > 1.0f) { @@ -583,6 +540,10 @@ status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount // must be called with mLock held status_t AudioTrack::setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount) { + if (mSharedBuffer == 0 || mIsTimed) { + return INVALID_OPERATION; + } + audio_track_cblk_t* cblk = mCblk; Mutex::Autolock _l(cblk->lock); @@ -595,10 +556,6 @@ status_t AudioTrack::setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCou return NO_ERROR; } - if (mIsTimed) { - return INVALID_OPERATION; - } - if (loopStart >= loopEnd || loopEnd - loopStart > mFrameCount || cblk->server > loopStart) { @@ -672,7 +629,7 @@ status_t AudioTrack::getPositionUpdatePeriod(uint32_t *updatePeriod) const status_t AudioTrack::setPosition(uint32_t position) { - if (mIsTimed) { + if (mSharedBuffer == 0 || mIsTimed) { return INVALID_OPERATION; } @@ -708,6 +665,10 @@ status_t AudioTrack::getPosition(uint32_t *position) status_t AudioTrack::reload() { + if (mSharedBuffer == 0 || mIsTimed) { + return INVALID_OPERATION; + } + AutoMutex lock(mLock); if (!stopped_l()) { @@ -735,11 +696,6 @@ audio_io_handle_t AudioTrack::getOutput_l() mCblk->sampleRate, mFormat, mChannelMask, mFlags); } -int AudioTrack::getSessionId() const -{ - return mSessionId; -} - status_t AudioTrack::attachAuxEffect(int effectId) { ALOGV("attachAuxEffect(%d)", effectId); @@ -1089,10 +1045,7 @@ void AudioTrack::releaseBuffer(Buffer* audioBuffer) ssize_t AudioTrack::write(const void* buffer, size_t userSize) { - if (mSharedBuffer != 0) { - return INVALID_OPERATION; - } - if (mIsTimed) { + if (mSharedBuffer != 0 || mIsTimed) { return INVALID_OPERATION; } @@ -1471,8 +1424,8 @@ status_t AudioTrack::dump(int fd, const Vector<String16>& args) const snprintf(buffer, 255, " format(%d), channel count(%d), frame count(%d)\n", mFormat, mChannelCount, mFrameCount); result.append(buffer); - snprintf(buffer, 255, " sample rate(%u), status(%d), muted(%d)\n", - (cblk == 0) ? 0 : cblk->sampleRate, mStatus, mMuted); + snprintf(buffer, 255, " sample rate(%u), status(%d)\n", + (cblk == 0) ? 0 : cblk->sampleRate, mStatus); result.append(buffer); snprintf(buffer, 255, " active(%d), latency (%d)\n", mActive, mLatency); result.append(buffer); @@ -1529,180 +1482,4 @@ void AudioTrack::AudioTrackThread::resume() } } -// ========================================================================= - - -audio_track_cblk_t::audio_track_cblk_t() - : lock(Mutex::SHARED), cv(Condition::SHARED), user(0), server(0), - userBase(0), serverBase(0), frameCount_(0), - loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), mVolumeLR(0x10001000), - mSendLevel(0), flags(0) -{ -} - -uint32_t audio_track_cblk_t::stepUser(size_t stepCount, size_t frameCount, bool isOut) -{ - ALOGV("stepuser %08x %08x %d", user, server, stepCount); - - uint32_t u = user; - u += stepCount; - // Ensure that user is never ahead of server for AudioRecord - if (isOut) { - // If stepServer() has been called once, switch to normal obtainBuffer() timeout period - if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS-1) { - bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; - } - } else if (u > server) { - ALOGW("stepUser occurred after track reset"); - u = server; - } - - if (u >= frameCount) { - // common case, user didn't just wrap - if (u - frameCount >= userBase ) { - userBase += frameCount; - } - } else if (u >= userBase + frameCount) { - // user just wrapped - userBase += frameCount; - } - - user = u; - - // Clear flow control error condition as new data has been written/read to/from buffer. - if (flags & CBLK_UNDERRUN) { - android_atomic_and(~CBLK_UNDERRUN, &flags); - } - - return u; -} - -bool audio_track_cblk_t::stepServer(size_t stepCount, size_t frameCount, bool isOut) -{ - ALOGV("stepserver %08x %08x %d", user, server, stepCount); - - if (!tryLock()) { - ALOGW("stepServer() could not lock cblk"); - return false; - } - - uint32_t s = server; - bool flushed = (s == user); - - s += stepCount; - if (isOut) { - // Mark that we have read the first buffer so that next time stepUser() is called - // we switch to normal obtainBuffer() timeout period - if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) { - bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS - 1; - } - // It is possible that we receive a flush() - // while the mixer is processing a block: in this case, - // stepServer() is called After the flush() has reset u & s and - // we have s > u - if (flushed) { - ALOGW("stepServer occurred after track reset"); - s = user; - } - } - - if (s >= loopEnd) { - ALOGW_IF(s > loopEnd, "stepServer: s %u > loopEnd %u", s, loopEnd); - s = loopStart; - if (--loopCount == 0) { - loopEnd = UINT_MAX; - loopStart = UINT_MAX; - } - } - - if (s >= frameCount) { - // common case, server didn't just wrap - if (s - frameCount >= serverBase ) { - serverBase += frameCount; - } - } else if (s >= serverBase + frameCount) { - // server just wrapped - serverBase += frameCount; - } - - server = s; - - if (!(flags & CBLK_INVALID)) { - cv.signal(); - } - lock.unlock(); - return true; -} - -void* audio_track_cblk_t::buffer(void *buffers, size_t frameSize, uint32_t offset) const -{ - return (int8_t *)buffers + (offset - userBase) * frameSize; -} - -uint32_t audio_track_cblk_t::framesAvailable(size_t frameCount, bool isOut) -{ - Mutex::Autolock _l(lock); - return framesAvailable_l(frameCount, isOut); -} - -uint32_t audio_track_cblk_t::framesAvailable_l(size_t frameCount, bool isOut) -{ - uint32_t u = user; - uint32_t s = server; - - if (isOut) { - uint32_t limit = (s < loopStart) ? s : loopStart; - return limit + frameCount - u; - } else { - return frameCount + u - s; - } -} - -uint32_t audio_track_cblk_t::framesReady(bool isOut) -{ - uint32_t u = user; - uint32_t s = server; - - if (isOut) { - if (u < loopEnd) { - return u - s; - } else { - // do not block on mutex shared with client on AudioFlinger side - if (!tryLock()) { - ALOGW("framesReady() could not lock cblk"); - return 0; - } - uint32_t frames = UINT_MAX; - if (loopCount >= 0) { - frames = (loopEnd - loopStart)*loopCount + u - s; - } - lock.unlock(); - return frames; - } - } else { - return s - u; - } -} - -bool audio_track_cblk_t::tryLock() -{ - // the code below simulates lock-with-timeout - // we MUST do this to protect the AudioFlinger server - // as this lock is shared with the client. - status_t err; - - err = lock.tryLock(); - if (err == -EBUSY) { // just wait a bit - usleep(1000); - err = lock.tryLock(); - } - if (err != NO_ERROR) { - // probably, the client just died. - return false; - } - return true; -} - -// ------------------------------------------------------------------------- - }; // namespace android diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp new file mode 100644 index 0000000..bee13c8 --- /dev/null +++ b/media/libmedia/AudioTrackShared.cpp @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "AudioTrackShared" +//#define LOG_NDEBUG 0 + +#include <private/media/AudioTrackShared.h> +#include <utils/Log.h> + +namespace android { + +audio_track_cblk_t::audio_track_cblk_t() + : lock(Mutex::SHARED), cv(Condition::SHARED), user(0), server(0), + userBase(0), serverBase(0), frameCount_(0), + loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), mVolumeLR(0x10001000), + mSendLevel(0), flags(0) +{ +} + +uint32_t audio_track_cblk_t::stepUser(size_t stepCount, size_t frameCount, bool isOut) +{ + ALOGV("stepuser %08x %08x %d", user, server, stepCount); + + uint32_t u = user; + u += stepCount; + // Ensure that user is never ahead of server for AudioRecord + if (isOut) { + // If stepServer() has been called once, switch to normal obtainBuffer() timeout period + if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS-1) { + bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; + } + } else if (u > server) { + ALOGW("stepUser occurred after track reset"); + u = server; + } + + if (u >= frameCount) { + // common case, user didn't just wrap + if (u - frameCount >= userBase ) { + userBase += frameCount; + } + } else if (u >= userBase + frameCount) { + // user just wrapped + userBase += frameCount; + } + + user = u; + + // Clear flow control error condition as new data has been written/read to/from buffer. + if (flags & CBLK_UNDERRUN) { + android_atomic_and(~CBLK_UNDERRUN, &flags); + } + + return u; +} + +bool audio_track_cblk_t::stepServer(size_t stepCount, size_t frameCount, bool isOut) +{ + ALOGV("stepserver %08x %08x %d", user, server, stepCount); + + if (!tryLock()) { + ALOGW("stepServer() could not lock cblk"); + return false; + } + + uint32_t s = server; + bool flushed = (s == user); + + s += stepCount; + if (isOut) { + // Mark that we have read the first buffer so that next time stepUser() is called + // we switch to normal obtainBuffer() timeout period + if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) { + bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS - 1; + } + // It is possible that we receive a flush() + // while the mixer is processing a block: in this case, + // stepServer() is called After the flush() has reset u & s and + // we have s > u + if (flushed) { + ALOGW("stepServer occurred after track reset"); + s = user; + } + } + + if (s >= loopEnd) { + ALOGW_IF(s > loopEnd, "stepServer: s %u > loopEnd %u", s, loopEnd); + s = loopStart; + if (--loopCount == 0) { + loopEnd = UINT_MAX; + loopStart = UINT_MAX; + } + } + + if (s >= frameCount) { + // common case, server didn't just wrap + if (s - frameCount >= serverBase ) { + serverBase += frameCount; + } + } else if (s >= serverBase + frameCount) { + // server just wrapped + serverBase += frameCount; + } + + server = s; + + if (!(flags & CBLK_INVALID)) { + cv.signal(); + } + lock.unlock(); + return true; +} + +void* audio_track_cblk_t::buffer(void *buffers, size_t frameSize, uint32_t offset) const +{ + return (int8_t *)buffers + (offset - userBase) * frameSize; +} + +uint32_t audio_track_cblk_t::framesAvailable(size_t frameCount, bool isOut) +{ + Mutex::Autolock _l(lock); + return framesAvailable_l(frameCount, isOut); +} + +uint32_t audio_track_cblk_t::framesAvailable_l(size_t frameCount, bool isOut) +{ + uint32_t u = user; + uint32_t s = server; + + if (isOut) { + uint32_t limit = (s < loopStart) ? s : loopStart; + return limit + frameCount - u; + } else { + return frameCount + u - s; + } +} + +uint32_t audio_track_cblk_t::framesReady(bool isOut) +{ + uint32_t u = user; + uint32_t s = server; + + if (isOut) { + if (u < loopEnd) { + return u - s; + } else { + // do not block on mutex shared with client on AudioFlinger side + if (!tryLock()) { + ALOGW("framesReady() could not lock cblk"); + return 0; + } + uint32_t frames = UINT_MAX; + if (loopCount >= 0) { + frames = (loopEnd - loopStart)*loopCount + u - s; + } + lock.unlock(); + return frames; + } + } else { + return s - u; + } +} + +bool audio_track_cblk_t::tryLock() +{ + // the code below simulates lock-with-timeout + // we MUST do this to protect the AudioFlinger server + // as this lock is shared with the client. + status_t err; + + err = lock.tryLock(); + if (err == -EBUSY) { // just wait a bit + usleep(1000); + err = lock.tryLock(); + } + if (err != NO_ERROR) { + // probably, the client just died. + return false; + } + return true; +} + +} // namespace android diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index a010bb6..c5fbbf0 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -32,7 +32,7 @@ enum { CREATE_TRACK = IBinder::FIRST_CALL_TRANSACTION, OPEN_RECORD, SAMPLE_RATE, - CHANNEL_COUNT, // obsolete + RESERVED, // obsolete, was CHANNEL_COUNT FORMAT, FRAME_COUNT, LATENCY, @@ -191,17 +191,6 @@ public: return reply.readInt32(); } -#if 0 - virtual int channelCount(audio_io_handle_t output) const - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32((int32_t) output); - remote()->transact(CHANNEL_COUNT, data, &reply); - return reply.readInt32(); - } -#endif - virtual audio_format_t format(audio_io_handle_t output) const { Parcel data, reply; @@ -768,13 +757,6 @@ status_t BnAudioFlinger::onTransact( reply->writeInt32( sampleRate((audio_io_handle_t) data.readInt32()) ); return NO_ERROR; } break; -#if 0 - case CHANNEL_COUNT: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - reply->writeInt32( channelCount((audio_io_handle_t) data.readInt32()) ); - return NO_ERROR; - } break; -#endif case FORMAT: { CHECK_INTERFACE(IAudioFlinger, data, reply); reply->writeInt32( format((audio_io_handle_t) data.readInt32()) ); diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp index 867d1a5..e92f8aa 100644 --- a/media/libmedia/IAudioTrack.cpp +++ b/media/libmedia/IAudioTrack.cpp @@ -33,7 +33,7 @@ enum { START, STOP, FLUSH, - MUTE, + RESERVED, // was MUTE PAUSE, ATTACH_AUX_EFFECT, ALLOCATE_TIMED_BUFFER, @@ -88,14 +88,6 @@ public: remote()->transact(FLUSH, data, &reply); } - virtual void mute(bool e) - { - Parcel data, reply; - data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); - data.writeInt32(e); - remote()->transact(MUTE, data, &reply); - } - virtual void pause() { Parcel data, reply; @@ -192,11 +184,6 @@ status_t BnAudioTrack::onTransact( flush(); return NO_ERROR; } break; - case MUTE: { - CHECK_INTERFACE(IAudioTrack, data, reply); - mute( data.readInt32() ); - return NO_ERROR; - } break; case PAUSE: { CHECK_INTERFACE(IAudioTrack, data, reply); pause(); diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp index cb07766..e79bcd2 100644 --- a/media/libmedia/IMediaPlayer.cpp +++ b/media/libmedia/IMediaPlayer.cpp @@ -24,7 +24,7 @@ #include <media/IMediaPlayer.h> #include <media/IStreamSource.h> -#include <gui/ISurfaceTexture.h> +#include <gui/IGraphicBufferProducer.h> #include <utils/String8.h> namespace android { @@ -113,12 +113,12 @@ public: return reply.readInt32(); } - // pass the buffered ISurfaceTexture to the media player service - status_t setVideoSurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture) + // pass the buffered IGraphicBufferProducer to the media player service + status_t setVideoSurfaceTexture(const sp<IGraphicBufferProducer>& bufferProducer) { Parcel data, reply; data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); - sp<IBinder> b(surfaceTexture->asBinder()); + sp<IBinder> b(bufferProducer->asBinder()); data.writeStrongBinder(b); remote()->transact(SET_VIDEO_SURFACETEXTURE, data, &reply); return reply.readInt32(); @@ -383,9 +383,9 @@ status_t BnMediaPlayer::onTransact( } case SET_VIDEO_SURFACETEXTURE: { CHECK_INTERFACE(IMediaPlayer, data, reply); - sp<ISurfaceTexture> surfaceTexture = - interface_cast<ISurfaceTexture>(data.readStrongBinder()); - reply->writeInt32(setVideoSurfaceTexture(surfaceTexture)); + sp<IGraphicBufferProducer> bufferProducer = + interface_cast<IGraphicBufferProducer>(data.readStrongBinder()); + reply->writeInt32(setVideoSurfaceTexture(bufferProducer)); return NO_ERROR; } break; case PREPARE_ASYNC: { diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp index a710fd7..fdbc747 100644 --- a/media/libmedia/IMediaRecorder.cpp +++ b/media/libmedia/IMediaRecorder.cpp @@ -23,7 +23,7 @@ #include <media/IMediaRecorderClient.h> #include <media/IMediaRecorder.h> #include <gui/Surface.h> -#include <gui/ISurfaceTexture.h> +#include <gui/IGraphicBufferProducer.h> #include <unistd.h> @@ -73,7 +73,7 @@ public: return reply.readInt32(); } - sp<ISurfaceTexture> querySurfaceMediaSource() + sp<IGraphicBufferProducer> querySurfaceMediaSource() { ALOGV("Query SurfaceMediaSource"); Parcel data, reply; @@ -83,7 +83,7 @@ public: if (returnedNull) { return NULL; } - return interface_cast<ISurfaceTexture>(reply.readStrongBinder()); + return interface_cast<IGraphicBufferProducer>(reply.readStrongBinder()); } status_t setPreviewSurface(const sp<Surface>& surface) @@ -444,7 +444,7 @@ status_t BnMediaRecorder::onTransact( CHECK_INTERFACE(IMediaRecorder, data, reply); // call the mediaserver side to create // a surfacemediasource - sp<ISurfaceTexture> surfaceMediaSource = querySurfaceMediaSource(); + sp<IGraphicBufferProducer> surfaceMediaSource = querySurfaceMediaSource(); // The mediaserver might have failed to create a source int returnedNull= (surfaceMediaSource == NULL) ? 1 : 0 ; reply->writeInt32(returnedNull); diff --git a/media/libmedia/IRemoteDisplay.cpp b/media/libmedia/IRemoteDisplay.cpp index da25a15..1e15434 100644 --- a/media/libmedia/IRemoteDisplay.cpp +++ b/media/libmedia/IRemoteDisplay.cpp @@ -23,6 +23,8 @@ namespace android { enum { DISPOSE = IBinder::FIRST_CALL_TRANSACTION, + PAUSE, + RESUME, }; class BpRemoteDisplay: public BpInterface<IRemoteDisplay> @@ -33,6 +35,20 @@ public: { } + virtual status_t pause() { + Parcel data, reply; + data.writeInterfaceToken(IRemoteDisplay::getInterfaceDescriptor()); + remote()->transact(PAUSE, data, &reply); + return reply.readInt32(); + } + + virtual status_t resume() { + Parcel data, reply; + data.writeInterfaceToken(IRemoteDisplay::getInterfaceDescriptor()); + remote()->transact(RESUME, data, &reply); + return reply.readInt32(); + } + status_t dispose() { Parcel data, reply; @@ -55,6 +71,21 @@ status_t BnRemoteDisplay::onTransact( reply->writeInt32(dispose()); return NO_ERROR; } + + case PAUSE: + { + CHECK_INTERFACE(IRemoteDisplay, data, reply); + reply->writeInt32(pause()); + return OK; + } + + case RESUME: + { + CHECK_INTERFACE(IRemoteDisplay, data, reply); + reply->writeInt32(resume()); + return OK; + } + default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libmedia/IRemoteDisplayClient.cpp b/media/libmedia/IRemoteDisplayClient.cpp index 4a1b570..5c494b3 100644 --- a/media/libmedia/IRemoteDisplayClient.cpp +++ b/media/libmedia/IRemoteDisplayClient.cpp @@ -18,7 +18,7 @@ #include <sys/types.h> #include <media/IRemoteDisplayClient.h> -#include <gui/ISurfaceTexture.h> +#include <gui/IGraphicBufferProducer.h> #include <utils/String8.h> namespace android { @@ -37,12 +37,12 @@ public: { } - void onDisplayConnected(const sp<ISurfaceTexture>& surfaceTexture, + void onDisplayConnected(const sp<IGraphicBufferProducer>& bufferProducer, uint32_t width, uint32_t height, uint32_t flags) { Parcel data, reply; data.writeInterfaceToken(IRemoteDisplayClient::getInterfaceDescriptor()); - data.writeStrongBinder(surfaceTexture->asBinder()); + data.writeStrongBinder(bufferProducer->asBinder()); data.writeInt32(width); data.writeInt32(height); data.writeInt32(flags); @@ -75,8 +75,8 @@ status_t BnRemoteDisplayClient::onTransact( switch (code) { case ON_DISPLAY_CONNECTED: { CHECK_INTERFACE(IRemoteDisplayClient, data, reply); - sp<ISurfaceTexture> surfaceTexture( - interface_cast<ISurfaceTexture>(data.readStrongBinder())); + sp<IGraphicBufferProducer> surfaceTexture( + interface_cast<IGraphicBufferProducer>(data.readStrongBinder())); uint32_t width = data.readInt32(); uint32_t height = data.readInt32(); uint32_t flags = data.readInt32(); diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index bbbf4b6..ae527e8 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -221,12 +221,12 @@ status_t MediaPlayer::getMetadata(bool update_only, bool apply_filter, Parcel *m } status_t MediaPlayer::setVideoSurfaceTexture( - const sp<ISurfaceTexture>& surfaceTexture) + const sp<IGraphicBufferProducer>& bufferProducer) { ALOGV("setVideoSurfaceTexture"); Mutex::Autolock _l(mLock); if (mPlayer == 0) return NO_INIT; - return mPlayer->setVideoSurfaceTexture(surfaceTexture); + return mPlayer->setVideoSurfaceTexture(bufferProducer); } // must call with lock held diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index 9541015..95c7f3e 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -24,7 +24,7 @@ #include <media/IMediaPlayerService.h> #include <media/IMediaRecorder.h> #include <media/mediaplayer.h> // for MEDIA_ERROR_SERVER_DIED -#include <gui/ISurfaceTexture.h> +#include <gui/IGraphicBufferProducer.h> namespace android { @@ -348,9 +348,9 @@ status_t MediaRecorder::setVideoSize(int width, int height) } // Query a SurfaceMediaSurface through the Mediaserver, over the -// binder interface. This is used by the Filter Framework (MeidaEncoder) -// to get an <ISurfaceTexture> object to hook up to ANativeWindow. -sp<ISurfaceTexture> MediaRecorder:: +// binder interface. This is used by the Filter Framework (MediaEncoder) +// to get an <IGraphicBufferProducer> object to hook up to ANativeWindow. +sp<IGraphicBufferProducer> MediaRecorder:: querySurfaceMediaSourceFromMediaServer() { Mutex::Autolock _l(mLock); diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index c3e5c40..4ca0811 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -714,21 +714,21 @@ void MediaPlayerService::Client::disconnectNativeWindow() { } status_t MediaPlayerService::Client::setVideoSurfaceTexture( - const sp<ISurfaceTexture>& surfaceTexture) + const sp<IGraphicBufferProducer>& bufferProducer) { - ALOGV("[%d] setVideoSurfaceTexture(%p)", mConnId, surfaceTexture.get()); + ALOGV("[%d] setVideoSurfaceTexture(%p)", mConnId, bufferProducer.get()); sp<MediaPlayerBase> p = getPlayer(); if (p == 0) return UNKNOWN_ERROR; - sp<IBinder> binder(surfaceTexture == NULL ? NULL : - surfaceTexture->asBinder()); + sp<IBinder> binder(bufferProducer == NULL ? NULL : + bufferProducer->asBinder()); if (mConnectedWindowBinder == binder) { return OK; } sp<ANativeWindow> anw; - if (surfaceTexture != NULL) { - anw = new SurfaceTextureClient(surfaceTexture); + if (bufferProducer != NULL) { + anw = new SurfaceTextureClient(bufferProducer); status_t err = native_window_api_connect(anw.get(), NATIVE_WINDOW_API_MEDIA); @@ -745,10 +745,10 @@ status_t MediaPlayerService::Client::setVideoSurfaceTexture( } } - // Note that we must set the player's new SurfaceTexture before + // Note that we must set the player's new GraphicBufferProducer before // disconnecting the old one. Otherwise queue/dequeue calls could be made // on the disconnected ANW, which may result in errors. - status_t err = p->setVideoSurfaceTexture(surfaceTexture); + status_t err = p->setVideoSurfaceTexture(bufferProducer); disconnectNativeWindow(); diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index fd648df..afb6780 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -307,7 +307,7 @@ private: // IMediaPlayer interface virtual void disconnect(); virtual status_t setVideoSurfaceTexture( - const sp<ISurfaceTexture>& surfaceTexture); + const sp<IGraphicBufferProducer>& bufferProducer); virtual status_t prepareAsync(); virtual status_t start(); virtual status_t stop(); diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp index eadc8ee..c6d8b76 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.cpp +++ b/media/libmediaplayerservice/MediaRecorderClient.cpp @@ -38,7 +38,7 @@ #include "MediaPlayerService.h" #include "StagefrightRecorder.h" -#include <gui/ISurfaceTexture.h> +#include <gui/IGraphicBufferProducer.h> namespace android { @@ -56,7 +56,7 @@ static bool checkPermission(const char* permissionString) { } -sp<ISurfaceTexture> MediaRecorderClient::querySurfaceMediaSource() +sp<IGraphicBufferProducer> MediaRecorderClient::querySurfaceMediaSource() { ALOGV("Query SurfaceMediaSource"); Mutex::Autolock lock(mLock); diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h index c9ccf22..5623917 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.h +++ b/media/libmediaplayerservice/MediaRecorderClient.h @@ -25,7 +25,7 @@ namespace android { class MediaRecorderBase; class MediaPlayerService; class ICameraRecordingProxy; -class ISurfaceTexture; +class IGraphicBufferProducer; class MediaRecorderClient : public BnMediaRecorder { @@ -55,7 +55,7 @@ public: virtual status_t close(); virtual status_t release(); virtual status_t dump(int fd, const Vector<String16>& args) const; - virtual sp<ISurfaceTexture> querySurfaceMediaSource(); + virtual sp<IGraphicBufferProducer> querySurfaceMediaSource(); private: friend class MediaPlayerService; // for accessing private constructor diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h index f6f8f7b..24d59b4 100644 --- a/media/libmediaplayerservice/MidiFile.h +++ b/media/libmediaplayerservice/MidiFile.h @@ -36,7 +36,7 @@ public: virtual status_t setDataSource(int fd, int64_t offset, int64_t length); virtual status_t setVideoSurfaceTexture( - const sp<ISurfaceTexture>& surfaceTexture) + const sp<IGraphicBufferProducer>& bufferProducer) { return UNKNOWN_ERROR; } virtual status_t prepare(); virtual status_t prepareAsync(); diff --git a/media/libmediaplayerservice/RemoteDisplay.cpp b/media/libmediaplayerservice/RemoteDisplay.cpp index 5baa3ad..20e6513 100644 --- a/media/libmediaplayerservice/RemoteDisplay.cpp +++ b/media/libmediaplayerservice/RemoteDisplay.cpp @@ -40,6 +40,14 @@ RemoteDisplay::RemoteDisplay( RemoteDisplay::~RemoteDisplay() { } +status_t RemoteDisplay::pause() { + return mSource->pause(); +} + +status_t RemoteDisplay::resume() { + return mSource->resume(); +} + status_t RemoteDisplay::dispose() { mSource->stop(); diff --git a/media/libmediaplayerservice/RemoteDisplay.h b/media/libmediaplayerservice/RemoteDisplay.h index 0d87250..bd8b684 100644 --- a/media/libmediaplayerservice/RemoteDisplay.h +++ b/media/libmediaplayerservice/RemoteDisplay.h @@ -33,6 +33,8 @@ struct WifiDisplaySource; struct RemoteDisplay : public BnRemoteDisplay { RemoteDisplay(const sp<IRemoteDisplayClient> &client, const char *iface); + virtual status_t pause(); + virtual status_t resume(); virtual status_t dispose(); protected: diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp index 619c149..de61d9b 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.cpp +++ b/media/libmediaplayerservice/StagefrightPlayer.cpp @@ -70,10 +70,10 @@ status_t StagefrightPlayer::setDataSource(const sp<IStreamSource> &source) { } status_t StagefrightPlayer::setVideoSurfaceTexture( - const sp<ISurfaceTexture> &surfaceTexture) { + const sp<IGraphicBufferProducer> &bufferProducer) { ALOGV("setVideoSurfaceTexture"); - return mPlayer->setSurfaceTexture(surfaceTexture); + return mPlayer->setSurfaceTexture(bufferProducer); } status_t StagefrightPlayer::prepare() { diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h index e89e18a..600945e 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.h +++ b/media/libmediaplayerservice/StagefrightPlayer.h @@ -41,7 +41,7 @@ public: virtual status_t setDataSource(const sp<IStreamSource> &source); virtual status_t setVideoSurfaceTexture( - const sp<ISurfaceTexture> &surfaceTexture); + const sp<IGraphicBufferProducer> &bufferProducer); virtual status_t prepare(); virtual status_t prepareAsync(); virtual status_t start(); diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 57b0ec2..497dda6 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -89,7 +89,7 @@ status_t StagefrightRecorder::init() { // The client side of mediaserver asks it to creat a SurfaceMediaSource // and return a interface reference. The client side will use that // while encoding GL Frames -sp<ISurfaceTexture> StagefrightRecorder::querySurfaceMediaSource() const { +sp<IGraphicBufferProducer> StagefrightRecorder::querySurfaceMediaSource() const { ALOGV("Get SurfaceMediaSource"); return mSurfaceMediaSource->getBufferQueue(); } diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h index ec5ce7e..351efd4 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -35,7 +35,7 @@ struct MediaWriter; class MetaData; struct AudioSource; class MediaProfiles; -class ISurfaceTexture; +class IGraphicBufferProducer; class SurfaceMediaSource; struct StagefrightRecorder : public MediaRecorderBase { @@ -65,7 +65,7 @@ struct StagefrightRecorder : public MediaRecorderBase { virtual status_t getMaxAmplitude(int *max); virtual status_t dump(int fd, const Vector<String16>& args) const; // Querying a SurfaceMediaSourcer - virtual sp<ISurfaceTexture> querySurfaceMediaSource() const; + virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() const; private: sp<ICamera> mCamera; @@ -116,7 +116,7 @@ private: bool mStarted; // Needed when GLFrames are encoded. - // An <ISurfaceTexture> pointer + // An <IGraphicBufferProducer> pointer // will be sent to the client side using which the // frame buffers will be queued and dequeued sp<SurfaceMediaSource> mSurfaceMediaSource; diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h index 91ffa7d..a3802eb 100644 --- a/media/libmediaplayerservice/TestPlayerStub.h +++ b/media/libmediaplayerservice/TestPlayerStub.h @@ -76,7 +76,7 @@ class TestPlayerStub : public MediaPlayerInterface { // All the methods below wrap the mPlayer instance. virtual status_t setVideoSurfaceTexture( - const android::sp<android::ISurfaceTexture>& st) { + const android::sp<android::IGraphicBufferProducer>& st) { return mPlayer->setVideoSurfaceTexture(st); } virtual status_t prepare() {return mPlayer->prepare();} diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index d3ec122..517fb34 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -41,7 +41,7 @@ #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaErrors.h> #include <media/stagefright/MetaData.h> -#include <gui/ISurfaceTexture.h> +#include <gui/IGraphicBufferProducer.h> #include "avc_utils.h" @@ -50,6 +50,64 @@ namespace android { +struct NuPlayer::Action : public RefBase { + Action() {} + + virtual void execute(NuPlayer *player) = 0; + +private: + DISALLOW_EVIL_CONSTRUCTORS(Action); +}; + +struct NuPlayer::SeekAction : public Action { + SeekAction(int64_t seekTimeUs) + : mSeekTimeUs(seekTimeUs) { + } + + virtual void execute(NuPlayer *player) { + player->performSeek(mSeekTimeUs); + } + +private: + int64_t mSeekTimeUs; + + DISALLOW_EVIL_CONSTRUCTORS(SeekAction); +}; + +struct NuPlayer::SetSurfaceAction : public Action { + SetSurfaceAction(const sp<NativeWindowWrapper> &wrapper) + : mWrapper(wrapper) { + } + + virtual void execute(NuPlayer *player) { + player->performSetSurface(mWrapper); + } + +private: + sp<NativeWindowWrapper> mWrapper; + + DISALLOW_EVIL_CONSTRUCTORS(SetSurfaceAction); +}; + +// Use this if there's no state necessary to save in order to execute +// the action. +struct NuPlayer::SimpleAction : public Action { + typedef void (NuPlayer::*ActionFunc)(); + + SimpleAction(ActionFunc func) + : mFunc(func) { + } + + virtual void execute(NuPlayer *player) { + (player->*mFunc)(); + } + +private: + ActionFunc mFunc; + + DISALLOW_EVIL_CONSTRUCTORS(SimpleAction); +}; + //////////////////////////////////////////////////////////////////////////////// NuPlayer::NuPlayer() @@ -63,14 +121,13 @@ NuPlayer::NuPlayer() mTimeDiscontinuityPending(false), mFlushingAudio(NONE), mFlushingVideo(NONE), - mResetInProgress(false), - mResetPostponed(false), mSkipRenderingAudioUntilMediaTimeUs(-1ll), mSkipRenderingVideoUntilMediaTimeUs(-1ll), mVideoLateByUs(0ll), mNumFramesTotal(0ll), mNumFramesDropped(0ll), - mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) { + mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW), + mStarted(false) { } NuPlayer::~NuPlayer() { @@ -140,11 +197,19 @@ void NuPlayer::setDataSource(int fd, int64_t offset, int64_t length) { msg->post(); } -void NuPlayer::setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) { +void NuPlayer::setVideoSurfaceTextureAsync( + const sp<IGraphicBufferProducer> &bufferProducer) { sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id()); - sp<SurfaceTextureClient> surfaceTextureClient(surfaceTexture != NULL ? - new SurfaceTextureClient(surfaceTexture) : NULL); - msg->setObject("native-window", new NativeWindowWrapper(surfaceTextureClient)); + + if (bufferProducer == NULL) { + msg->setObject("native-window", NULL); + } else { + msg->setObject( + "native-window", + new NativeWindowWrapper( + new SurfaceTextureClient(bufferProducer))); + } + msg->post(); } @@ -237,13 +302,24 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { { ALOGV("kWhatSetVideoNativeWindow"); + mDeferredActions.push_back( + new SimpleAction(&NuPlayer::performDecoderShutdown)); + sp<RefBase> obj; CHECK(msg->findObject("native-window", &obj)); - mNativeWindow = static_cast<NativeWindowWrapper *>(obj.get()); + mDeferredActions.push_back( + new SetSurfaceAction( + static_cast<NativeWindowWrapper *>(obj.get()))); - // XXX - ignore error from setVideoScalingMode for now - setVideoScalingMode(mVideoScalingMode); + if (obj != NULL) { + // If there is a new surface texture, instantiate decoders + // again if possible. + mDeferredActions.push_back( + new SimpleAction(&NuPlayer::performScanSources)); + } + + processDeferredActions(); break; } @@ -270,6 +346,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { mVideoLateByUs = 0; mNumFramesTotal = 0; mNumFramesDropped = 0; + mStarted = true; mSource->start(); @@ -407,7 +484,8 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { } else if (what == ACodec::kWhatOutputFormatChanged) { if (audio) { int32_t numChannels; - CHECK(codecRequest->findInt32("channel-count", &numChannels)); + CHECK(codecRequest->findInt32( + "channel-count", &numChannels)); int32_t sampleRate; CHECK(codecRequest->findInt32("sample-rate", &sampleRate)); @@ -419,13 +497,15 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { audio_output_flags_t flags; int64_t durationUs; - // FIXME: we should handle the case where the video decoder is created after - // we receive the format change indication. Current code will just make that - // we select deep buffer with video which should not be a problem as it should + // FIXME: we should handle the case where the video decoder + // is created after we receive the format change indication. + // Current code will just make that we select deep buffer + // with video which should not be a problem as it should // not prevent from keeping A/V sync. if (mVideoDecoder == NULL && mSource->getDuration(&durationUs) == OK && - durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) { + durationUs + > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) { flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER; } else { flags = AUDIO_OUTPUT_FLAG_NONE; @@ -461,17 +541,35 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { "crop", &cropLeft, &cropTop, &cropRight, &cropBottom)); + int32_t displayWidth = cropRight - cropLeft + 1; + int32_t displayHeight = cropBottom - cropTop + 1; + ALOGV("Video output format changed to %d x %d " "(crop: %d x %d @ (%d, %d))", width, height, - (cropRight - cropLeft + 1), - (cropBottom - cropTop + 1), + displayWidth, + displayHeight, cropLeft, cropTop); + sp<AMessage> videoInputFormat = + mSource->getFormat(false /* audio */); + + // Take into account sample aspect ratio if necessary: + int32_t sarWidth, sarHeight; + if (videoInputFormat->findInt32("sar-width", &sarWidth) + && videoInputFormat->findInt32( + "sar-height", &sarHeight)) { + ALOGV("Sample aspect ratio %d : %d", + sarWidth, sarHeight); + + displayWidth = (displayWidth * sarWidth) / sarHeight; + + ALOGV("display dimensions %d x %d", + displayWidth, displayHeight); + } + notifyListener( - MEDIA_SET_VIDEO_SIZE, - cropRight - cropLeft + 1, - cropBottom - cropTop + 1); + MEDIA_SET_VIDEO_SIZE, displayWidth, displayHeight); } } else if (what == ACodec::kWhatShutdownCompleted) { ALOGV("%s shutdown completed", audio ? "audio" : "video"); @@ -495,8 +593,15 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { mRenderer->queueEOS(audio, UNKNOWN_ERROR); } else if (what == ACodec::kWhatDrainThisBuffer) { renderBuffer(audio, codecRequest); - } else { - ALOGV("Unhandled codec notification %d.", what); + } else if (what != ACodec::kWhatComponentAllocated + && what != ACodec::kWhatComponentConfigured + && what != ACodec::kWhatBuffersAllocated) { + ALOGV("Unhandled codec notification %d '%c%c%c%c'.", + what, + what >> 24, + (what >> 16) & 0xff, + (what >> 8) & 0xff, + what & 0xff); } break; @@ -569,47 +674,13 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { { ALOGV("kWhatReset"); - cancelPollDuration(); - - if (mRenderer != NULL) { - // There's an edge case where the renderer owns all output - // buffers and is paused, therefore the decoder will not read - // more input data and will never encounter the matching - // discontinuity. To avoid this, we resume the renderer. - - if (mFlushingAudio == AWAITING_DISCONTINUITY - || mFlushingVideo == AWAITING_DISCONTINUITY) { - mRenderer->resume(); - } - } - - if (mFlushingAudio != NONE || mFlushingVideo != NONE) { - // We're currently flushing, postpone the reset until that's - // completed. - - ALOGV("postponing reset mFlushingAudio=%d, mFlushingVideo=%d", - mFlushingAudio, mFlushingVideo); + mDeferredActions.push_back( + new SimpleAction(&NuPlayer::performDecoderShutdown)); - mResetPostponed = true; - break; - } + mDeferredActions.push_back( + new SimpleAction(&NuPlayer::performReset)); - if (mAudioDecoder == NULL && mVideoDecoder == NULL) { - finishReset(); - break; - } - - mTimeDiscontinuityPending = true; - - if (mAudioDecoder != NULL) { - flushDecoder(true /* audio */, true /* needShutdown */); - } - - if (mVideoDecoder != NULL) { - flushDecoder(false /* audio */, true /* needShutdown */); - } - - mResetInProgress = true; + processDeferredActions(); break; } @@ -618,18 +689,14 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { int64_t seekTimeUs; CHECK(msg->findInt64("seekTimeUs", &seekTimeUs)); - ALOGV("kWhatSeek seekTimeUs=%lld us (%.2f secs)", - seekTimeUs, seekTimeUs / 1E6); + ALOGV("kWhatSeek seekTimeUs=%lld us", seekTimeUs); - mSource->seekTo(seekTimeUs); + mDeferredActions.push_back( + new SimpleAction(&NuPlayer::performDecoderFlush)); - if (mDriver != NULL) { - sp<NuPlayerDriver> driver = mDriver.promote(); - if (driver != NULL) { - driver->notifySeekComplete(); - } - } + mDeferredActions.push_back(new SeekAction(seekTimeUs)); + processDeferredActions(); break; } @@ -680,39 +747,7 @@ void NuPlayer::finishFlushIfPossible() { mFlushingAudio = NONE; mFlushingVideo = NONE; - if (mResetInProgress) { - ALOGV("reset completed"); - - mResetInProgress = false; - finishReset(); - } else if (mResetPostponed) { - (new AMessage(kWhatReset, id()))->post(); - mResetPostponed = false; - } else if (mAudioDecoder == NULL || mVideoDecoder == NULL) { - postScanSources(); - } -} - -void NuPlayer::finishReset() { - CHECK(mAudioDecoder == NULL); - CHECK(mVideoDecoder == NULL); - - ++mScanSourcesGeneration; - mScanSourcesPending = false; - - mRenderer.clear(); - - if (mSource != NULL) { - mSource->stop(); - mSource.clear(); - } - - if (mDriver != NULL) { - sp<NuPlayerDriver> driver = mDriver.promote(); - if (driver != NULL) { - driver->notifyResetComplete(); - } - } + processDeferredActions(); } void NuPlayer::postScanSources() { @@ -831,6 +866,14 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) { mTimeDiscontinuityPending || timeChange; if (formatChange || timeChange) { + if (mFlushingAudio == NONE && mFlushingVideo == NONE) { + // And we'll resume scanning sources once we're done + // flushing. + mDeferredActions.push_front( + new SimpleAction( + &NuPlayer::performScanSources)); + } + flushDecoder(audio, formatChange); } else { // This stream is unaffected by the discontinuity @@ -1000,8 +1043,7 @@ sp<AMessage> NuPlayer::Source::getFormat(bool audio) { status_t NuPlayer::setVideoScalingMode(int32_t mode) { mVideoScalingMode = mode; - if (mNativeWindow != NULL - && mNativeWindow->getNativeWindow() != NULL) { + if (mNativeWindow != NULL) { status_t ret = native_window_set_scaling_mode( mNativeWindow->getNativeWindow().get(), mVideoScalingMode); if (ret != OK) { @@ -1023,4 +1065,149 @@ void NuPlayer::cancelPollDuration() { ++mPollDurationGeneration; } +void NuPlayer::processDeferredActions() { + while (!mDeferredActions.empty()) { + // We won't execute any deferred actions until we're no longer in + // an intermediate state, i.e. one more more decoders are currently + // flushing or shutting down. + + if (mRenderer != NULL) { + // There's an edge case where the renderer owns all output + // buffers and is paused, therefore the decoder will not read + // more input data and will never encounter the matching + // discontinuity. To avoid this, we resume the renderer. + + if (mFlushingAudio == AWAITING_DISCONTINUITY + || mFlushingVideo == AWAITING_DISCONTINUITY) { + mRenderer->resume(); + } + } + + if (mFlushingAudio != NONE || mFlushingVideo != NONE) { + // We're currently flushing, postpone the reset until that's + // completed. + + ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d", + mFlushingAudio, mFlushingVideo); + + break; + } + + sp<Action> action = *mDeferredActions.begin(); + mDeferredActions.erase(mDeferredActions.begin()); + + action->execute(this); + } +} + +void NuPlayer::performSeek(int64_t seekTimeUs) { + ALOGV("performSeek seekTimeUs=%lld us (%.2f secs)", + seekTimeUs, + seekTimeUs / 1E6); + + mSource->seekTo(seekTimeUs); + + if (mDriver != NULL) { + sp<NuPlayerDriver> driver = mDriver.promote(); + if (driver != NULL) { + driver->notifyPosition(seekTimeUs); + driver->notifySeekComplete(); + } + } + + // everything's flushed, continue playback. +} + +void NuPlayer::performDecoderFlush() { + ALOGV("performDecoderFlush"); + + if (mAudioDecoder != NULL && mVideoDecoder == NULL) { + return; + } + + mTimeDiscontinuityPending = true; + + if (mAudioDecoder != NULL) { + flushDecoder(true /* audio */, false /* needShutdown */); + } + + if (mVideoDecoder != NULL) { + flushDecoder(false /* audio */, false /* needShutdown */); + } +} + +void NuPlayer::performDecoderShutdown() { + ALOGV("performDecoderShutdown"); + + if (mAudioDecoder != NULL && mVideoDecoder == NULL) { + return; + } + + mTimeDiscontinuityPending = true; + + if (mAudioDecoder != NULL) { + flushDecoder(true /* audio */, true /* needShutdown */); + } + + if (mVideoDecoder != NULL) { + flushDecoder(false /* audio */, true /* needShutdown */); + } +} + +void NuPlayer::performReset() { + ALOGV("performReset"); + + CHECK(mAudioDecoder == NULL); + CHECK(mVideoDecoder == NULL); + + cancelPollDuration(); + + ++mScanSourcesGeneration; + mScanSourcesPending = false; + + mRenderer.clear(); + + if (mSource != NULL) { + mSource->stop(); + mSource.clear(); + } + + if (mDriver != NULL) { + sp<NuPlayerDriver> driver = mDriver.promote(); + if (driver != NULL) { + driver->notifyResetComplete(); + } + } + + mStarted = false; +} + +void NuPlayer::performScanSources() { + ALOGV("performScanSources"); + + if (!mStarted) { + return; + } + + if (mAudioDecoder == NULL || mVideoDecoder == NULL) { + postScanSources(); + } +} + +void NuPlayer::performSetSurface(const sp<NativeWindowWrapper> &wrapper) { + ALOGV("performSetSurface"); + + mNativeWindow = wrapper; + + // XXX - ignore error from setVideoScalingMode for now + setVideoScalingMode(mVideoScalingMode); + + if (mDriver != NULL) { + sp<NuPlayerDriver> driver = mDriver.promote(); + if (driver != NULL) { + driver->notifySetSurfaceComplete(); + } + } +} + } // namespace android diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h index 31efb2e..09fc0ba 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h @@ -42,7 +42,9 @@ struct NuPlayer : public AHandler { void setDataSource(int fd, int64_t offset, int64_t length); - void setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture); + void setVideoSurfaceTextureAsync( + const sp<IGraphicBufferProducer> &bufferProducer); + void setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink); void start(); @@ -73,6 +75,10 @@ private: struct Renderer; struct RTSPSource; struct StreamingSource; + struct Action; + struct SeekAction; + struct SetSurfaceAction; + struct SimpleAction; enum { kWhatSetDataSource = '=DaS', @@ -102,6 +108,8 @@ private: sp<Decoder> mAudioDecoder; sp<Renderer> mRenderer; + List<sp<Action> > mDeferredActions; + bool mAudioEOS; bool mVideoEOS; @@ -126,8 +134,6 @@ private: FlushStatus mFlushingAudio; FlushStatus mFlushingVideo; - bool mResetInProgress; - bool mResetPostponed; int64_t mSkipRenderingAudioUntilMediaTimeUs; int64_t mSkipRenderingVideoUntilMediaTimeUs; @@ -137,6 +143,8 @@ private: int32_t mVideoScalingMode; + bool mStarted; + status_t instantiateDecoder(bool audio, sp<Decoder> *decoder); status_t feedDecoderInputData(bool audio, const sp<AMessage> &msg); @@ -150,12 +158,20 @@ private: static bool IsFlushingState(FlushStatus state, bool *needShutdown = NULL); - void finishReset(); void postScanSources(); void schedulePollDuration(); void cancelPollDuration(); + void processDeferredActions(); + + void performSeek(int64_t seekTimeUs); + void performDecoderFlush(); + void performDecoderShutdown(); + void performReset(); + void performScanSources(); + void performSetSurface(const sp<NativeWindowWrapper> &wrapper); + DISALLOW_EVIL_CONSTRUCTORS(NuPlayer); }; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp index d03601f..7043404 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp @@ -29,6 +29,7 @@ namespace android { NuPlayerDriver::NuPlayerDriver() : mResetInProgress(false), + mSetSurfaceInProgress(false), mDurationUs(-1), mPositionUs(-1), mNumFramesTotal(0), @@ -96,8 +97,20 @@ status_t NuPlayerDriver::setDataSource(const sp<IStreamSource> &source) { } status_t NuPlayerDriver::setVideoSurfaceTexture( - const sp<ISurfaceTexture> &surfaceTexture) { - mPlayer->setVideoSurfaceTexture(surfaceTexture); + const sp<IGraphicBufferProducer> &bufferProducer) { + Mutex::Autolock autoLock(mLock); + + if (mResetInProgress) { + return INVALID_OPERATION; + } + + mSetSurfaceInProgress = true; + + mPlayer->setVideoSurfaceTextureAsync(bufferProducer); + + while (mSetSurfaceInProgress) { + mCondition.wait(mLock); + } return OK; } @@ -308,6 +321,13 @@ void NuPlayerDriver::notifyResetComplete() { mCondition.broadcast(); } +void NuPlayerDriver::notifySetSurfaceComplete() { + Mutex::Autolock autoLock(mLock); + CHECK(mSetSurfaceInProgress); + mSetSurfaceInProgress = false; + mCondition.broadcast(); +} + void NuPlayerDriver::notifyDuration(int64_t durationUs) { Mutex::Autolock autoLock(mLock); mDurationUs = durationUs; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h index 4a0026c..553c406 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h @@ -38,7 +38,7 @@ struct NuPlayerDriver : public MediaPlayerInterface { virtual status_t setDataSource(const sp<IStreamSource> &source); virtual status_t setVideoSurfaceTexture( - const sp<ISurfaceTexture> &surfaceTexture); + const sp<IGraphicBufferProducer> &bufferProducer); virtual status_t prepare(); virtual status_t prepareAsync(); virtual status_t start(); @@ -62,6 +62,7 @@ struct NuPlayerDriver : public MediaPlayerInterface { virtual status_t dump(int fd, const Vector<String16> &args) const; void notifyResetComplete(); + void notifySetSurfaceComplete(); void notifyDuration(int64_t durationUs); void notifyPosition(int64_t positionUs); void notifySeekComplete(); @@ -78,6 +79,7 @@ private: // The following are protected through "mLock" // >>> bool mResetInProgress; + bool mSetSurfaceInProgress; int64_t mDurationUs; int64_t mPositionUs; int64_t mNumFramesTotal; diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index a135222..7920d32 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -612,7 +612,7 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() { sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); BufferInfo info; info.mStatus = BufferInfo::OWNED_BY_US; - info.mData = new ABuffer(0); + info.mData = new ABuffer(NULL /* data */, def.nBufferSize /* capacity */); info.mGraphicBuffer = graphicBuffer; mBuffers[kPortIndexOutput].push(info); @@ -966,17 +966,23 @@ status_t ACodec::configureCodec( err = INVALID_OPERATION; } else { if (encoder) { - if (!msg->findInt32("flac-compression-level", &compressionLevel)) { + if (!msg->findInt32( + "flac-compression-level", &compressionLevel)) { compressionLevel = 5;// default FLAC compression level } else if (compressionLevel < 0) { - ALOGW("compression level %d outside [0..8] range, using 0", compressionLevel); + ALOGW("compression level %d outside [0..8] range, " + "using 0", + compressionLevel); compressionLevel = 0; } else if (compressionLevel > 8) { - ALOGW("compression level %d outside [0..8] range, using 8", compressionLevel); + ALOGW("compression level %d outside [0..8] range, " + "using 8", + compressionLevel); compressionLevel = 8; } } - err = setupFlacCodec(encoder, numChannels, sampleRate, compressionLevel); + err = setupFlacCodec( + encoder, numChannels, sampleRate, compressionLevel); } } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { int32_t numChannels, sampleRate; @@ -1632,6 +1638,43 @@ status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) { return err; } +status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) { + OMX_VIDEO_PARAM_INTRAREFRESHTYPE params; + InitOMXParams(¶ms); + params.nPortIndex = kPortIndexOutput; + + params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode); + + if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic || + params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { + int32_t mbs; + if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) { + return INVALID_OPERATION; + } + params.nCirMBs = mbs; + } + + if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive || + params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { + int32_t mbs; + if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) { + return INVALID_OPERATION; + } + params.nAirMBs = mbs; + + int32_t ref; + if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) { + return INVALID_OPERATION; + } + params.nAirRef = ref; + } + + status_t err = mOMX->setParameter( + mNode, OMX_IndexParamVideoIntraRefresh, + ¶ms, sizeof(params)); + return err; +} + static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) { if (iFramesInterval < 0) { return 0xFFFFFFFF; @@ -1827,11 +1870,22 @@ status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) { frameRate = (float)tmp; } + status_t err = OK; + int32_t intraRefreshMode = 0; + if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) { + err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode); + if (err != OK) { + ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x", + err, intraRefreshMode); + return err; + } + } + OMX_VIDEO_PARAM_AVCTYPE h264type; InitOMXParams(&h264type); h264type.nPortIndex = kPortIndexOutput; - status_t err = mOMX->getParameter( + err = mOMX->getParameter( mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); if (err != OK) { @@ -2814,15 +2868,14 @@ bool ACodec::BaseState::onOMXFillBufferDone( mCodec->sendFormatChange(); } - if (mCodec->mNativeWindow == NULL) { - info->mData->setRange(rangeOffset, rangeLength); - + info->mData->setRange(rangeOffset, rangeLength); #if 0 + if (mCodec->mNativeWindow == NULL) { if (IsIDR(info->mData)) { ALOGI("IDR frame"); } -#endif } +#endif if (mCodec->mSkipCutBuffer != NULL) { mCodec->mSkipCutBuffer->submit(info->mData); @@ -3106,11 +3159,6 @@ bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { mCodec->mOMX = omx; mCodec->mNode = node; - mCodec->mPortEOS[kPortIndexInput] = - mCodec->mPortEOS[kPortIndexOutput] = false; - - mCodec->mInputEOSResult = OK; - { sp<AMessage> notify = mCodec->mNotify->dup(); notify->setInt32("what", ACodec::kWhatComponentAllocated); @@ -3132,6 +3180,11 @@ ACodec::LoadedState::LoadedState(ACodec *codec) void ACodec::LoadedState::stateEntered() { ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); + mCodec->mPortEOS[kPortIndexInput] = + mCodec->mPortEOS[kPortIndexOutput] = false; + + mCodec->mInputEOSResult = OK; + if (mCodec->mShutdownInProgress) { bool keepComponentAllocated = mCodec->mKeepComponentAllocated; diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index a056706..85662db 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -94,6 +94,7 @@ LOCAL_STATIC_LIBRARIES := \ libstagefright_matroska \ libstagefright_timedtext \ libvpx \ + libwebm \ libstagefright_mpeg2ts \ libstagefright_httplive \ libstagefright_id3 \ diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 1e2625a..23ce088 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -48,7 +48,7 @@ #include <media/stagefright/MetaData.h> #include <media/stagefright/OMXCodec.h> -#include <gui/ISurfaceTexture.h> +#include <gui/IGraphicBufferProducer.h> #include <gui/SurfaceTextureClient.h> #include <media/stagefright/foundation/AMessage.h> @@ -1178,12 +1178,12 @@ bool AwesomePlayer::isPlaying() const { return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN); } -status_t AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) { +status_t AwesomePlayer::setSurfaceTexture(const sp<IGraphicBufferProducer> &bufferProducer) { Mutex::Autolock autoLock(mLock); status_t err; - if (surfaceTexture != NULL) { - err = setNativeWindow_l(new SurfaceTextureClient(surfaceTexture)); + if (bufferProducer != NULL) { + err = setNativeWindow_l(new SurfaceTextureClient(bufferProducer)); } else { err = setNativeWindow_l(NULL); } diff --git a/media/libstagefright/FragmentedMP4Extractor.cpp b/media/libstagefright/FragmentedMP4Extractor.cpp index 82712ef..496828d 100644 --- a/media/libstagefright/FragmentedMP4Extractor.cpp +++ b/media/libstagefright/FragmentedMP4Extractor.cpp @@ -222,8 +222,8 @@ status_t FragmentedMPEG4Source::start(MetaData *params) { mGroup = new MediaBufferGroup; - int32_t max_size = 65536; - // XXX CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size)); + // for video, make the buffer big enough for an extremely poorly compressed 1080p frame. + int32_t max_size = mIsAudioTrack ? 65536 : 3110400; mGroup->add_buffer(new MediaBuffer(max_size)); @@ -278,6 +278,10 @@ status_t FragmentedMPEG4Source::read( sp<AMessage> meta = parseBuffer->meta(); int64_t timeUs; CHECK(meta->findInt64("timeUs", &timeUs)); + int32_t isSync; + if (meta->findInt32("is-sync-frame", &isSync) && isSync != 0) { + buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); + } buffer->meta_data()->setInt64(kKeyTime, timeUs); buffer->set_range(0, parseBuffer->size()); memcpy(buffer->data(), parseBuffer->data(), parseBuffer->size()); diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp index d94054b..380dab4 100644 --- a/media/libstagefright/MP3Extractor.cpp +++ b/media/libstagefright/MP3Extractor.cpp @@ -350,8 +350,10 @@ MP3Extractor::MP3Extractor( mInitCheck = OK; - // get iTunes-style gapless info if present - ID3 id3(mDataSource); + // Get iTunes-style gapless info if present. + // When getting the id3 tag, skip the V1 tags to prevent the source cache + // from being iterated to the end of the file. + ID3 id3(mDataSource, true); if (id3.isValid()) { ID3::Iterator *com = new ID3::Iterator(id3, "COM"); if (com->done()) { diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index b2afec7..1a62f9d 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -1424,18 +1424,15 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { if (mFileMetaData != NULL) { ALOGV("chunk_data_size = %lld and data_offset = %lld", chunk_data_size, data_offset); - uint8_t *buffer = new uint8_t[chunk_data_size + 1]; + sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1); if (mDataSource->readAt( - data_offset, buffer, chunk_data_size) != (ssize_t)chunk_data_size) { - delete[] buffer; - buffer = NULL; - + data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) { return ERROR_IO; } const int kSkipBytesOfDataBox = 16; mFileMetaData->setData( kKeyAlbumArt, MetaData::TYPE_NONE, - buffer + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox); + buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox); } *offset += chunk_size; diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp index 8b52e15..14986b2 100644 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -575,13 +575,50 @@ status_t MPEG4Writer::start(MetaData *param) { /* * When the requested file size limit is small, the priority * is to meet the file size limit requirement, rather than - * to make the file streamable. + * to make the file streamable. mStreamableFile does not tell + * whether the actual recorded file is streamable or not. */ mStreamableFile = (mMaxFileSizeLimitBytes != 0 && mMaxFileSizeLimitBytes >= kMinStreamableFileSizeInBytes); - mWriteMoovBoxToMemory = mStreamableFile; + /* + * mWriteMoovBoxToMemory is true if the amount of data in moov box is + * smaller than the reserved free space at the beginning of a file, AND + * when the content of moov box is constructed. Note that video/audio + * frame data is always written to the file but not in the memory. + * + * Before stop()/reset() is called, mWriteMoovBoxToMemory is always + * false. When reset() is called at the end of a recording session, + * Moov box needs to be constructed. + * + * 1) Right before a moov box is constructed, mWriteMoovBoxToMemory + * to set to mStreamableFile so that if + * the file is intended to be streamable, it is set to true; + * otherwise, it is set to false. When the value is set to false, + * all the content of the moov box is written immediately to + * the end of the file. When the value is set to true, all the + * content of the moov box is written to an in-memory cache, + * mMoovBoxBuffer, util the following condition happens. Note + * that the size of the in-memory cache is the same as the + * reserved free space at the beginning of the file. + * + * 2) While the data of the moov box is written to an in-memory + * cache, the data size is checked against the reserved space. + * If the data size surpasses the reserved space, subsequent moov + * data could no longer be hold in the in-memory cache. This also + * indicates that the reserved space was too small. At this point, + * _all_ moov data must be written to the end of the file. + * mWriteMoovBoxToMemory must be set to false to direct the write + * to the file. + * + * 3) If the data size in moov box is smaller than the reserved + * space after moov box is completely constructed, the in-memory + * cache copy of the moov box is written to the reserved free + * space. Thus, immediately after the moov is completedly + * constructed, mWriteMoovBoxToMemory is always set to false. + */ + mWriteMoovBoxToMemory = false; mMoovBoxBuffer = NULL; mMoovBoxBufferOffset = 0; @@ -786,15 +823,25 @@ status_t MPEG4Writer::reset() { } lseek64(mFd, mOffset, SEEK_SET); - const off64_t moovOffset = mOffset; - mWriteMoovBoxToMemory = mStreamableFile; - mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); + // Construct moov box now mMoovBoxBufferOffset = 0; - CHECK(mMoovBoxBuffer != NULL); + mWriteMoovBoxToMemory = mStreamableFile; + if (mWriteMoovBoxToMemory) { + // There is no need to allocate in-memory cache + // for moov box if the file is not streamable. + + mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); + CHECK(mMoovBoxBuffer != NULL); + } writeMoovBox(maxDurationUs); - mWriteMoovBoxToMemory = false; - if (mStreamableFile) { + // mWriteMoovBoxToMemory could be set to false in + // MPEG4Writer::write() method + if (mWriteMoovBoxToMemory) { + mWriteMoovBoxToMemory = false; + // Content of the moov box is saved in the cache, and the in-memory + // moov box needs to be written to the file in a single shot. + CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize); // Moov box @@ -806,13 +853,15 @@ status_t MPEG4Writer::reset() { lseek64(mFd, mOffset, SEEK_SET); writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); write("free", 4); + } else { + ALOGI("The mp4 file will not be streamable."); + } - // Free temp memory + // Free in-memory cache for moov box + if (mMoovBoxBuffer != NULL) { free(mMoovBoxBuffer); mMoovBoxBuffer = NULL; mMoovBoxBufferOffset = 0; - } else { - ALOGI("The mp4 file will not be streamable."); } CHECK(mBoxes.empty()); @@ -994,23 +1043,28 @@ size_t MPEG4Writer::write( const size_t bytes = size * nmemb; if (mWriteMoovBoxToMemory) { - // This happens only when we write the moov box at the end of - // recording, not for each output video/audio frame we receive. + off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes; if (moovBoxSize > mEstimatedMoovBoxSize) { + // The reserved moov box at the beginning of the file + // is not big enough. Moov box should be written to + // the end of the file from now on, but not to the + // in-memory cache. + + // We write partial moov box that is in the memory to + // the file first. for (List<off64_t>::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) { (*it) += mOffset; } lseek64(mFd, mOffset, SEEK_SET); ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset); - ::write(mFd, ptr, size * nmemb); + ::write(mFd, ptr, bytes); mOffset += (bytes + mMoovBoxBufferOffset); - free(mMoovBoxBuffer); - mMoovBoxBuffer = NULL; - mMoovBoxBufferOffset = 0; + + // All subsequent moov box content will be written + // to the end of the file. mWriteMoovBoxToMemory = false; - mStreamableFile = false; } else { memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); mMoovBoxBufferOffset += bytes; diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp index 3c002fc..0345de6 100644 --- a/media/libstagefright/SurfaceMediaSource.cpp +++ b/media/libstagefright/SurfaceMediaSource.cpp @@ -298,6 +298,10 @@ status_t SurfaceMediaSource::read( MediaBuffer **buffer, // wait for a buffer to be queued mFrameAvailableCondition.wait(mMutex); } else if (err == OK) { + err = item.mFence->waitForever(1000, "SurfaceMediaSource::read"); + if (err) { + ALOGW("read: failed to wait for buffer fence: %d", err); + } // First time seeing the buffer? Added it to the SMS slot if (item.mGraphicBuffer != NULL) { diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp index 74e9222..8ed07bf 100644 --- a/media/libstagefright/Utils.cpp +++ b/media/libstagefright/Utils.cpp @@ -78,6 +78,11 @@ status_t convertMetaDataToMessage( msg->setInt64("durationUs", durationUs); } + int32_t isSync; + if (meta->findInt32(kKeyIsSyncFrame, &isSync) && isSync != 0) { + msg->setInt32("is-sync-frame", 1); + } + if (!strncasecmp("video/", mime, 6)) { int32_t width, height; CHECK(meta->findInt32(kKeyWidth, &width)); @@ -85,6 +90,13 @@ status_t convertMetaDataToMessage( msg->setInt32("width", width); msg->setInt32("height", height); + + int32_t sarWidth, sarHeight; + if (meta->findInt32(kKeySARWidth, &sarWidth) + && meta->findInt32(kKeySARHeight, &sarHeight)) { + msg->setInt32("sar-width", sarWidth); + msg->setInt32("sar-height", sarHeight); + } } else if (!strncasecmp("audio/", mime, 6)) { int32_t numChannels, sampleRate; CHECK(meta->findInt32(kKeyChannelCount, &numChannels)); @@ -363,6 +375,11 @@ void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) { meta->setInt64(kKeyDuration, durationUs); } + int32_t isSync; + if (msg->findInt32("is-sync-frame", &isSync) && isSync != 0) { + meta->setInt32(kKeyIsSyncFrame, 1); + } + if (mime.startsWith("video/")) { int32_t width; int32_t height; @@ -372,6 +389,13 @@ void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) { } else { ALOGW("did not find width and/or height"); } + + int32_t sarWidth, sarHeight; + if (msg->findInt32("sar-width", &sarWidth) + && msg->findInt32("sar-height", &sarHeight)) { + meta->setInt32(kKeySARWidth, sarWidth); + meta->setInt32(kKeySARHeight, sarHeight); + } } else if (mime.startsWith("audio/")) { int32_t numChannels; if (msg->findInt32("channel-count", &numChannels)) { diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp index d32f4fb..22af6fb 100644 --- a/media/libstagefright/WAVExtractor.cpp +++ b/media/libstagefright/WAVExtractor.cpp @@ -426,8 +426,10 @@ status_t WAVSource::read( return err; } + // make sure that maxBytesToRead is multiple of 3, in 24-bit case size_t maxBytesToRead = - mBitsPerSample == 8 ? kMaxFrameSize / 2 : kMaxFrameSize; + mBitsPerSample == 8 ? kMaxFrameSize / 2 : + (mBitsPerSample == 24 ? 3*(kMaxFrameSize/3): kMaxFrameSize); size_t maxBytesAvailable = (mCurrentPos - mOffset >= (off64_t)mSize) @@ -459,7 +461,7 @@ status_t WAVSource::read( buffer->set_range(0, n); - if (mWaveFormat == WAVE_FORMAT_PCM) { + if (mWaveFormat == WAVE_FORMAT_PCM || mWaveFormat == WAVE_FORMAT_EXTENSIBLE) { if (mBitsPerSample == 8) { // Convert 8-bit unsigned samples to 16-bit signed. diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp index a141752..b822868 100644 --- a/media/libstagefright/avc_utils.cpp +++ b/media/libstagefright/avc_utils.cpp @@ -22,6 +22,7 @@ #include <media/stagefright/foundation/ABitReader.h> #include <media/stagefright/foundation/ADebug.h> +#include <media/stagefright/foundation/hexdump.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaErrors.h> #include <media/stagefright/MetaData.h> @@ -41,7 +42,9 @@ unsigned parseUE(ABitReader *br) { // Determine video dimensions from the sequence parameterset. void FindAVCDimensions( - const sp<ABuffer> &seqParamSet, int32_t *width, int32_t *height) { + const sp<ABuffer> &seqParamSet, + int32_t *width, int32_t *height, + int32_t *sarWidth, int32_t *sarHeight) { ABitReader br(seqParamSet->data() + 1, seqParamSet->size() - 1); unsigned profile_idc = br.getBits(8); @@ -129,6 +132,48 @@ void FindAVCDimensions( *height -= (frame_crop_top_offset + frame_crop_bottom_offset) * cropUnitY; } + + if (sarWidth != NULL) { + *sarWidth = 0; + } + + if (sarHeight != NULL) { + *sarHeight = 0; + } + + if (br.getBits(1)) { // vui_parameters_present_flag + unsigned sar_width = 0, sar_height = 0; + + if (br.getBits(1)) { // aspect_ratio_info_present_flag + unsigned aspect_ratio_idc = br.getBits(8); + + if (aspect_ratio_idc == 255 /* extendedSAR */) { + sar_width = br.getBits(16); + sar_height = br.getBits(16); + } else if (aspect_ratio_idc > 0 && aspect_ratio_idc < 14) { + static const int32_t kFixedSARWidth[] = { + 1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160 + }; + + static const int32_t kFixedSARHeight[] = { + 1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99 + }; + + sar_width = kFixedSARWidth[aspect_ratio_idc - 1]; + sar_height = kFixedSARHeight[aspect_ratio_idc - 1]; + } + } + + ALOGV("sample aspect ratio = %u : %u", sar_width, sar_height); + + if (sarWidth != NULL) { + *sarWidth = sar_width; + } + + if (sarHeight != NULL) { + *sarHeight = sar_height; + } + } } status_t getNextNALUnit( @@ -254,7 +299,9 @@ sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit) { } int32_t width, height; - FindAVCDimensions(seqParamSet, &width, &height); + int32_t sarWidth, sarHeight; + FindAVCDimensions( + seqParamSet, &width, &height, &sarWidth, &sarHeight); size_t stopOffset; sp<ABuffer> picParamSet = FindNAL(data, size, 8, &stopOffset); @@ -301,8 +348,29 @@ sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit) { meta->setInt32(kKeyWidth, width); meta->setInt32(kKeyHeight, height); - ALOGI("found AVC codec config (%d x %d, %s-profile level %d.%d)", - width, height, AVCProfileToString(profile), level / 10, level % 10); + if (sarWidth > 1 || sarHeight > 1) { + // We treat 0:0 (unspecified) as 1:1. + + meta->setInt32(kKeySARWidth, sarWidth); + meta->setInt32(kKeySARHeight, sarHeight); + + ALOGI("found AVC codec config (%d x %d, %s-profile level %d.%d) " + "SAR %d : %d", + width, + height, + AVCProfileToString(profile), + level / 10, + level % 10, + sarWidth, + sarHeight); + } else { + ALOGI("found AVC codec config (%d x %d, %s-profile level %d.%d)", + width, + height, + AVCProfileToString(profile), + level / 10, + level % 10); + } return meta; } diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp index d88813e..a8ab2ac 100644 --- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp +++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp @@ -594,6 +594,11 @@ void SoftAAC2::onPortFlushCompleted(OMX_U32 portIndex) { } } +void SoftAAC2::onReset() { + aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1); + mIsFirst = true; +} + void SoftAAC2::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) { if (portIndex != 1) { return; diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.h b/media/libstagefright/codecs/aacdec/SoftAAC2.h index 0353196..6957ade 100644 --- a/media/libstagefright/codecs/aacdec/SoftAAC2.h +++ b/media/libstagefright/codecs/aacdec/SoftAAC2.h @@ -41,6 +41,7 @@ protected: virtual void onQueueFilled(OMX_U32 portIndex); virtual void onPortFlushCompleted(OMX_U32 portIndex); virtual void onPortEnableCompleted(OMX_U32 portIndex, bool enabled); + virtual void onReset(); private: enum { diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp index fb1135c..849be87 100644 --- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp +++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp @@ -343,6 +343,11 @@ void SoftMP3::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) { } } +void SoftMP3::onReset() { + pvmp3_InitDecoder(mConfig, mDecoderBuf); + mIsFirst = true; +} + } // namespace android android::SoftOMXComponent *createSoftOMXComponent( diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.h b/media/libstagefright/codecs/mp3dec/SoftMP3.h index 3a05466..4af91ea 100644 --- a/media/libstagefright/codecs/mp3dec/SoftMP3.h +++ b/media/libstagefright/codecs/mp3dec/SoftMP3.h @@ -42,6 +42,7 @@ protected: virtual void onQueueFilled(OMX_U32 portIndex); virtual void onPortFlushCompleted(OMX_U32 portIndex); virtual void onPortEnableCompleted(OMX_U32 portIndex, bool enabled); + virtual void onReset(); private: enum { diff --git a/media/libstagefright/codecs/on2/dec/Android.mk b/media/libstagefright/codecs/on2/dec/Android.mk index 3223871..0082d7c 100644 --- a/media/libstagefright/codecs/on2/dec/Android.mk +++ b/media/libstagefright/codecs/on2/dec/Android.mk @@ -5,9 +5,9 @@ LOCAL_SRC_FILES := \ SoftVPX.cpp LOCAL_C_INCLUDES := \ - $(TOP)/external/libvpx \ - $(TOP)/external/libvpx/vpx_codec \ - $(TOP)/external/libvpx/vpx_ports \ + $(TOP)/external/libvpx/libvpx \ + $(TOP)/external/libvpx/libvpx/vpx_codec \ + $(TOP)/external/libvpx/libvpx/vpx_ports \ frameworks/av/media/libstagefright/include \ frameworks/native/include/media/openmax \ @@ -21,4 +21,3 @@ LOCAL_MODULE := libstagefright_soft_vpxdec LOCAL_MODULE_TAGS := optional include $(BUILD_SHARED_LIBRARY) - diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp index ac88107..13dfc8c 100644 --- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp +++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp @@ -410,6 +410,11 @@ void SoftVorbis::onPortFlushCompleted(OMX_U32 portIndex) { } } +void SoftVorbis::onReset() { + mNumFramesOutput = 0; + vorbis_dsp_restart(mState); +} + void SoftVorbis::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) { if (portIndex != 1) { return; diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h index e252f55..cb628a0 100644 --- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h +++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h @@ -43,6 +43,7 @@ protected: virtual void onQueueFilled(OMX_U32 portIndex); virtual void onPortFlushCompleted(OMX_U32 portIndex); virtual void onPortEnableCompleted(OMX_U32 portIndex, bool enabled); + virtual void onReset(); private: enum { diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp index 2704a37..77f21b7 100644 --- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp +++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp @@ -24,7 +24,7 @@ #include <media/stagefright/MetaData.h> #include <system/window.h> #include <ui/GraphicBufferMapper.h> -#include <gui/ISurfaceTexture.h> +#include <gui/IGraphicBufferProducer.h> namespace android { diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp index 69274ca..22c2f5a 100644 --- a/media/libstagefright/id3/ID3.cpp +++ b/media/libstagefright/id3/ID3.cpp @@ -30,7 +30,7 @@ namespace android { static const size_t kMaxMetadataSize = 3 * 1024 * 1024; -ID3::ID3(const sp<DataSource> &source) +ID3::ID3(const sp<DataSource> &source, bool ignoreV1) : mIsValid(false), mData(NULL), mSize(0), @@ -38,7 +38,7 @@ ID3::ID3(const sp<DataSource> &source) mVersion(ID3_UNKNOWN) { mIsValid = parseV2(source); - if (!mIsValid) { + if (!mIsValid && !ignoreV1) { mIsValid = parseV1(source); } } diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h index 1422687..2306f31 100644 --- a/media/libstagefright/include/AwesomePlayer.h +++ b/media/libstagefright/include/AwesomePlayer.h @@ -36,7 +36,7 @@ struct MediaBuffer; struct MediaExtractor; struct MediaSource; struct NuCachedSource2; -struct ISurfaceTexture; +struct IGraphicBufferProducer; class DrmManagerClinet; class DecryptHandle; @@ -81,7 +81,7 @@ struct AwesomePlayer { bool isPlaying() const; - status_t setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture); + status_t setSurfaceTexture(const sp<IGraphicBufferProducer> &bufferProducer); void setAudioSink(const sp<MediaPlayerBase::AudioSink> &audioSink); status_t setLooping(bool shouldLoop); diff --git a/media/libstagefright/include/ID3.h b/media/libstagefright/include/ID3.h index 8714008..3028f56 100644 --- a/media/libstagefright/include/ID3.h +++ b/media/libstagefright/include/ID3.h @@ -35,7 +35,7 @@ struct ID3 { ID3_V2_4, }; - ID3(const sp<DataSource> &source); + ID3(const sp<DataSource> &source, bool ignoreV1 = false); ~ID3(); bool isValid() const; diff --git a/media/libstagefright/include/SimpleSoftOMXComponent.h b/media/libstagefright/include/SimpleSoftOMXComponent.h index 50cd275..f8c61eb 100644 --- a/media/libstagefright/include/SimpleSoftOMXComponent.h +++ b/media/libstagefright/include/SimpleSoftOMXComponent.h @@ -71,6 +71,7 @@ protected: virtual void onPortFlushCompleted(OMX_U32 portIndex); virtual void onPortEnableCompleted(OMX_U32 portIndex, bool enabled); + virtual void onReset(); PortInfo *editPortInfo(OMX_U32 portIndex); diff --git a/media/libstagefright/include/avc_utils.h b/media/libstagefright/include/avc_utils.h index e418822..d517320 100644 --- a/media/libstagefright/include/avc_utils.h +++ b/media/libstagefright/include/avc_utils.h @@ -36,8 +36,11 @@ enum { kAVCProfileCAVLC444Intra = 0x2c }; +// Optionally returns sample aspect ratio as well. void FindAVCDimensions( - const sp<ABuffer> &seqParamSet, int32_t *width, int32_t *height); + const sp<ABuffer> &seqParamSet, + int32_t *width, int32_t *height, + int32_t *sarWidth = NULL, int32_t *sarHeight = NULL); unsigned parseUE(ABitReader *br); diff --git a/media/libstagefright/matroska/Android.mk b/media/libstagefright/matroska/Android.mk index 2cccb4f..2d8c1e1 100644 --- a/media/libstagefright/matroska/Android.mk +++ b/media/libstagefright/matroska/Android.mk @@ -5,7 +5,7 @@ LOCAL_SRC_FILES:= \ MatroskaExtractor.cpp LOCAL_C_INCLUDES:= \ - $(TOP)/external/libvpx/mkvparser \ + $(TOP)/external/libvpx/libwebm \ $(TOP)/frameworks/native/include/media/openmax \ LOCAL_CFLAGS += -Wno-multichar diff --git a/media/libstagefright/mp4/FragmentedMP4Parser.cpp b/media/libstagefright/mp4/FragmentedMP4Parser.cpp index 54c3d63..0102656 100644 --- a/media/libstagefright/mp4/FragmentedMP4Parser.cpp +++ b/media/libstagefright/mp4/FragmentedMP4Parser.cpp @@ -18,6 +18,7 @@ #define LOG_TAG "FragmentedMP4Parser" #include <utils/Log.h> +#include "include/avc_utils.h" #include "include/ESDS.h" #include "include/FragmentedMP4Parser.h" #include "TrackFragment.h" @@ -132,6 +133,10 @@ struct FileSource : public FragmentedMP4Parser::Source { 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); @@ -319,8 +324,7 @@ status_t FragmentedMP4Parser::onSeekTo(bool wantAudio, int64_t position) { off_t totalOffset = mFirstMoofOffset; for (int i = 0; i < numSidxEntries; i++) { const SidxEntry *se = &info->mSidx[i]; - totalTime += se->mDurationUs; - if (totalTime > position) { + if (totalTime + se->mDurationUs > position) { mBuffer->setRange(0,0); mBufferPos = totalOffset; if (mFinalResult == ERROR_END_OF_STREAM) { @@ -329,9 +333,10 @@ status_t FragmentedMP4Parser::onSeekTo(bool wantAudio, int64_t position) { resumeIfNecessary(); } info->mFragments.clear(); - info->mDecodingTime = position * info->mMediaTimeScale / 1000000ll; + info->mDecodingTime = totalTime * info->mMediaTimeScale / 1000000ll; return OK; } + totalTime += se->mDurationUs; totalOffset += se->mSize; } } @@ -961,6 +966,10 @@ status_t FragmentedMP4Parser::makeAccessUnit( sample.mSize); (*accessUnit)->meta()->setInt64("timeUs", presentationTimeUs); + if (IsIDR(*accessUnit)) { + (*accessUnit)->meta()->setInt32("is-sync-frame", 1); + } + return OK; } @@ -1003,6 +1012,9 @@ status_t FragmentedMP4Parser::makeAccessUnit( "timeUs", presentationTimeUs); } } + if (IsIDR(*accessUnit)) { + (*accessUnit)->meta()->setInt32("is-sync-frame", 1); + } return OK; } diff --git a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp index c79e01f..4999663 100644 --- a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp +++ b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp @@ -450,6 +450,10 @@ void SimpleSoftOMXComponent::onChangeState(OMX_STATETYPE state) { checkTransitions(); } +void SimpleSoftOMXComponent::onReset() { + // no-op +} + void SimpleSoftOMXComponent::onPortEnable(OMX_U32 portIndex, bool enable) { CHECK_LT(portIndex, mPorts.size()); @@ -581,6 +585,10 @@ void SimpleSoftOMXComponent::checkTransitions() { if (transitionComplete) { mState = mTargetState; + if (mState == OMX_StateLoaded) { + onReset(); + } + notify(OMX_EventCmdComplete, OMX_CommandStateSet, mState, NULL); } } diff --git a/media/libstagefright/rtsp/AAMRAssembler.cpp b/media/libstagefright/rtsp/AAMRAssembler.cpp index fb8abc5..9e8725a 100644 --- a/media/libstagefright/rtsp/AAMRAssembler.cpp +++ b/media/libstagefright/rtsp/AAMRAssembler.cpp @@ -145,7 +145,6 @@ ARTPAssembler::AssemblyStatus AAMRAssembler::addPacket( unsigned payloadHeader = buffer->data()[0]; unsigned CMR = payloadHeader >> 4; - CHECK_EQ(payloadHeader & 0x0f, 0u); // RR Vector<uint8_t> tableOfContents; diff --git a/media/libstagefright/rtsp/AH263Assembler.cpp b/media/libstagefright/rtsp/AH263Assembler.cpp index d0313cc..75cd911 100644 --- a/media/libstagefright/rtsp/AH263Assembler.cpp +++ b/media/libstagefright/rtsp/AH263Assembler.cpp @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +//#define LOG_NDEBUG 0 +#define LOG_TAG "AH263Assembler" +#include <utils/Log.h> #include "AH263Assembler.h" @@ -100,11 +103,34 @@ ARTPAssembler::AssemblyStatus AH263Assembler::addPacket( } unsigned payloadHeader = U16_AT(buffer->data()); - CHECK_EQ(payloadHeader >> 11, 0u); // RR=0 unsigned P = (payloadHeader >> 10) & 1; unsigned V = (payloadHeader >> 9) & 1; unsigned PLEN = (payloadHeader >> 3) & 0x3f; - // unsigned PEBIT = payloadHeader & 7; + unsigned PEBIT = payloadHeader & 7; + + // V=0 + if (V != 0u) { + queue->erase(queue->begin()); + ++mNextExpectedSeqNo; + ALOGW("Packet discarded due to VRC (V != 0)"); + return MALFORMED_PACKET; + } + + // PLEN=0 + if (PLEN != 0u) { + queue->erase(queue->begin()); + ++mNextExpectedSeqNo; + ALOGW("Packet discarded (PLEN != 0)"); + return MALFORMED_PACKET; + } + + // PEBIT=0 + if (PEBIT != 0u) { + queue->erase(queue->begin()); + ++mNextExpectedSeqNo; + ALOGW("Packet discarded (PEBIT != 0)"); + return MALFORMED_PACKET; + } size_t skip = V + PLEN + (P ? 0 : 2); diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp index 539a888..161bd4f 100644 --- a/media/libstagefright/rtsp/ARTSPConnection.cpp +++ b/media/libstagefright/rtsp/ARTSPConnection.cpp @@ -830,6 +830,7 @@ status_t ARTSPConnection::findPendingRequest( if (i < 0) { // This is an unsolicited server->client message. + *index = -1; return OK; } diff --git a/media/libstagefright/tests/SurfaceMediaSource_test.cpp b/media/libstagefright/tests/SurfaceMediaSource_test.cpp index a61d6a2..6a98509 100644 --- a/media/libstagefright/tests/SurfaceMediaSource_test.cpp +++ b/media/libstagefright/tests/SurfaceMediaSource_test.cpp @@ -107,7 +107,7 @@ protected: window.get(), NULL); } else { ALOGV("No actual display. Choosing EGLSurface based on SurfaceMediaSource"); - sp<ISurfaceTexture> sms = (new SurfaceMediaSource( + sp<IGraphicBufferProducer> sms = (new SurfaceMediaSource( getSurfaceWidth(), getSurfaceHeight()))->getBufferQueue(); sp<SurfaceTextureClient> stc = new SurfaceTextureClient(sms); sp<ANativeWindow> window = stc; @@ -361,7 +361,7 @@ protected: mSMS = new SurfaceMediaSource(mYuvTexWidth, mYuvTexHeight); // Manual cast is required to avoid constructor ambiguity - mSTC = new SurfaceTextureClient(static_cast<sp<ISurfaceTexture> >( mSMS->getBufferQueue())); + mSTC = new SurfaceTextureClient(static_cast<sp<IGraphicBufferProducer> >( mSMS->getBufferQueue())); mANW = mSTC; } @@ -396,7 +396,7 @@ protected: ALOGV("SMS-GLTest::SetUp()"); android::ProcessState::self()->startThreadPool(); mSMS = new SurfaceMediaSource(mYuvTexWidth, mYuvTexHeight); - mSTC = new SurfaceTextureClient(static_cast<sp<ISurfaceTexture> >( mSMS->getBufferQueue())); + mSTC = new SurfaceTextureClient(static_cast<sp<IGraphicBufferProducer> >( mSMS->getBufferQueue())); mANW = mSTC; // Doing the setup related to the GL Side @@ -482,7 +482,7 @@ sp<MediaRecorder> SurfaceMediaSourceGLTest::setUpMediaRecorder(int fd, int video // query the mediarecorder for a surfacemeidasource and create an egl surface with that void SurfaceMediaSourceGLTest::setUpEGLSurfaceFromMediaRecorder(sp<MediaRecorder>& mr) { - sp<ISurfaceTexture> iST = mr->querySurfaceMediaSourceFromMediaServer(); + sp<IGraphicBufferProducer> iST = mr->querySurfaceMediaSourceFromMediaServer(); mSTC = new SurfaceTextureClient(iST); mANW = mSTC; @@ -749,7 +749,7 @@ TEST_F(SurfaceMediaSourceTest, DISABLED_EncodingFromCpuYV12BufferNpotWriteMediaS mYuvTexHeight, 30); // get the reference to the surfacemediasource living in // mediaserver that is created by stagefrightrecorder - sp<ISurfaceTexture> iST = mr->querySurfaceMediaSourceFromMediaServer(); + sp<IGraphicBufferProducer> iST = mr->querySurfaceMediaSourceFromMediaServer(); mSTC = new SurfaceTextureClient(iST); mANW = mSTC; ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU)); @@ -781,7 +781,7 @@ TEST_F(SurfaceMediaSourceGLTest, ChooseAndroidRecordableEGLConfigDummyWriter) { ALOGV("Verify creating a surface w/ right config + dummy writer*********"); mSMS = new SurfaceMediaSource(mYuvTexWidth, mYuvTexHeight); - mSTC = new SurfaceTextureClient(static_cast<sp<ISurfaceTexture> >( mSMS->getBufferQueue())); + mSTC = new SurfaceTextureClient(static_cast<sp<IGraphicBufferProducer> >( mSMS->getBufferQueue())); mANW = mSTC; DummyRecorder writer(mSMS); diff --git a/media/libstagefright/wifi-display/sink/RTPSink.cpp b/media/libstagefright/wifi-display/sink/RTPSink.cpp index 0918034..640e055 100644 --- a/media/libstagefright/wifi-display/sink/RTPSink.cpp +++ b/media/libstagefright/wifi-display/sink/RTPSink.cpp @@ -238,9 +238,9 @@ void RTPSink::Source::addReportBlock( RTPSink::RTPSink( const sp<ANetworkSession> &netSession, - const sp<ISurfaceTexture> &surfaceTex) + const sp<IGraphicBufferProducer> &bufferProducer) : mNetSession(netSession), - mSurfaceTex(surfaceTex), + mSurfaceTex(bufferProducer), mRTPPort(0), mRTPSessionID(0), mRTCPSessionID(0), diff --git a/media/libstagefright/wifi-display/sink/RTPSink.h b/media/libstagefright/wifi-display/sink/RTPSink.h index a1d127d..2183fd6 100644 --- a/media/libstagefright/wifi-display/sink/RTPSink.h +++ b/media/libstagefright/wifi-display/sink/RTPSink.h @@ -35,7 +35,7 @@ struct TunnelRenderer; // the RTCP channel. struct RTPSink : public AHandler { RTPSink(const sp<ANetworkSession> &netSession, - const sp<ISurfaceTexture> &surfaceTex); + const sp<IGraphicBufferProducer> &bufferProducer); // If TCP interleaving is used, no UDP sockets are created, instead // incoming RTP/RTCP packets (arriving on the RTSP control connection) @@ -66,7 +66,7 @@ private: struct StreamSource; sp<ANetworkSession> mNetSession; - sp<ISurfaceTexture> mSurfaceTex; + sp<IGraphicBufferProducer> mSurfaceTex; KeyedVector<uint32_t, sp<Source> > mSources; int32_t mRTPPort; diff --git a/media/libstagefright/wifi-display/sink/TunnelRenderer.cpp b/media/libstagefright/wifi-display/sink/TunnelRenderer.cpp index b913124..8ffb877 100644 --- a/media/libstagefright/wifi-display/sink/TunnelRenderer.cpp +++ b/media/libstagefright/wifi-display/sink/TunnelRenderer.cpp @@ -159,9 +159,9 @@ void TunnelRenderer::StreamSource::doSomeWork() { TunnelRenderer::TunnelRenderer( const sp<AMessage> ¬ifyLost, - const sp<ISurfaceTexture> &surfaceTex) + const sp<IGraphicBufferProducer> &bufferProducer) : mNotifyLost(notifyLost), - mSurfaceTex(surfaceTex), + mSurfaceTex(bufferProducer), mTotalBytesQueued(0ll), mLastDequeuedExtSeqNo(-1), mFirstFailedAttemptUs(-1ll), diff --git a/media/libstagefright/wifi-display/sink/TunnelRenderer.h b/media/libstagefright/wifi-display/sink/TunnelRenderer.h index c9597e0..52e6e66 100644 --- a/media/libstagefright/wifi-display/sink/TunnelRenderer.h +++ b/media/libstagefright/wifi-display/sink/TunnelRenderer.h @@ -36,7 +36,7 @@ struct IStreamListener; struct TunnelRenderer : public AHandler { TunnelRenderer( const sp<AMessage> ¬ifyLost, - const sp<ISurfaceTexture> &surfaceTex); + const sp<IGraphicBufferProducer> &bufferProducer); sp<ABuffer> dequeueBuffer(); @@ -55,7 +55,7 @@ private: mutable Mutex mLock; sp<AMessage> mNotifyLost; - sp<ISurfaceTexture> mSurfaceTex; + sp<IGraphicBufferProducer> mSurfaceTex; List<sp<ABuffer> > mPackets; int64_t mTotalBytesQueued; diff --git a/media/libstagefright/wifi-display/source/Converter.cpp b/media/libstagefright/wifi-display/source/Converter.cpp index 82c98b9..7a87444 100644 --- a/media/libstagefright/wifi-display/source/Converter.cpp +++ b/media/libstagefright/wifi-display/source/Converter.cpp @@ -161,7 +161,24 @@ status_t Converter::initEncoder() { mOutputFormat->setInt32("bitrate", videoBitrate); mOutputFormat->setInt32("bitrate-mode", OMX_Video_ControlRateConstant); mOutputFormat->setInt32("frame-rate", 30); - mOutputFormat->setInt32("i-frame-interval", 1); // Iframes every 1 secs + mOutputFormat->setInt32("i-frame-interval", 15); // Iframes every 15 secs + + // Configure encoder to use intra macroblock refresh mode + mOutputFormat->setInt32("intra-refresh-mode", OMX_VIDEO_IntraRefreshCyclic); + + int width, height, mbs; + if (!mOutputFormat->findInt32("width", &width) + || !mOutputFormat->findInt32("height", &height)) { + return ERROR_UNSUPPORTED; + } + + // Update macroblocks in a cyclic fashion with 10% of all MBs within + // frame gets updated at one time. It takes about 10 frames to + // completely update a whole video frame. If the frame rate is 30, + // it takes about 333 ms in the best case (if next frame is not an IDR) + // to recover from a lost/corrupted packet. + mbs = (((width + 15) / 16) * ((height + 15) / 16) * 10) / 100; + mOutputFormat->setInt32("intra-refresh-CIR-mbs", mbs); } ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str()); diff --git a/media/libstagefright/wifi-display/source/MediaPuller.cpp b/media/libstagefright/wifi-display/source/MediaPuller.cpp index ab69c4a..189bea3 100644 --- a/media/libstagefright/wifi-display/source/MediaPuller.cpp +++ b/media/libstagefright/wifi-display/source/MediaPuller.cpp @@ -34,7 +34,8 @@ MediaPuller::MediaPuller( : mSource(source), mNotify(notify), mPullGeneration(0), - mIsAudio(false) { + mIsAudio(false), + mPaused(false) { sp<MetaData> meta = source->getFormat(); const char *mime; CHECK(meta->findCString(kKeyMIMEType, &mime)); @@ -71,6 +72,14 @@ void MediaPuller::stopAsync(const sp<AMessage> ¬ify) { msg->post(); } +void MediaPuller::pause() { + (new AMessage(kWhatPause, id()))->post(); +} + +void MediaPuller::resume() { + (new AMessage(kWhatResume, id()))->post(); +} + void MediaPuller::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { case kWhatStart: @@ -95,7 +104,6 @@ void MediaPuller::onMessageReceived(const sp<AMessage> &msg) { uint32_t replyID; CHECK(msg->senderAwaitsResponse(&replyID)); - response->postReply(replyID); break; } @@ -130,6 +138,16 @@ void MediaPuller::onMessageReceived(const sp<AMessage> &msg) { MediaBuffer *mbuf; status_t err = mSource->read(&mbuf); + if (mPaused) { + if (err == OK) { + mbuf->release(); + mbuf = NULL; + } + + schedulePull(); + break; + } + if (err != OK) { if (err == ERROR_END_OF_STREAM) { ALOGI("stream ended."); @@ -176,6 +194,18 @@ void MediaPuller::onMessageReceived(const sp<AMessage> &msg) { break; } + case kWhatPause: + { + mPaused = true; + break; + } + + case kWhatResume: + { + mPaused = false; + break; + } + default: TRESPASS(); } diff --git a/media/libstagefright/wifi-display/source/MediaPuller.h b/media/libstagefright/wifi-display/source/MediaPuller.h index 728da7b..1291bb3 100644 --- a/media/libstagefright/wifi-display/source/MediaPuller.h +++ b/media/libstagefright/wifi-display/source/MediaPuller.h @@ -35,6 +35,9 @@ struct MediaPuller : public AHandler { status_t start(); void stopAsync(const sp<AMessage> ¬ify); + void pause(); + void resume(); + protected: virtual void onMessageReceived(const sp<AMessage> &msg); virtual ~MediaPuller(); @@ -44,12 +47,15 @@ private: kWhatStart, kWhatStop, kWhatPull, + kWhatPause, + kWhatResume, }; sp<MediaSource> mSource; sp<AMessage> mNotify; int32_t mPullGeneration; bool mIsAudio; + bool mPaused; status_t postSynchronouslyAndReturnError(const sp<AMessage> &msg); void schedulePull(); diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp index 4e5eb52..d6b87a7 100644 --- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp +++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp @@ -76,6 +76,9 @@ struct WifiDisplaySource::PlaybackSession::Track : public AHandler { status_t start(); void stopAsync(); + void pause(); + void resume(); + void queueAccessUnit(const sp<ABuffer> &accessUnit); sp<ABuffer> dequeueAccessUnit(); @@ -208,6 +211,14 @@ void WifiDisplaySource::PlaybackSession::Track::stopAsync() { } } +void WifiDisplaySource::PlaybackSession::Track::pause() { + mMediaPuller->pause(); +} + +void WifiDisplaySource::PlaybackSession::Track::resume() { + mMediaPuller->resume(); +} + void WifiDisplaySource::PlaybackSession::Track::onMessageReceived( const sp<AMessage> &msg) { switch (msg->what()) { @@ -325,6 +336,7 @@ WifiDisplaySource::PlaybackSession::PlaybackSession( mInterfaceAddr(interfaceAddr), mHDCP(hdcp), mWeAreDead(false), + mPaused(false), mLastLifesignUs(), mVideoTrackIndex(-1), mPrevTimeUs(-1ll), @@ -383,6 +395,8 @@ void WifiDisplaySource::PlaybackSession::updateLiveness() { status_t WifiDisplaySource::PlaybackSession::play() { updateLiveness(); + (new AMessage(kWhatResume, id()))->post(); + return OK; } @@ -413,6 +427,8 @@ status_t WifiDisplaySource::PlaybackSession::onFinishPlay2() { status_t WifiDisplaySource::PlaybackSession::pause() { updateLiveness(); + (new AMessage(kWhatPause, id()))->post(); + return OK; } @@ -590,6 +606,34 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived( break; } + case kWhatPause: + { + if (mPaused) { + break; + } + + for (size_t i = 0; i < mTracks.size(); ++i) { + mTracks.editValueAt(i)->pause(); + } + + mPaused = true; + break; + } + + case kWhatResume: + { + if (!mPaused) { + break; + } + + for (size_t i = 0; i < mTracks.size(); ++i) { + mTracks.editValueAt(i)->resume(); + } + + mPaused = false; + break; + } + default: TRESPASS(); } @@ -742,7 +786,7 @@ status_t WifiDisplaySource::PlaybackSession::addAudioSource(bool usePCMAudio) { return OK; } -sp<ISurfaceTexture> WifiDisplaySource::PlaybackSession::getSurfaceTexture() { +sp<IGraphicBufferProducer> WifiDisplaySource::PlaybackSession::getSurfaceTexture() { return mBufferQueue; } diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.h b/media/libstagefright/wifi-display/source/PlaybackSession.h index dabc1c4..281548d 100644 --- a/media/libstagefright/wifi-display/source/PlaybackSession.h +++ b/media/libstagefright/wifi-display/source/PlaybackSession.h @@ -26,7 +26,7 @@ namespace android { struct ABuffer; struct BufferQueue; struct IHDCP; -struct ISurfaceTexture; +struct IGraphicBufferProducer; struct MediaPuller; struct MediaSource; struct TSPacketizer; @@ -56,7 +56,7 @@ struct WifiDisplaySource::PlaybackSession : public AHandler { status_t finishPlay(); status_t pause(); - sp<ISurfaceTexture> getSurfaceTexture(); + sp<IGraphicBufferProducer> getSurfaceTexture(); int32_t width() const; int32_t height() const; @@ -84,6 +84,8 @@ private: kWhatUpdateSurface, kWhatFinishPlay, kWhatPacketize, + kWhatPause, + kWhatResume, }; sp<ANetworkSession> mNetSession; @@ -93,6 +95,7 @@ private: in_addr mInterfaceAddr; sp<IHDCP> mHDCP; bool mWeAreDead; + bool mPaused; int64_t mLastLifesignUs; diff --git a/media/libstagefright/wifi-display/source/Sender.h b/media/libstagefright/wifi-display/source/Sender.h index 73e3d19..66951f7 100644 --- a/media/libstagefright/wifi-display/source/Sender.h +++ b/media/libstagefright/wifi-display/source/Sender.h @@ -25,7 +25,7 @@ namespace android { #define LOG_TRANSPORT_STREAM 0 #define TRACK_BANDWIDTH 0 -#define ENABLE_RETRANSMISSION 0 +#define ENABLE_RETRANSMISSION 1 // If retransmission is enabled the following define determines what // kind we support, if RETRANSMISSION_ACCORDING_TO_RFC_XXXX is 0 diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp index 78d6e62..9ec1064 100644 --- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp +++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp @@ -25,7 +25,7 @@ #include "Sender.h" #include <binder/IServiceManager.h> -#include <gui/ISurfaceTexture.h> +#include <gui/IGraphicBufferProducer.h> #include <media/IHDCP.h> #include <media/IMediaPlayerService.h> #include <media/IRemoteDisplayClient.h> @@ -65,41 +65,50 @@ WifiDisplaySource::WifiDisplaySource( WifiDisplaySource::~WifiDisplaySource() { } -status_t WifiDisplaySource::start(const char *iface) { - CHECK_EQ(mState, INITIALIZED); - - sp<AMessage> msg = new AMessage(kWhatStart, id()); - msg->setString("iface", iface); - - sp<AMessage> response; - status_t err = msg->postAndAwaitResponse(&response); +static status_t PostAndAwaitResponse( + const sp<AMessage> &msg, sp<AMessage> *response) { + status_t err = msg->postAndAwaitResponse(response); if (err != OK) { return err; } - if (!response->findInt32("err", &err)) { + if (response == NULL || !(*response)->findInt32("err", &err)) { err = OK; } return err; } +status_t WifiDisplaySource::start(const char *iface) { + CHECK_EQ(mState, INITIALIZED); + + sp<AMessage> msg = new AMessage(kWhatStart, id()); + msg->setString("iface", iface); + + sp<AMessage> response; + return PostAndAwaitResponse(msg, &response); +} + status_t WifiDisplaySource::stop() { sp<AMessage> msg = new AMessage(kWhatStop, id()); sp<AMessage> response; - status_t err = msg->postAndAwaitResponse(&response); + return PostAndAwaitResponse(msg, &response); +} - if (err != OK) { - return err; - } +status_t WifiDisplaySource::pause() { + sp<AMessage> msg = new AMessage(kWhatPause, id()); - if (!response->findInt32("err", &err)) { - err = OK; - } + sp<AMessage> response; + return PostAndAwaitResponse(msg, &response); +} - return err; +status_t WifiDisplaySource::resume() { + sp<AMessage> msg = new AMessage(kWhatResume, id()); + + sp<AMessage> response; + return PostAndAwaitResponse(msg, &response); } void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) { @@ -236,6 +245,20 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) { mClient->onDisplayError( IRemoteDisplayClient::kDisplayErrorUnknown); } + +#if 0 + // testing only. + char val[PROPERTY_VALUE_MAX]; + if (property_get("media.wfd.trigger", val, NULL)) { + if (!strcasecmp(val, "pause") && mState == PLAYING) { + mState = PLAYING_TO_PAUSED; + sendTrigger(mClientSessionID, TRIGGER_PAUSE); + } else if (!strcasecmp(val, "play") && mState == PAUSED) { + mState = PAUSED_TO_PLAYING; + sendTrigger(mClientSessionID, TRIGGER_PLAY); + } + } +#endif break; } @@ -254,8 +277,8 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) { if (mState >= AWAITING_CLIENT_PLAY) { // We have a session, i.e. a previous SETUP succeeded. - status_t err = sendM5( - mClientSessionID, true /* requestShutdown */); + status_t err = sendTrigger( + mClientSessionID, TRIGGER_TEARDOWN); if (err == OK) { mState = AWAITING_CLIENT_TEARDOWN; @@ -273,6 +296,46 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) { break; } + case kWhatPause: + { + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + status_t err = OK; + + if (mState != PLAYING) { + err = INVALID_OPERATION; + } else { + mState = PLAYING_TO_PAUSED; + sendTrigger(mClientSessionID, TRIGGER_PAUSE); + } + + sp<AMessage> response = new AMessage; + response->setInt32("err", err); + response->postReply(replyID); + break; + } + + case kWhatResume: + { + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + status_t err = OK; + + if (mState != PAUSED) { + err = INVALID_OPERATION; + } else { + mState = PAUSED_TO_PLAYING; + sendTrigger(mClientSessionID, TRIGGER_PLAY); + } + + sp<AMessage> response = new AMessage; + response->setInt32("err", err); + response->postReply(replyID); + break; + } + case kWhatReapDeadClients: { mReaperPending = false; @@ -400,7 +463,7 @@ void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) { if (mSetupTriggerDeferred) { mSetupTriggerDeferred = false; - sendM5(mClientSessionID, false /* requestShutdown */); + sendTrigger(mClientSessionID, TRIGGER_SETUP); } break; } @@ -574,13 +637,25 @@ status_t WifiDisplaySource::sendM4(int32_t sessionID) { return OK; } -status_t WifiDisplaySource::sendM5(int32_t sessionID, bool requestShutdown) { +status_t WifiDisplaySource::sendTrigger( + int32_t sessionID, TriggerType triggerType) { AString body = "wfd_trigger_method: "; - if (requestShutdown) { - ALOGI("Sending TEARDOWN trigger."); - body.append("TEARDOWN"); - } else { - body.append("SETUP"); + switch (triggerType) { + case TRIGGER_SETUP: + body.append("SETUP"); + break; + case TRIGGER_TEARDOWN: + ALOGI("Sending TEARDOWN trigger."); + body.append("TEARDOWN"); + break; + case TRIGGER_PAUSE: + body.append("PAUSE"); + break; + case TRIGGER_PLAY: + body.append("PLAY"); + break; + default: + TRESPASS(); } body.append("\r\n"); @@ -807,7 +882,7 @@ status_t WifiDisplaySource::onReceiveM4Response( return OK; } - return sendM5(sessionID, false /* requestShutdown */); + return sendTrigger(sessionID, TRIGGER_SETUP); } status_t WifiDisplaySource::onReceiveM5Response( @@ -1184,6 +1259,11 @@ status_t WifiDisplaySource::onPlayRequest( return err; } + if (mState == PAUSED_TO_PLAYING) { + mState = PLAYING; + return OK; + } + playbackSession->finishPlay(); CHECK_EQ(mState, AWAITING_CLIENT_PLAY); @@ -1205,6 +1285,12 @@ status_t WifiDisplaySource::onPauseRequest( return ERROR_MALFORMED; } + ALOGI("Received PAUSE request."); + + if (mState != PLAYING_TO_PAUSED) { + return INVALID_OPERATION; + } + status_t err = playbackSession->pause(); CHECK_EQ(err, (status_t)OK); @@ -1214,6 +1300,12 @@ status_t WifiDisplaySource::onPauseRequest( err = mNetSession->sendRequest(sessionID, response.c_str()); + if (err != OK) { + return err; + } + + mState = PAUSED; + return err; } diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.h b/media/libstagefright/wifi-display/source/WifiDisplaySource.h index 1e855e7..974e070 100644 --- a/media/libstagefright/wifi-display/source/WifiDisplaySource.h +++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.h @@ -44,6 +44,9 @@ struct WifiDisplaySource : public AHandler { status_t start(const char *iface); status_t stop(); + status_t pause(); + status_t resume(); + protected: virtual ~WifiDisplaySource(); virtual void onMessageReceived(const sp<AMessage> &msg); @@ -59,6 +62,9 @@ private: AWAITING_CLIENT_PLAY, ABOUT_TO_PLAY, PLAYING, + PLAYING_TO_PAUSED, + PAUSED, + PAUSED_TO_PLAYING, AWAITING_CLIENT_TEARDOWN, STOPPING, STOPPED, @@ -68,6 +74,8 @@ private: kWhatStart, kWhatRTSPNotify, kWhatStop, + kWhatPause, + kWhatResume, kWhatReapDeadClients, kWhatPlaybackSessionNotify, kWhatKeepAlive, @@ -147,7 +155,17 @@ private: status_t sendM1(int32_t sessionID); status_t sendM3(int32_t sessionID); status_t sendM4(int32_t sessionID); - status_t sendM5(int32_t sessionID, bool requestShutdown); + + enum TriggerType { + TRIGGER_SETUP, + TRIGGER_TEARDOWN, + TRIGGER_PAUSE, + TRIGGER_PLAY, + }; + + // M5 + status_t sendTrigger(int32_t sessionID, TriggerType triggerType); + status_t sendM16(int32_t sessionID); status_t onReceiveM1Response( diff --git a/media/libstagefright/wifi-display/wfd.cpp b/media/libstagefright/wifi-display/wfd.cpp index 03a1123..2ec9b4f 100644 --- a/media/libstagefright/wifi-display/wfd.cpp +++ b/media/libstagefright/wifi-display/wfd.cpp @@ -47,7 +47,7 @@ struct RemoteDisplayClient : public BnRemoteDisplayClient { RemoteDisplayClient(); virtual void onDisplayConnected( - const sp<ISurfaceTexture> &surfaceTexture, + const sp<IGraphicBufferProducer> &bufferProducer, uint32_t width, uint32_t height, uint32_t flags); @@ -67,7 +67,7 @@ private: bool mDone; sp<SurfaceComposerClient> mComposerClient; - sp<ISurfaceTexture> mSurfaceTexture; + sp<IGraphicBufferProducer> mSurfaceTexture; sp<IBinder> mDisplayBinder; DISALLOW_EVIL_CONSTRUCTORS(RemoteDisplayClient); @@ -83,14 +83,14 @@ RemoteDisplayClient::~RemoteDisplayClient() { } void RemoteDisplayClient::onDisplayConnected( - const sp<ISurfaceTexture> &surfaceTexture, + const sp<IGraphicBufferProducer> &bufferProducer, uint32_t width, uint32_t height, uint32_t flags) { ALOGI("onDisplayConnected width=%u, height=%u, flags = 0x%08x", width, height, flags); - mSurfaceTexture = surfaceTexture; + mSurfaceTexture = bufferProducer; mDisplayBinder = mComposerClient->createDisplay( String8("foo"), false /* secure */); diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk index c4050b8..6d42143 100644 --- a/services/audioflinger/Android.mk +++ b/services/audioflinger/Android.mk @@ -66,9 +66,6 @@ LOCAL_CFLAGS += -DSTATE_QUEUE_INSTANTIATIONS='"StateQueueInstantiations.cpp"' LOCAL_CFLAGS += -UFAST_TRACKS_AT_NON_NATIVE_SAMPLE_RATE -# uncomment for systrace -# LOCAL_CFLAGS += -DATRACE_TAG=ATRACE_TAG_AUDIO - # uncomment for dumpsys to write most recent audio output to .wav file # 47.5 seconds at 44.1 kHz, 8 megabytes # LOCAL_CFLAGS += -DTEE_SINK_FRAMES=0x200000 @@ -81,6 +78,13 @@ LOCAL_CFLAGS += -UFAST_TRACKS_AT_NON_NATIVE_SAMPLE_RATE # LOCAL_SRC_FILES += AudioWatchdog.cpp # LOCAL_CFLAGS += -DAUDIO_WATCHDOG +# Define ANDROID_SMP appropriately. Used to get inline tracing fast-path. +ifeq ($(TARGET_CPU_SMP),true) + LOCAL_CFLAGS += -DANDROID_SMP=1 +else + LOCAL_CFLAGS += -DANDROID_SMP=0 +endif + include $(BUILD_SHARED_LIBRARY) # diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index 46a8e0f..6d3f0a1 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -385,7 +385,6 @@ private: virtual status_t start(); virtual void stop(); virtual void flush(); - virtual void mute(bool); virtual void pause(); virtual status_t attachAuxEffect(int effectId); virtual status_t allocateTimedBuffer(size_t size, diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp index b3ca877..08325ad 100644 --- a/services/audioflinger/AudioMixer.cpp +++ b/services/audioflinger/AudioMixer.cpp @@ -1109,6 +1109,12 @@ void AudioMixer::process__genericNoResampling(state_t* state, int64_t pts) e0 &= ~(1<<i); track_t& t = state->tracks[i]; t.buffer.frameCount = state->frameCount; + int valid = t.bufferProvider->getValid(); + if (valid != AudioBufferProvider::kValid) { + ALOGE("invalid bufferProvider=%p name=%d frameCount=%d valid=%#x enabledTracks=%#x", + t.bufferProvider, i, t.buffer.frameCount, valid, enabledTracks); + // expect to crash + } t.bufferProvider->getNextBuffer(&t.buffer, pts); t.frameCount = t.buffer.frameCount; t.in = t.buffer.raw; diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp index 2005899..9283f53 100644 --- a/services/audioflinger/FastMixer.cpp +++ b/services/audioflinger/FastMixer.cpp @@ -23,6 +23,8 @@ #define LOG_TAG "FastMixer" //#define LOG_NDEBUG 0 +#define ATRACE_TAG ATRACE_TAG_AUDIO + #include <sys/atomics.h> #include <time.h> #include <utils/Log.h> @@ -377,14 +379,14 @@ bool FastMixer::threadLoop() // up to 1 ms. If enough active tracks all blocked in sequence, this would result // in the overall fast mix cycle being delayed. Should use a non-blocking FIFO. size_t framesReady = fastTrack->mBufferProvider->framesReady(); -#if defined(ATRACE_TAG) && (ATRACE_TAG != ATRACE_TAG_NEVER) - // I wish we had formatted trace names - char traceName[16]; - strcpy(traceName, "framesReady"); - traceName[11] = i + (i < 10 ? '0' : 'A' - 10); - traceName[12] = '\0'; - ATRACE_INT(traceName, framesReady); -#endif + if (ATRACE_ENABLED()) { + // I wish we had formatted trace names + char traceName[16]; + strcpy(traceName, "framesReady"); + traceName[11] = i + (i < 10 ? '0' : 'A' - 10); + traceName[12] = '\0'; + ATRACE_INT(traceName, framesReady); + } FastTrackDump *ftDump = &dumpState->mTracks[i]; FastTrackUnderruns underruns = ftDump->mUnderruns; if (framesReady < frameCount) { @@ -430,13 +432,9 @@ bool FastMixer::threadLoop() // FIXME write() is non-blocking and lock-free for a properly implemented NBAIO sink, // but this code should be modified to handle both non-blocking and blocking sinks dumpState->mWriteSequence++; -#if defined(ATRACE_TAG) && (ATRACE_TAG != ATRACE_TAG_NEVER) - Tracer::traceBegin(ATRACE_TAG, "write"); -#endif + ATRACE_BEGIN("write"); ssize_t framesWritten = outputSink->write(mixBuffer, frameCount); -#if defined(ATRACE_TAG) && (ATRACE_TAG != ATRACE_TAG_NEVER) - Tracer::traceEnd(ATRACE_TAG); -#endif + ATRACE_END(); dumpState->mWriteSequence++; if (framesWritten >= 0) { ALOG_ASSERT(framesWritten <= frameCount); @@ -491,9 +489,7 @@ bool FastMixer::threadLoop() sleepNs = -1; if (isWarm) { if (sec > 0 || nsec > underrunNs) { -#if defined(ATRACE_TAG) && (ATRACE_TAG != ATRACE_TAG_NEVER) - ScopedTrace st(ATRACE_TAG, "underrun"); -#endif + ATRACE_NAME("underrun"); // FIXME only log occasionally ALOGV("underrun: time since last cycle %d.%03ld sec", (int) sec, nsec / 1000000L); @@ -573,10 +569,8 @@ bool FastMixer::threadLoop() // this store #4 is not atomic with respect to stores #1, #2, #3 above, but // the newest open and oldest closed halves are atomic with respect to each other dumpState->mBounds = bounds; -#if defined(ATRACE_TAG) && (ATRACE_TAG != ATRACE_TAG_NEVER) ATRACE_INT("cycle_ms", monotonicNs / 1000000); ATRACE_INT("load_us", loadNs / 1000); -#endif } #endif } else { diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h index b898924..aaa5333 100644 --- a/services/audioflinger/PlaybackTracks.h +++ b/services/audioflinger/PlaybackTracks.h @@ -44,7 +44,6 @@ public: void flush(); void destroy(); - void mute(bool); int name() const { return mName; } audio_stream_type_t streamType() const { @@ -78,7 +77,6 @@ protected: virtual size_t framesReady() const; - bool isMuted() const { return mMute; } bool isPausing() const { return mState == PAUSING; } @@ -105,17 +103,14 @@ protected: public: void triggerEvents(AudioSystem::sync_event_t type); + void invalidate(); + bool isInvalid() const { return mIsInvalid; } virtual bool isTimedTrack() const { return false; } bool isFastTrack() const { return (mFlags & IAudioFlinger::TRACK_FAST) != 0; } virtual bool isOut() const; protected: - // written by Track::mute() called by binder thread(s), without a mutex or barrier. - // read by Track::isMuted() called by playback thread, also without a mutex or barrier. - // The lack of mutex or barrier is safe because the mute status is only used by itself. - bool mMute; - // FILLED state is used for suppressing volume ramp at begin of playing enum {FS_INVALID, FS_FILLING, FS_FILLED, FS_ACTIVE}; mutable uint8_t mFillingUpStatus; @@ -150,6 +145,7 @@ private: volatile float mCachedVolume; // combined master volume and stream type volume; // 'volatile' means accessed without lock or // barrier, but is read/written atomically + bool mIsInvalid; // non-resettable latch, set by invalidate() }; // end of Track class TimedTrack : public Track { diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 1ceb850..d2b2931 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -18,6 +18,7 @@ #define LOG_TAG "AudioFlinger" //#define LOG_NDEBUG 0 +#define ATRACE_TAG ATRACE_TAG_AUDIO #include <math.h> #include <fcntl.h> @@ -25,6 +26,7 @@ #include <cutils/properties.h> #include <cutils/compiler.h> #include <utils/Log.h> +#include <utils/Trace.h> #include <private/media/AudioTrackShared.h> #include <hardware/audio.h> @@ -1522,8 +1524,7 @@ uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId) const for (size_t i = 0; i < mTracks.size(); ++i) { sp<Track> track = mTracks[i]; - if (sessionId == track->sessionId() && - !(track->mCblk->flags & CBLK_INVALID)) { + if (sessionId == track->sessionId() && !track->isInvalid()) { result |= TRACK_SESSION; break; } @@ -1541,8 +1542,7 @@ uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId) } for (size_t i = 0; i < mTracks.size(); i++) { sp<Track> track = mTracks[i]; - if (sessionId == track->sessionId() && - !(track->mCblk->flags & CBLK_INVALID)) { + if (sessionId == track->sessionId() && !track->isInvalid()) { return AudioSystem::getStrategyForStream(track->streamType()); } } @@ -1652,9 +1652,7 @@ void AudioFlinger::PlaybackThread::threadLoop_write() if (mNormalSink != 0) { #define mBitShift 2 // FIXME size_t count = mixBufferSize >> mBitShift; -#if defined(ATRACE_TAG) && (ATRACE_TAG != ATRACE_TAG_NEVER) - Tracer::traceBegin(ATRACE_TAG, "write"); -#endif + ATRACE_BEGIN("write"); // update the setpoint when AudioFlinger::mScreenState changes uint32_t screenState = AudioFlinger::mScreenState; if (screenState != mScreenState) { @@ -1666,9 +1664,7 @@ void AudioFlinger::PlaybackThread::threadLoop_write() } } ssize_t framesWritten = mNormalSink->write(mMixBuffer, count); -#if defined(ATRACE_TAG) && (ATRACE_TAG != ATRACE_TAG_NEVER) - Tracer::traceEnd(ATRACE_TAG); -#endif + ATRACE_END(); if (framesWritten > 0) { bytesWritten = framesWritten << mBitShift; } else { @@ -1723,8 +1719,7 @@ void AudioFlinger::PlaybackThread::invalidateTracks(audio_stream_type_t streamTy for (size_t i = 0; i < size; i++) { sp<Track> t = mTracks[i]; if (t->streamType() == streamType) { - android_atomic_or(CBLK_INVALID, &t->mCblk->flags); - t->mCblk->cv.signal(); + t->invalidate(); } } } @@ -2000,9 +1995,7 @@ if (mType == MIXER) { if (!mStandby && delta > maxPeriod) { mNumDelayedWrites++; if ((now - lastWarning) > kWarningThrottleNs) { -#if defined(ATRACE_TAG) && (ATRACE_TAG != ATRACE_TAG_NEVER) - ScopedTrace st(ATRACE_TAG, "underrun"); -#endif + ATRACE_NAME("underrun"); ALOGW("write blocked for %llu msecs, %d delayed writes, thread %p", ns2ms(delta), mNumDelayedWrites, this); lastWarning = now; @@ -2548,8 +2541,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac } // cache the combined master volume and stream type volume for fast mixer; this // lacks any synchronization or barrier so VolumeProvider may read a stale value - track->mCachedVolume = track->isMuted() ? - 0 : masterVolume * mStreamTypes[track->streamType()].volume; + track->mCachedVolume = masterVolume * mStreamTypes[track->streamType()].volume; ++fastTracks; } else { // was it previously active? @@ -2641,8 +2633,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac // compute volume for this track uint32_t vl, vr, va; - if (track->isMuted() || track->isPausing() || - mStreamTypes[track->streamType()].mute) { + if (track->isPausing() || mStreamTypes[track->streamType()].mute) { vl = vr = va = 0; if (track->isPausing()) { track->setPaused(); @@ -3143,8 +3134,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep // compute volume for this track float left, right; - if (track->isMuted() || mMasterMute || track->isPausing() || - mStreamTypes[track->streamType()].mute) { + if (mMasterMute || track->isPausing() || mStreamTypes[track->streamType()].mute) { left = right = 0; if (track->isPausing()) { track->setPaused(); diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index 2c6ba8b..9b611d2 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -248,10 +248,6 @@ void AudioFlinger::TrackHandle::flush() { mTrack->flush(); } -void AudioFlinger::TrackHandle::mute(bool e) { - mTrack->mute(e); -} - void AudioFlinger::TrackHandle::pause() { mTrack->pause(); } @@ -315,7 +311,6 @@ AudioFlinger::PlaybackThread::Track::Track( IAudioFlinger::track_flags_t flags) : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer, sessionId), - mMute(false), mFillingUpStatus(FS_INVALID), // mRetryCount initialized later when needed mSharedBuffer(sharedBuffer), @@ -328,7 +323,8 @@ AudioFlinger::PlaybackThread::Track::Track( mFlags(flags), mFastIndex(-1), mUnderrunCount(0), - mCachedVolume(1.0) + mCachedVolume(1.0), + mIsInvalid(false) { if (mCblk != NULL) { // to avoid leaking a track name, do not allocate one unless there is an mCblk @@ -397,7 +393,7 @@ void AudioFlinger::PlaybackThread::Track::destroy() /*static*/ void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result) { - result.append(" Name Client Type Fmt Chn mask Session StpCnt fCount S M F SRate " + result.append(" Name Client Type Fmt Chn mask Session StpCnt fCount S F SRate " "L dB R dB Server User Main buf Aux Buf Flags Underruns\n"); } @@ -461,7 +457,7 @@ void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size) nowInUnderrun = '?'; break; } - snprintf(&buffer[7], size-7, " %6d %4u %3u 0x%08x %7u %6u %6u %1c %1d %1d %5u %5.2g %5.2g " + snprintf(&buffer[7], size-7, " %6d %4u %3u 0x%08x %7u %6u %6u %1c %1d %5u %5.2g %5.2g " "0x%08x 0x%08x 0x%08x 0x%08x %#5x %9u%c\n", (mClient == 0) ? getpid_cached : mClient->pid(), mStreamType, @@ -471,7 +467,6 @@ void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size) mStepCount, mFrameCount, stateChar, - mMute, mFillingUpStatus, mCblk->sampleRate, 20.0 * log10((vlr & 0xFFFF) / 4096.0), @@ -708,11 +703,6 @@ void AudioFlinger::PlaybackThread::Track::reset() } } -void AudioFlinger::PlaybackThread::Track::mute(bool muted) -{ - mMute = muted; -} - status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId) { status_t status = DEAD_OBJECT; @@ -845,6 +835,14 @@ bool AudioFlinger::PlaybackThread::Track::isOut() const return true; } +void AudioFlinger::PlaybackThread::Track::invalidate() +{ + // FIXME should use proxy + android_atomic_or(CBLK_INVALID, &mCblk->flags); + mCblk->cv.signal(); + mIsInvalid = true; +} + // ---------------------------------------------------------------------------- sp<AudioFlinger::PlaybackThread::TimedTrack> diff --git a/services/audioflinger/audio-resampler/AudioResamplerCoefficients.cpp b/services/audioflinger/audio-resampler/AudioResamplerCoefficients.cpp index af3e40d..d45d697 100644 --- a/services/audioflinger/audio-resampler/AudioResamplerCoefficients.cpp +++ b/services/audioflinger/audio-resampler/AudioResamplerCoefficients.cpp @@ -15,7 +15,7 @@ */ #define LOG_TAG "ResamplerCoefficients" -#define LOG_NDEBUG 0 +//#define LOG_NDEBUG 0 #include <utils/Log.h> diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp index 5a7bb48..70bf0ac 100644 --- a/services/camera/libcameraservice/Camera2Client.cpp +++ b/services/camera/libcameraservice/Camera2Client.cpp @@ -183,37 +183,37 @@ status_t Camera2Client::dump(int fd, const Vector<String16>& args) { result.append(" White balance mode: "); switch (p.wbMode) { - CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_AUTO) - CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_INCANDESCENT) - CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_FLUORESCENT) - CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_WARM_FLUORESCENT) - CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_DAYLIGHT) - CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_CLOUDY_DAYLIGHT) - CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_TWILIGHT) - CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_SHADE) + CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_MODE_AUTO) + CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_MODE_INCANDESCENT) + CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_MODE_FLUORESCENT) + CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_MODE_WARM_FLUORESCENT) + CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_MODE_DAYLIGHT) + CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_MODE_CLOUDY_DAYLIGHT) + CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_MODE_TWILIGHT) + CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_MODE_SHADE) default: result.append("UNKNOWN\n"); } result.append(" Effect mode: "); switch (p.effectMode) { - CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_OFF) - CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_MONO) - CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_NEGATIVE) - CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_SOLARIZE) - CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_SEPIA) - CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_POSTERIZE) - CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_WHITEBOARD) - CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_BLACKBOARD) - CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_AQUA) + CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_MODE_OFF) + CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_MODE_MONO) + CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_MODE_NEGATIVE) + CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_MODE_SOLARIZE) + CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_MODE_SEPIA) + CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_MODE_POSTERIZE) + CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_MODE_WHITEBOARD) + CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_MODE_BLACKBOARD) + CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_MODE_AQUA) default: result.append("UNKNOWN\n"); } result.append(" Antibanding mode: "); switch (p.antibandingMode) { - CASE_APPEND_ENUM(ANDROID_CONTROL_AE_ANTIBANDING_AUTO) - CASE_APPEND_ENUM(ANDROID_CONTROL_AE_ANTIBANDING_OFF) - CASE_APPEND_ENUM(ANDROID_CONTROL_AE_ANTIBANDING_50HZ) - CASE_APPEND_ENUM(ANDROID_CONTROL_AE_ANTIBANDING_60HZ) + CASE_APPEND_ENUM(ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO) + CASE_APPEND_ENUM(ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF) + CASE_APPEND_ENUM(ANDROID_CONTROL_AE_ANTIBANDING_MODE_50HZ) + CASE_APPEND_ENUM(ANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ) default: result.append("UNKNOWN\n"); } @@ -497,7 +497,7 @@ status_t Camera2Client::setPreviewDisplay( } status_t Camera2Client::setPreviewTexture( - const sp<ISurfaceTexture>& surfaceTexture) { + const sp<IGraphicBufferProducer>& bufferProducer) { ATRACE_CALL(); ALOGV("%s: E", __FUNCTION__); Mutex::Autolock icl(mICameraLock); @@ -506,9 +506,9 @@ status_t Camera2Client::setPreviewTexture( sp<IBinder> binder; sp<ANativeWindow> window; - if (surfaceTexture != 0) { - binder = surfaceTexture->asBinder(); - window = new SurfaceTextureClient(surfaceTexture); + if (bufferProducer != 0) { + binder = bufferProducer->asBinder(); + window = new SurfaceTextureClient(bufferProducer); } return setPreviewWindowL(binder, window); } @@ -1260,7 +1260,7 @@ status_t Camera2Client::commandStartFaceDetectionL(int /*type*/) { } // Ignoring type if (l.mParameters.fastInfo.bestFaceDetectMode == - ANDROID_STATS_FACE_DETECTION_OFF) { + ANDROID_STATISTICS_FACE_DETECT_MODE_OFF) { ALOGE("%s: Camera %d: Face detection not supported", __FUNCTION__, mCameraId); return INVALID_OPERATION; diff --git a/services/camera/libcameraservice/Camera2Client.h b/services/camera/libcameraservice/Camera2Client.h index 55ead02..4669958 100644 --- a/services/camera/libcameraservice/Camera2Client.h +++ b/services/camera/libcameraservice/Camera2Client.h @@ -49,7 +49,7 @@ public: virtual status_t unlock(); virtual status_t setPreviewDisplay(const sp<Surface>& surface); virtual status_t setPreviewTexture( - const sp<ISurfaceTexture>& surfaceTexture); + const sp<IGraphicBufferProducer>& bufferProducer); virtual void setPreviewCallbackFlag(int flag); virtual status_t startPreview(); virtual void stopPreview(); diff --git a/services/camera/libcameraservice/CameraClient.cpp b/services/camera/libcameraservice/CameraClient.cpp index 006a9c9..f9cee0d 100644 --- a/services/camera/libcameraservice/CameraClient.cpp +++ b/services/camera/libcameraservice/CameraClient.cpp @@ -307,17 +307,17 @@ status_t CameraClient::setPreviewDisplay(const sp<Surface>& surface) { return setPreviewWindow(binder, window); } -// set the SurfaceTexture that the preview will use +// set the SurfaceTextureClient that the preview will use status_t CameraClient::setPreviewTexture( - const sp<ISurfaceTexture>& surfaceTexture) { - LOG1("setPreviewTexture(%p) (pid %d)", surfaceTexture.get(), + const sp<IGraphicBufferProducer>& bufferProducer) { + LOG1("setPreviewTexture(%p) (pid %d)", bufferProducer.get(), getCallingPid()); sp<IBinder> binder; sp<ANativeWindow> window; - if (surfaceTexture != 0) { - binder = surfaceTexture->asBinder(); - window = new SurfaceTextureClient(surfaceTexture); + if (bufferProducer != 0) { + binder = bufferProducer->asBinder(); + window = new SurfaceTextureClient(bufferProducer); } return setPreviewWindow(binder, window); } diff --git a/services/camera/libcameraservice/CameraClient.h b/services/camera/libcameraservice/CameraClient.h index 2f31c4e..7da3da7 100644 --- a/services/camera/libcameraservice/CameraClient.h +++ b/services/camera/libcameraservice/CameraClient.h @@ -33,7 +33,7 @@ public: virtual status_t lock(); virtual status_t unlock(); virtual status_t setPreviewDisplay(const sp<Surface>& surface); - virtual status_t setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture); + virtual status_t setPreviewTexture(const sp<IGraphicBufferProducer>& bufferProducer); virtual void setPreviewCallbackFlag(int flag); virtual status_t startPreview(); virtual void stopPreview(); @@ -124,7 +124,7 @@ private: // Ensures atomicity among the public methods mutable Mutex mLock; - // This is a binder of Surface or SurfaceTexture. + // This is a binder of Surface or SurfaceTextureClient. sp<IBinder> mSurface; sp<ANativeWindow> mPreviewWindow; diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index 4dab340..41365a0 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -81,7 +81,7 @@ public: virtual status_t lock() = 0; virtual status_t unlock() = 0; virtual status_t setPreviewDisplay(const sp<Surface>& surface) = 0; - virtual status_t setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture) = 0; + virtual status_t setPreviewTexture(const sp<IGraphicBufferProducer>& bufferProducer)=0; virtual void setPreviewCallbackFlag(int flag) = 0; virtual status_t startPreview() = 0; virtual void stopPreview() = 0; diff --git a/services/camera/libcameraservice/camera2/FrameProcessor.cpp b/services/camera/libcameraservice/camera2/FrameProcessor.cpp index e032522..8ee5de7 100644 --- a/services/camera/libcameraservice/camera2/FrameProcessor.cpp +++ b/services/camera/libcameraservice/camera2/FrameProcessor.cpp @@ -177,7 +177,7 @@ status_t FrameProcessor::processFaceDetect(const CameraMetadata &frame, SharedParameters::Lock l(client->getParameters()); enableFaceDetect = l.mParameters.enableFaceDetect; } - entry = frame.find(ANDROID_STATS_FACE_DETECT_MODE); + entry = frame.find(ANDROID_STATISTICS_FACE_DETECT_MODE); // TODO: This should be an error once implementations are compliant if (entry.count == 0) { @@ -190,9 +190,9 @@ status_t FrameProcessor::processFaceDetect(const CameraMetadata &frame, Vector<camera_face_t> faces; metadata.number_of_faces = 0; - if (enableFaceDetect && faceDetectMode != ANDROID_STATS_FACE_DETECTION_OFF) { + if (enableFaceDetect && faceDetectMode != ANDROID_STATISTICS_FACE_DETECT_MODE_OFF) { SharedParameters::Lock l(client->getParameters()); - entry = frame.find(ANDROID_STATS_FACE_RECTANGLES); + entry = frame.find(ANDROID_STATISTICS_FACE_RECTANGLES); if (entry.count == 0) { // No faces this frame /* warning: locks SharedCameraClient */ @@ -209,7 +209,7 @@ status_t FrameProcessor::processFaceDetect(const CameraMetadata &frame, } const int32_t *faceRects = entry.data.i32; - entry = frame.find(ANDROID_STATS_FACE_SCORES); + entry = frame.find(ANDROID_STATISTICS_FACE_SCORES); if (entry.count == 0) { ALOGE("%s: Camera %d: Unable to read face scores", __FUNCTION__, client->getCameraId()); @@ -220,8 +220,8 @@ status_t FrameProcessor::processFaceDetect(const CameraMetadata &frame, const int32_t *faceLandmarks = NULL; const int32_t *faceIds = NULL; - if (faceDetectMode == ANDROID_STATS_FACE_DETECTION_FULL) { - entry = frame.find(ANDROID_STATS_FACE_LANDMARKS); + if (faceDetectMode == ANDROID_STATISTICS_FACE_DETECT_MODE_FULL) { + entry = frame.find(ANDROID_STATISTICS_FACE_LANDMARKS); if (entry.count == 0) { ALOGE("%s: Camera %d: Unable to read face landmarks", __FUNCTION__, client->getCameraId()); @@ -229,7 +229,7 @@ status_t FrameProcessor::processFaceDetect(const CameraMetadata &frame, } faceLandmarks = entry.data.i32; - entry = frame.find(ANDROID_STATS_FACE_IDS); + entry = frame.find(ANDROID_STATISTICS_FACE_IDS); if (entry.count == 0) { ALOGE("%s: Camera %d: Unable to read face IDs", @@ -256,7 +256,7 @@ status_t FrameProcessor::processFaceDetect(const CameraMetadata &frame, face.rect[3] = l.mParameters.arrayYToNormalized(faceRects[i*4 + 3]); face.score = faceScores[i]; - if (faceDetectMode == ANDROID_STATS_FACE_DETECTION_FULL) { + if (faceDetectMode == ANDROID_STATISTICS_FACE_DETECT_MODE_FULL) { face.id = faceIds[i]; face.left_eye[0] = l.mParameters.arrayXToNormalized(faceLandmarks[i*6 + 0]); diff --git a/services/camera/libcameraservice/camera2/Parameters.cpp b/services/camera/libcameraservice/camera2/Parameters.cpp index 93927e6..6ab19b1 100644 --- a/services/camera/libcameraservice/camera2/Parameters.cpp +++ b/services/camera/libcameraservice/camera2/Parameters.cpp @@ -278,7 +278,7 @@ status_t Parameters::initialize(const CameraMetadata *info) { gpsProcessingMethod = "unknown"; // GPS fields in CameraParameters are not set by implementation - wbMode = ANDROID_CONTROL_AWB_AUTO; + wbMode = ANDROID_CONTROL_AWB_MODE_AUTO; params.set(CameraParameters::KEY_WHITE_BALANCE, CameraParameters::WHITE_BALANCE_AUTO); @@ -291,40 +291,40 @@ status_t Parameters::initialize(const CameraMetadata *info) { if (addComma) supportedWhiteBalance += ","; addComma = true; switch (availableWhiteBalanceModes.data.u8[i]) { - case ANDROID_CONTROL_AWB_AUTO: + case ANDROID_CONTROL_AWB_MODE_AUTO: supportedWhiteBalance += CameraParameters::WHITE_BALANCE_AUTO; break; - case ANDROID_CONTROL_AWB_INCANDESCENT: + case ANDROID_CONTROL_AWB_MODE_INCANDESCENT: supportedWhiteBalance += CameraParameters::WHITE_BALANCE_INCANDESCENT; break; - case ANDROID_CONTROL_AWB_FLUORESCENT: + case ANDROID_CONTROL_AWB_MODE_FLUORESCENT: supportedWhiteBalance += CameraParameters::WHITE_BALANCE_FLUORESCENT; break; - case ANDROID_CONTROL_AWB_WARM_FLUORESCENT: + case ANDROID_CONTROL_AWB_MODE_WARM_FLUORESCENT: supportedWhiteBalance += CameraParameters::WHITE_BALANCE_WARM_FLUORESCENT; break; - case ANDROID_CONTROL_AWB_DAYLIGHT: + case ANDROID_CONTROL_AWB_MODE_DAYLIGHT: supportedWhiteBalance += CameraParameters::WHITE_BALANCE_DAYLIGHT; break; - case ANDROID_CONTROL_AWB_CLOUDY_DAYLIGHT: + case ANDROID_CONTROL_AWB_MODE_CLOUDY_DAYLIGHT: supportedWhiteBalance += CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT; break; - case ANDROID_CONTROL_AWB_TWILIGHT: + case ANDROID_CONTROL_AWB_MODE_TWILIGHT: supportedWhiteBalance += CameraParameters::WHITE_BALANCE_TWILIGHT; break; - case ANDROID_CONTROL_AWB_SHADE: + case ANDROID_CONTROL_AWB_MODE_SHADE: supportedWhiteBalance += CameraParameters::WHITE_BALANCE_SHADE; break; // Skipping values not mappable to v1 API - case ANDROID_CONTROL_AWB_OFF: + case ANDROID_CONTROL_AWB_MODE_OFF: addComma = false; break; default: @@ -339,7 +339,7 @@ status_t Parameters::initialize(const CameraMetadata *info) { supportedWhiteBalance); } - effectMode = ANDROID_CONTROL_EFFECT_OFF; + effectMode = ANDROID_CONTROL_EFFECT_MODE_OFF; params.set(CameraParameters::KEY_EFFECT, CameraParameters::EFFECT_NONE); @@ -353,39 +353,39 @@ status_t Parameters::initialize(const CameraMetadata *info) { if (addComma) supportedEffects += ","; addComma = true; switch (availableEffects.data.u8[i]) { - case ANDROID_CONTROL_EFFECT_OFF: + case ANDROID_CONTROL_EFFECT_MODE_OFF: supportedEffects += CameraParameters::EFFECT_NONE; break; - case ANDROID_CONTROL_EFFECT_MONO: + case ANDROID_CONTROL_EFFECT_MODE_MONO: supportedEffects += CameraParameters::EFFECT_MONO; break; - case ANDROID_CONTROL_EFFECT_NEGATIVE: + case ANDROID_CONTROL_EFFECT_MODE_NEGATIVE: supportedEffects += CameraParameters::EFFECT_NEGATIVE; break; - case ANDROID_CONTROL_EFFECT_SOLARIZE: + case ANDROID_CONTROL_EFFECT_MODE_SOLARIZE: supportedEffects += CameraParameters::EFFECT_SOLARIZE; break; - case ANDROID_CONTROL_EFFECT_SEPIA: + case ANDROID_CONTROL_EFFECT_MODE_SEPIA: supportedEffects += CameraParameters::EFFECT_SEPIA; break; - case ANDROID_CONTROL_EFFECT_POSTERIZE: + case ANDROID_CONTROL_EFFECT_MODE_POSTERIZE: supportedEffects += CameraParameters::EFFECT_POSTERIZE; break; - case ANDROID_CONTROL_EFFECT_WHITEBOARD: + case ANDROID_CONTROL_EFFECT_MODE_WHITEBOARD: supportedEffects += CameraParameters::EFFECT_WHITEBOARD; break; - case ANDROID_CONTROL_EFFECT_BLACKBOARD: + case ANDROID_CONTROL_EFFECT_MODE_BLACKBOARD: supportedEffects += CameraParameters::EFFECT_BLACKBOARD; break; - case ANDROID_CONTROL_EFFECT_AQUA: + case ANDROID_CONTROL_EFFECT_MODE_AQUA: supportedEffects += CameraParameters::EFFECT_AQUA; break; @@ -399,7 +399,7 @@ status_t Parameters::initialize(const CameraMetadata *info) { params.set(CameraParameters::KEY_SUPPORTED_EFFECTS, supportedEffects); } - antibandingMode = ANDROID_CONTROL_AE_ANTIBANDING_AUTO; + antibandingMode = ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO; params.set(CameraParameters::KEY_ANTIBANDING, CameraParameters::ANTIBANDING_AUTO); @@ -413,19 +413,19 @@ status_t Parameters::initialize(const CameraMetadata *info) { if (addComma) supportedAntibanding += ","; addComma = true; switch (availableAntibandingModes.data.u8[i]) { - case ANDROID_CONTROL_AE_ANTIBANDING_OFF: + case ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF: supportedAntibanding += CameraParameters::ANTIBANDING_OFF; break; - case ANDROID_CONTROL_AE_ANTIBANDING_50HZ: + case ANDROID_CONTROL_AE_ANTIBANDING_MODE_50HZ: supportedAntibanding += CameraParameters::ANTIBANDING_50HZ; break; - case ANDROID_CONTROL_AE_ANTIBANDING_60HZ: + case ANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ: supportedAntibanding += CameraParameters::ANTIBANDING_60HZ; break; - case ANDROID_CONTROL_AE_ANTIBANDING_AUTO: + case ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO: supportedAntibanding += CameraParameters::ANTIBANDING_AUTO; break; @@ -538,7 +538,7 @@ status_t Parameters::initialize(const CameraMetadata *info) { } camera_metadata_ro_entry_t flashAvailable = - staticInfo(ANDROID_FLASH_AVAILABLE, 1, 1); + staticInfo(ANDROID_FLASH_INFO_AVAILABLE, 1, 1); if (!flashAvailable.count) return NO_INIT; camera_metadata_ro_entry_t availableAeModes = @@ -557,7 +557,7 @@ status_t Parameters::initialize(const CameraMetadata *info) { "," + CameraParameters::FLASH_MODE_TORCH; for (size_t i=0; i < availableAeModes.count; i++) { if (availableAeModes.data.u8[i] == - ANDROID_CONTROL_AE_ON_AUTO_FLASH_REDEYE) { + ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE) { supportedFlashModes = supportedFlashModes + "," + CameraParameters::FLASH_MODE_RED_EYE; break; @@ -574,7 +574,7 @@ status_t Parameters::initialize(const CameraMetadata *info) { } camera_metadata_ro_entry_t minFocusDistance = - staticInfo(ANDROID_LENS_MINIMUM_FOCUS_DISTANCE, 1, 1); + staticInfo(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE, 1, 1); if (!minFocusDistance.count) return NO_INIT; camera_metadata_ro_entry_t availableAfModes = @@ -599,28 +599,28 @@ status_t Parameters::initialize(const CameraMetadata *info) { if (addComma) supportedFocusModes += ","; addComma = true; switch (availableAfModes.data.u8[i]) { - case ANDROID_CONTROL_AF_AUTO: + case ANDROID_CONTROL_AF_MODE_AUTO: supportedFocusModes += CameraParameters::FOCUS_MODE_AUTO; break; - case ANDROID_CONTROL_AF_MACRO: + case ANDROID_CONTROL_AF_MODE_MACRO: supportedFocusModes += CameraParameters::FOCUS_MODE_MACRO; break; - case ANDROID_CONTROL_AF_CONTINUOUS_VIDEO: + case ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO: supportedFocusModes += CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO; break; - case ANDROID_CONTROL_AF_CONTINUOUS_PICTURE: + case ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE: supportedFocusModes += CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE; break; - case ANDROID_CONTROL_AF_EDOF: + case ANDROID_CONTROL_AF_MODE_EDOF: supportedFocusModes += CameraParameters::FOCUS_MODE_EDOF; break; // Not supported in old API - case ANDROID_CONTROL_AF_OFF: + case ANDROID_CONTROL_AF_MODE_OFF: addComma = false; break; default: @@ -651,14 +651,14 @@ status_t Parameters::initialize(const CameraMetadata *info) { focusingAreas.add(Parameters::Area(0,0,0,0,0)); camera_metadata_ro_entry_t availableFocalLengths = - staticInfo(ANDROID_LENS_AVAILABLE_FOCAL_LENGTHS); + staticInfo(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS); if (!availableFocalLengths.count) return NO_INIT; float minFocalLength = availableFocalLengths.data.f[0]; params.setFloat(CameraParameters::KEY_FOCAL_LENGTH, minFocalLength); camera_metadata_ro_entry_t sensorSize = - staticInfo(ANDROID_SENSOR_PHYSICAL_SIZE, 2, 2); + staticInfo(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, 2, 2); if (!sensorSize.count) return NO_INIT; // The fields of view here assume infinity focus, maximum wide angle @@ -674,7 +674,7 @@ status_t Parameters::initialize(const CameraMetadata *info) { exposureCompensation); camera_metadata_ro_entry_t exposureCompensationRange = - staticInfo(ANDROID_CONTROL_AE_EXP_COMPENSATION_RANGE, 2, 2); + staticInfo(ANDROID_CONTROL_AE_COMPENSATION_RANGE, 2, 2); if (!exposureCompensationRange.count) return NO_INIT; params.set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, @@ -683,7 +683,7 @@ status_t Parameters::initialize(const CameraMetadata *info) { exposureCompensationRange.data.i32[0]); camera_metadata_ro_entry_t exposureCompensationStep = - staticInfo(ANDROID_CONTROL_AE_EXP_COMPENSATION_STEP, 1, 1); + staticInfo(ANDROID_CONTROL_AE_COMPENSATION_STEP, 1, 1); if (!exposureCompensationStep.count) return NO_INIT; params.setFloat(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, @@ -713,7 +713,7 @@ status_t Parameters::initialize(const CameraMetadata *info) { params.set(CameraParameters::KEY_MAX_ZOOM, NUM_ZOOM_STEPS - 1); camera_metadata_ro_entry_t maxDigitalZoom = - staticInfo(ANDROID_SCALER_AVAILABLE_MAX_ZOOM, /*minCount*/1, /*maxCount*/1); + staticInfo(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, /*minCount*/1, /*maxCount*/1); if (!maxDigitalZoom.count) return NO_INIT; { @@ -811,31 +811,31 @@ String8 Parameters::get() const { status_t Parameters::buildFastInfo() { camera_metadata_ro_entry_t activeArraySize = - staticInfo(ANDROID_SENSOR_ACTIVE_ARRAY_SIZE, 2, 2); + staticInfo(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, 2, 2); if (!activeArraySize.count) return NO_INIT; int32_t arrayWidth = activeArraySize.data.i32[0]; int32_t arrayHeight = activeArraySize.data.i32[1]; camera_metadata_ro_entry_t availableFaceDetectModes = - staticInfo(ANDROID_STATS_AVAILABLE_FACE_DETECT_MODES); + staticInfo(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES); if (!availableFaceDetectModes.count) return NO_INIT; uint8_t bestFaceDetectMode = - ANDROID_STATS_FACE_DETECTION_OFF; + ANDROID_STATISTICS_FACE_DETECT_MODE_OFF; for (size_t i = 0 ; i < availableFaceDetectModes.count; i++) { switch (availableFaceDetectModes.data.u8[i]) { - case ANDROID_STATS_FACE_DETECTION_OFF: + case ANDROID_STATISTICS_FACE_DETECT_MODE_OFF: break; - case ANDROID_STATS_FACE_DETECTION_SIMPLE: + case ANDROID_STATISTICS_FACE_DETECT_MODE_SIMPLE: if (bestFaceDetectMode != - ANDROID_STATS_FACE_DETECTION_FULL) { + ANDROID_STATISTICS_FACE_DETECT_MODE_FULL) { bestFaceDetectMode = - ANDROID_STATS_FACE_DETECTION_SIMPLE; + ANDROID_STATISTICS_FACE_DETECT_MODE_SIMPLE; } break; - case ANDROID_STATS_FACE_DETECTION_FULL: + case ANDROID_STATISTICS_FACE_DETECT_MODE_FULL: bestFaceDetectMode = - ANDROID_STATS_FACE_DETECTION_FULL; + ANDROID_STATISTICS_FACE_DETECT_MODE_FULL; break; default: ALOGE("%s: Camera %d: Unknown face detect mode %d:", @@ -846,7 +846,7 @@ status_t Parameters::buildFastInfo() { } camera_metadata_ro_entry_t maxFacesDetected = - staticInfo(ANDROID_STATS_MAX_FACE_COUNT, 1, 1); + staticInfo(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, 1, 1); if (!maxFacesDetected.count) return NO_INIT; int32_t maxFaces = maxFacesDetected.data.i32[0]; @@ -856,7 +856,7 @@ status_t Parameters::buildFastInfo() { camera_metadata_ro_entry_t sceneModeOverrides = staticInfo(ANDROID_CONTROL_SCENE_MODE_OVERRIDES); camera_metadata_ro_entry_t minFocusDistance = - staticInfo(ANDROID_LENS_MINIMUM_FOCUS_DISTANCE); + staticInfo(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE); bool fixedLens = (minFocusDistance.data.f[0] == 0); if (sceneModeOverrides.count > 0) { @@ -877,16 +877,16 @@ status_t Parameters::buildFastInfo() { uint8_t aeMode = sceneModeOverrides.data.u8[i * kModesPerSceneMode + 0]; switch(aeMode) { - case ANDROID_CONTROL_AE_ON: + case ANDROID_CONTROL_AE_MODE_ON: modes.flashMode = FLASH_MODE_OFF; break; - case ANDROID_CONTROL_AE_ON_AUTO_FLASH: + case ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH: modes.flashMode = FLASH_MODE_AUTO; break; - case ANDROID_CONTROL_AE_ON_ALWAYS_FLASH: + case ANDROID_CONTROL_AE_MODE_ON_ALWAYS_FLASH: modes.flashMode = FLASH_MODE_ON; break; - case ANDROID_CONTROL_AE_ON_AUTO_FLASH_REDEYE: + case ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE: modes.flashMode = FLASH_MODE_RED_EYE; break; default: @@ -900,15 +900,15 @@ status_t Parameters::buildFastInfo() { uint8_t afMode = sceneModeOverrides.data.u8[i * kModesPerSceneMode + 2]; switch(afMode) { - case ANDROID_CONTROL_AF_OFF: + case ANDROID_CONTROL_AF_MODE_OFF: modes.focusMode = fixedLens ? FOCUS_MODE_FIXED : FOCUS_MODE_INFINITY; break; - case ANDROID_CONTROL_AF_AUTO: - case ANDROID_CONTROL_AF_MACRO: - case ANDROID_CONTROL_AF_CONTINUOUS_VIDEO: - case ANDROID_CONTROL_AF_CONTINUOUS_PICTURE: - case ANDROID_CONTROL_AF_EDOF: + case ANDROID_CONTROL_AF_MODE_AUTO: + case ANDROID_CONTROL_AF_MODE_MACRO: + case ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO: + case ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE: + case ANDROID_CONTROL_AF_MODE_EDOF: modes.focusMode = static_cast<focusMode_t>(afMode); break; default: @@ -1363,7 +1363,7 @@ status_t Parameters::set(const String8& paramString) { if (validatedParams.flashMode != flashMode) { camera_metadata_ro_entry_t flashAvailable = - staticInfo(ANDROID_FLASH_AVAILABLE, 1, 1); + staticInfo(ANDROID_FLASH_INFO_AVAILABLE, 1, 1); if (!flashAvailable.data.u8[0] && validatedParams.flashMode != Parameters::FLASH_MODE_OFF) { ALOGE("%s: Requested flash mode \"%s\" is not supported: " @@ -1400,9 +1400,9 @@ status_t Parameters::set(const String8& paramString) { fastInfo.sceneModeOverrides. valueFor(validatedParams.sceneMode).wbMode; } else { - validatedParams.wbMode = ANDROID_CONTROL_AWB_OFF; + validatedParams.wbMode = ANDROID_CONTROL_AWB_MODE_OFF; } - if (validatedParams.wbMode == ANDROID_CONTROL_AWB_OFF) { + if (validatedParams.wbMode == ANDROID_CONTROL_AWB_MODE_OFF) { validatedParams.wbMode = wbModeStringToEnum( newParams.get(CameraParameters::KEY_WHITE_BALANCE) ); } @@ -1439,7 +1439,7 @@ status_t Parameters::set(const String8& paramString) { validatedParams.currentAfTriggerId = -1; if (validatedParams.focusMode != Parameters::FOCUS_MODE_FIXED) { camera_metadata_ro_entry_t minFocusDistance = - staticInfo(ANDROID_LENS_MINIMUM_FOCUS_DISTANCE); + staticInfo(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE); if (minFocusDistance.data.f[0] == 0) { ALOGE("%s: Requested focus mode \"%s\" is not available: " "fixed focus lens", @@ -1489,7 +1489,7 @@ status_t Parameters::set(const String8& paramString) { validatedParams.exposureCompensation = newParams.getInt(CameraParameters::KEY_EXPOSURE_COMPENSATION); camera_metadata_ro_entry_t exposureCompensationRange = - staticInfo(ANDROID_CONTROL_AE_EXP_COMPENSATION_RANGE); + staticInfo(ANDROID_CONTROL_AE_COMPENSATION_RANGE); if ((validatedParams.exposureCompensation < exposureCompensationRange.data.i32[0]) || (validatedParams.exposureCompensation > @@ -1585,7 +1585,7 @@ status_t Parameters::updateRequest(CameraMetadata *request) const { ATRACE_CALL(); status_t res; - uint8_t metadataMode = ANDROID_REQUEST_METADATA_FULL; + uint8_t metadataMode = ANDROID_REQUEST_METADATA_MODE_FULL; res = request->update(ANDROID_REQUEST_METADATA_MODE, &metadataMode, 1); if (res != OK) return res; @@ -1612,9 +1612,9 @@ status_t Parameters::updateRequest(CameraMetadata *request) const { // to the other. bool sceneModeActive = sceneMode != (uint8_t)ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED; - uint8_t reqControlMode = ANDROID_CONTROL_AUTO; + uint8_t reqControlMode = ANDROID_CONTROL_MODE_AUTO; if (enableFaceDetect || sceneModeActive) { - reqControlMode = ANDROID_CONTROL_USE_SCENE_MODE; + reqControlMode = ANDROID_CONTROL_MODE_USE_SCENE_MODE; } res = request->update(ANDROID_CONTROL_MODE, &reqControlMode, 1); @@ -1628,21 +1628,21 @@ status_t Parameters::updateRequest(CameraMetadata *request) const { &reqSceneMode, 1); if (res != OK) return res; - uint8_t reqFlashMode = ANDROID_FLASH_OFF; - uint8_t reqAeMode = ANDROID_CONTROL_AE_OFF; + uint8_t reqFlashMode = ANDROID_FLASH_MODE_OFF; + uint8_t reqAeMode = ANDROID_CONTROL_AE_MODE_OFF; switch (flashMode) { case Parameters::FLASH_MODE_OFF: - reqAeMode = ANDROID_CONTROL_AE_ON; break; + reqAeMode = ANDROID_CONTROL_AE_MODE_ON; break; case Parameters::FLASH_MODE_AUTO: - reqAeMode = ANDROID_CONTROL_AE_ON_AUTO_FLASH; break; + reqAeMode = ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH; break; case Parameters::FLASH_MODE_ON: - reqAeMode = ANDROID_CONTROL_AE_ON_ALWAYS_FLASH; break; + reqAeMode = ANDROID_CONTROL_AE_MODE_ON_ALWAYS_FLASH; break; case Parameters::FLASH_MODE_TORCH: - reqAeMode = ANDROID_CONTROL_AE_ON; - reqFlashMode = ANDROID_FLASH_TORCH; + reqAeMode = ANDROID_CONTROL_AE_MODE_ON; + reqFlashMode = ANDROID_FLASH_MODE_TORCH; break; case Parameters::FLASH_MODE_RED_EYE: - reqAeMode = ANDROID_CONTROL_AE_ON_AUTO_FLASH_REDEYE; break; + reqAeMode = ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE; break; default: ALOGE("%s: Camera %d: Unknown flash mode %d", __FUNCTION__, cameraId, flashMode); @@ -1666,7 +1666,7 @@ status_t Parameters::updateRequest(CameraMetadata *request) const { if (res != OK) return res; float reqFocusDistance = 0; // infinity focus in diopters - uint8_t reqFocusMode = ANDROID_CONTROL_AF_OFF; + uint8_t reqFocusMode = ANDROID_CONTROL_AF_MODE_OFF; switch (focusMode) { case Parameters::FOCUS_MODE_AUTO: case Parameters::FOCUS_MODE_MACRO: @@ -1677,7 +1677,7 @@ status_t Parameters::updateRequest(CameraMetadata *request) const { break; case Parameters::FOCUS_MODE_INFINITY: case Parameters::FOCUS_MODE_FIXED: - reqFocusMode = ANDROID_CONTROL_AF_OFF; + reqFocusMode = ANDROID_CONTROL_AF_MODE_OFF; break; default: ALOGE("%s: Camera %d: Unknown focus mode %d", __FUNCTION__, @@ -1716,7 +1716,7 @@ status_t Parameters::updateRequest(CameraMetadata *request) const { if (res != OK) return res; delete[] reqFocusingAreas; - res = request->update(ANDROID_CONTROL_AE_EXP_COMPENSATION, + res = request->update(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, &exposureCompensation, 1); if (res != OK) return res; @@ -1758,16 +1758,16 @@ status_t Parameters::updateRequest(CameraMetadata *request) const { if (res != OK) return res; uint8_t reqVstabMode = videoStabilization ? - ANDROID_CONTROL_VIDEO_STABILIZATION_ON : - ANDROID_CONTROL_VIDEO_STABILIZATION_OFF; + ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_ON : + ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF; res = request->update(ANDROID_CONTROL_VIDEO_STABILIZATION_MODE, &reqVstabMode, 1); if (res != OK) return res; uint8_t reqFaceDetectMode = enableFaceDetect ? fastInfo.bestFaceDetectMode : - (uint8_t)ANDROID_STATS_FACE_DETECTION_OFF; - res = request->update(ANDROID_STATS_FACE_DETECT_MODE, + (uint8_t)ANDROID_STATISTICS_FACE_DETECT_MODE_OFF; + res = request->update(ANDROID_STATISTICS_FACE_DETECT_MODE, &reqFaceDetectMode, 1); if (res != OK) return res; @@ -1891,43 +1891,43 @@ const char* Parameters::formatEnumToString(int format) { int Parameters::wbModeStringToEnum(const char *wbMode) { return !wbMode ? - ANDROID_CONTROL_AWB_AUTO : + ANDROID_CONTROL_AWB_MODE_AUTO : !strcmp(wbMode, CameraParameters::WHITE_BALANCE_AUTO) ? - ANDROID_CONTROL_AWB_AUTO : + ANDROID_CONTROL_AWB_MODE_AUTO : !strcmp(wbMode, CameraParameters::WHITE_BALANCE_INCANDESCENT) ? - ANDROID_CONTROL_AWB_INCANDESCENT : + ANDROID_CONTROL_AWB_MODE_INCANDESCENT : !strcmp(wbMode, CameraParameters::WHITE_BALANCE_FLUORESCENT) ? - ANDROID_CONTROL_AWB_FLUORESCENT : + ANDROID_CONTROL_AWB_MODE_FLUORESCENT : !strcmp(wbMode, CameraParameters::WHITE_BALANCE_WARM_FLUORESCENT) ? - ANDROID_CONTROL_AWB_WARM_FLUORESCENT : + ANDROID_CONTROL_AWB_MODE_WARM_FLUORESCENT : !strcmp(wbMode, CameraParameters::WHITE_BALANCE_DAYLIGHT) ? - ANDROID_CONTROL_AWB_DAYLIGHT : + ANDROID_CONTROL_AWB_MODE_DAYLIGHT : !strcmp(wbMode, CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT) ? - ANDROID_CONTROL_AWB_CLOUDY_DAYLIGHT : + ANDROID_CONTROL_AWB_MODE_CLOUDY_DAYLIGHT : !strcmp(wbMode, CameraParameters::WHITE_BALANCE_TWILIGHT) ? - ANDROID_CONTROL_AWB_TWILIGHT : + ANDROID_CONTROL_AWB_MODE_TWILIGHT : !strcmp(wbMode, CameraParameters::WHITE_BALANCE_SHADE) ? - ANDROID_CONTROL_AWB_SHADE : + ANDROID_CONTROL_AWB_MODE_SHADE : -1; } const char* Parameters::wbModeEnumToString(uint8_t wbMode) { switch (wbMode) { - case ANDROID_CONTROL_AWB_AUTO: + case ANDROID_CONTROL_AWB_MODE_AUTO: return CameraParameters::WHITE_BALANCE_AUTO; - case ANDROID_CONTROL_AWB_INCANDESCENT: + case ANDROID_CONTROL_AWB_MODE_INCANDESCENT: return CameraParameters::WHITE_BALANCE_INCANDESCENT; - case ANDROID_CONTROL_AWB_FLUORESCENT: + case ANDROID_CONTROL_AWB_MODE_FLUORESCENT: return CameraParameters::WHITE_BALANCE_FLUORESCENT; - case ANDROID_CONTROL_AWB_WARM_FLUORESCENT: + case ANDROID_CONTROL_AWB_MODE_WARM_FLUORESCENT: return CameraParameters::WHITE_BALANCE_WARM_FLUORESCENT; - case ANDROID_CONTROL_AWB_DAYLIGHT: + case ANDROID_CONTROL_AWB_MODE_DAYLIGHT: return CameraParameters::WHITE_BALANCE_DAYLIGHT; - case ANDROID_CONTROL_AWB_CLOUDY_DAYLIGHT: + case ANDROID_CONTROL_AWB_MODE_CLOUDY_DAYLIGHT: return CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT; - case ANDROID_CONTROL_AWB_TWILIGHT: + case ANDROID_CONTROL_AWB_MODE_TWILIGHT: return CameraParameters::WHITE_BALANCE_TWILIGHT; - case ANDROID_CONTROL_AWB_SHADE: + case ANDROID_CONTROL_AWB_MODE_SHADE: return CameraParameters::WHITE_BALANCE_SHADE; default: ALOGE("%s: Unknown AWB mode enum: %d", @@ -1939,40 +1939,40 @@ const char* Parameters::wbModeEnumToString(uint8_t wbMode) { int Parameters::effectModeStringToEnum(const char *effectMode) { return !effectMode ? - ANDROID_CONTROL_EFFECT_OFF : + ANDROID_CONTROL_EFFECT_MODE_OFF : !strcmp(effectMode, CameraParameters::EFFECT_NONE) ? - ANDROID_CONTROL_EFFECT_OFF : + ANDROID_CONTROL_EFFECT_MODE_OFF : !strcmp(effectMode, CameraParameters::EFFECT_MONO) ? - ANDROID_CONTROL_EFFECT_MONO : + ANDROID_CONTROL_EFFECT_MODE_MONO : !strcmp(effectMode, CameraParameters::EFFECT_NEGATIVE) ? - ANDROID_CONTROL_EFFECT_NEGATIVE : + ANDROID_CONTROL_EFFECT_MODE_NEGATIVE : !strcmp(effectMode, CameraParameters::EFFECT_SOLARIZE) ? - ANDROID_CONTROL_EFFECT_SOLARIZE : + ANDROID_CONTROL_EFFECT_MODE_SOLARIZE : !strcmp(effectMode, CameraParameters::EFFECT_SEPIA) ? - ANDROID_CONTROL_EFFECT_SEPIA : + ANDROID_CONTROL_EFFECT_MODE_SEPIA : !strcmp(effectMode, CameraParameters::EFFECT_POSTERIZE) ? - ANDROID_CONTROL_EFFECT_POSTERIZE : + ANDROID_CONTROL_EFFECT_MODE_POSTERIZE : !strcmp(effectMode, CameraParameters::EFFECT_WHITEBOARD) ? - ANDROID_CONTROL_EFFECT_WHITEBOARD : + ANDROID_CONTROL_EFFECT_MODE_WHITEBOARD : !strcmp(effectMode, CameraParameters::EFFECT_BLACKBOARD) ? - ANDROID_CONTROL_EFFECT_BLACKBOARD : + ANDROID_CONTROL_EFFECT_MODE_BLACKBOARD : !strcmp(effectMode, CameraParameters::EFFECT_AQUA) ? - ANDROID_CONTROL_EFFECT_AQUA : + ANDROID_CONTROL_EFFECT_MODE_AQUA : -1; } int Parameters::abModeStringToEnum(const char *abMode) { return !abMode ? - ANDROID_CONTROL_AE_ANTIBANDING_AUTO : + ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO : !strcmp(abMode, CameraParameters::ANTIBANDING_AUTO) ? - ANDROID_CONTROL_AE_ANTIBANDING_AUTO : + ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO : !strcmp(abMode, CameraParameters::ANTIBANDING_OFF) ? - ANDROID_CONTROL_AE_ANTIBANDING_OFF : + ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF : !strcmp(abMode, CameraParameters::ANTIBANDING_50HZ) ? - ANDROID_CONTROL_AE_ANTIBANDING_50HZ : + ANDROID_CONTROL_AE_ANTIBANDING_MODE_50HZ : !strcmp(abMode, CameraParameters::ANTIBANDING_60HZ) ? - ANDROID_CONTROL_AE_ANTIBANDING_60HZ : + ANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ : -1; } @@ -2329,7 +2329,7 @@ Parameters::CropRegion Parameters::calculateCropRegion( // chosen to maximize its area on the sensor camera_metadata_ro_entry_t maxDigitalZoom = - staticInfo(ANDROID_SCALER_AVAILABLE_MAX_ZOOM); + staticInfo(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM); // For each zoom step by how many pixels more do we change the zoom float zoomIncrement = (maxDigitalZoom.data.f[0] - 1) / (NUM_ZOOM_STEPS-1); diff --git a/services/camera/libcameraservice/camera2/Parameters.h b/services/camera/libcameraservice/camera2/Parameters.h index 6d32bf6..4192e97 100644 --- a/services/camera/libcameraservice/camera2/Parameters.h +++ b/services/camera/libcameraservice/camera2/Parameters.h @@ -73,16 +73,16 @@ struct Parameters { FLASH_MODE_AUTO, FLASH_MODE_ON, FLASH_MODE_TORCH, - FLASH_MODE_RED_EYE = ANDROID_CONTROL_AE_ON_AUTO_FLASH_REDEYE, + FLASH_MODE_RED_EYE = ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE, FLASH_MODE_INVALID = -1 } flashMode; enum focusMode_t { - FOCUS_MODE_AUTO = ANDROID_CONTROL_AF_AUTO, - FOCUS_MODE_MACRO = ANDROID_CONTROL_AF_MACRO, - FOCUS_MODE_CONTINUOUS_VIDEO = ANDROID_CONTROL_AF_CONTINUOUS_VIDEO, - FOCUS_MODE_CONTINUOUS_PICTURE = ANDROID_CONTROL_AF_CONTINUOUS_PICTURE, - FOCUS_MODE_EDOF = ANDROID_CONTROL_AF_EDOF, + FOCUS_MODE_AUTO = ANDROID_CONTROL_AF_MODE_AUTO, + FOCUS_MODE_MACRO = ANDROID_CONTROL_AF_MODE_MACRO, + FOCUS_MODE_CONTINUOUS_VIDEO = ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO, + FOCUS_MODE_CONTINUOUS_PICTURE = ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE, + FOCUS_MODE_EDOF = ANDROID_CONTROL_AF_MODE_EDOF, FOCUS_MODE_INFINITY, FOCUS_MODE_FIXED, FOCUS_MODE_INVALID = -1 @@ -179,7 +179,7 @@ struct Parameters { focusMode_t focusMode; OverrideModes(): flashMode(FLASH_MODE_INVALID), - wbMode(ANDROID_CONTROL_AWB_OFF), + wbMode(ANDROID_CONTROL_AWB_MODE_OFF), focusMode(FOCUS_MODE_INVALID) { } }; |