1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_GUI_SURFACEMEDIASOURCE_H
18#define ANDROID_GUI_SURFACEMEDIASOURCE_H
19
20#include <gui/IGraphicBufferProducer.h>
21#include <gui/BufferQueue.h>
22
23#include <utils/threads.h>
24#include <utils/Vector.h>
25#include <media/stagefright/MediaSource.h>
26#include <media/stagefright/MediaBuffer.h>
27
28namespace android {
29// ----------------------------------------------------------------------------
30
31class IGraphicBufferAlloc;
32class String8;
33class GraphicBuffer;
34
35// ASSUMPTIONS
36// 1. SurfaceMediaSource is initialized with width*height which
37// can never change.  However, deqeueue buffer does not currently
38// enforce this as in BufferQueue, dequeue can be used by Surface
39// which can modify the default width and heght.  Also neither the width
40// nor height can be 0.
41// 2. setSynchronousMode is never used (basically no one should call
42// setSynchronousMode(false)
43// 3. setCrop, setTransform, setScalingMode should never be used
44// 4. queueBuffer returns a filled buffer to the SurfaceMediaSource. In addition, a
45// timestamp must be provided for the buffer. The timestamp is in
46// nanoseconds, and must be monotonically increasing. Its other semantics
47// (zero point, etc) are client-dependent and should be documented by the
48// client.
49// 5. Once disconnected, SurfaceMediaSource can be reused (can not
50// connect again)
51// 6. Stop is a hard stop, the last few frames held by the encoder
52// may be dropped.  It is possible to wait for the buffers to be
53// returned (but not implemented)
54
55#define DEBUG_PENDING_BUFFERS   0
56
57class SurfaceMediaSource : public MediaSource,
58                                public MediaBufferObserver,
59                                protected ConsumerListener {
60public:
61    enum { MIN_UNDEQUEUED_BUFFERS = 4};
62
63    struct FrameAvailableListener : public virtual RefBase {
64        // onFrameAvailable() is called from queueBuffer() is the FIFO is
65        // empty. You can use SurfaceMediaSource::getQueuedCount() to
66        // figure out if there are more frames waiting.
67        // This is called without any lock held can be called concurrently by
68        // multiple threads.
69        virtual void onFrameAvailable() = 0;
70    };
71
72    SurfaceMediaSource(uint32_t bufferWidth, uint32_t bufferHeight);
73
74    virtual ~SurfaceMediaSource();
75
76    // For the MediaSource interface for use by StageFrightRecorder:
77    virtual status_t start(MetaData *params = NULL);
78    virtual status_t stop();
79    virtual status_t read(MediaBuffer **buffer,
80            const ReadOptions *options = NULL);
81    virtual sp<MetaData> getFormat();
82
83    // Get / Set the frame rate used for encoding. Default fps = 30
84    status_t setFrameRate(int32_t fps) ;
85    int32_t getFrameRate( ) const;
86
87    // The call for the StageFrightRecorder to tell us that
88    // it is done using the MediaBuffer data so that its state
89    // can be set to FREE for dequeuing
90    virtual void signalBufferReturned(MediaBuffer* buffer);
91    // end of MediaSource interface
92
93    // getTimestamp retrieves the timestamp associated with the image
94    // set by the most recent call to read()
95    //
96    // The timestamp is in nanoseconds, and is monotonically increasing. Its
97    // other semantics (zero point, etc) are source-dependent and should be
98    // documented by the source.
99    int64_t getTimestamp();
100
101    // setFrameAvailableListener sets the listener object that will be notified
102    // when a new frame becomes available.
103    void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
104
105    // dump our state in a String
106    void dump(String8& result) const;
107    void dump(String8& result, const char* prefix, char* buffer,
108                                                    size_t SIZE) const;
109
110    // isMetaDataStoredInVideoBuffers tells the encoder whether we will
111    // pass metadata through the buffers. Currently, it is force set to true
112    bool isMetaDataStoredInVideoBuffers() const;
113
114    sp<IGraphicBufferProducer> getProducer() const { return mProducer; }
115
116    // To be called before start()
117    status_t setMaxAcquiredBufferCount(size_t count);
118
119    // To be called before start()
120    status_t setUseAbsoluteTimestamps();
121
122protected:
123
124    // Implementation of the BufferQueue::ConsumerListener interface.  These
125    // calls are used to notify the Surface of asynchronous events in the
126    // BufferQueue.
127    virtual void onFrameAvailable(const BufferItem& item);
128
129    // Used as a hook to BufferQueue::disconnect()
130    // This is called by the client side when it is done
131    // TODO: Currently, this also sets mStopped to true which
132    // is needed for unblocking the encoder which might be
133    // waiting to read more frames. So if on the client side,
134    // the same thread supplies the frames and also calls stop
135    // on the encoder, the client has to call disconnect before
136    // it calls stop.
137    // In the case of the camera,
138    // that need not be required since the thread supplying the
139    // frames is separate than the one calling stop.
140    virtual void onBuffersReleased();
141
142    // SurfaceMediaSource can't handle sideband streams, so this is not expected
143    // to ever be called. Does nothing.
144    virtual void onSidebandStreamChanged();
145
146    static bool isExternalFormat(uint32_t format);
147
148private:
149    // A BufferQueue, represented by these interfaces, is the exchange point
150    // between the producer and this consumer
151    sp<IGraphicBufferProducer> mProducer;
152    sp<IGraphicBufferConsumer> mConsumer;
153
154    struct SlotData {
155        sp<GraphicBuffer> mGraphicBuffer;
156        uint64_t mFrameNumber;
157    };
158
159    // mSlots caches GraphicBuffers and frameNumbers from the buffer queue
160    SlotData mSlots[BufferQueue::NUM_BUFFER_SLOTS];
161
162    // The permenent width and height of SMS buffers
163    int mWidth;
164    int mHeight;
165
166    // mCurrentSlot is the buffer slot index of the buffer that is currently
167    // being used by buffer consumer
168    // (e.g. StageFrightRecorder in the case of SurfaceMediaSource or GLTexture
169    // in the case of Surface).
170    // It is initialized to INVALID_BUFFER_SLOT,
171    // indicating that no buffer slot is currently bound to the texture. Note,
172    // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean
173    // that no buffer is bound to the texture. A call to setBufferCount will
174    // reset mCurrentTexture to INVALID_BUFFER_SLOT.
175    int mCurrentSlot;
176
177    // mCurrentBuffers is a list of the graphic buffers that are being used by
178    // buffer consumer (i.e. the video encoder). It's possible that these
179    // buffers are not associated with any buffer slots, so we must track them
180    // separately.  Buffers are added to this list in read, and removed from
181    // this list in signalBufferReturned
182    Vector<sp<GraphicBuffer> > mCurrentBuffers;
183
184    size_t mNumPendingBuffers;
185
186#if DEBUG_PENDING_BUFFERS
187    Vector<MediaBuffer *> mPendingBuffers;
188#endif
189
190    // mCurrentTimestamp is the timestamp for the current texture. It
191    // gets set to mLastQueuedTimestamp each time updateTexImage is called.
192    int64_t mCurrentTimestamp;
193
194    // mFrameAvailableListener is the listener object that will be called when a
195    // new frame becomes available. If it is not NULL it will be called from
196    // queueBuffer.
197    sp<FrameAvailableListener> mFrameAvailableListener;
198
199    // mMutex is the mutex used to prevent concurrent access to the member
200    // variables of SurfaceMediaSource objects. It must be locked whenever the
201    // member variables are accessed.
202    mutable Mutex mMutex;
203
204    ////////////////////////// For MediaSource
205    // Set to a default of 30 fps if not specified by the client side
206    int32_t mFrameRate;
207
208    // mStarted is a flag to check if the recording is going on
209    bool mStarted;
210
211    // mNumFramesReceived indicates the number of frames recieved from
212    // the client side
213    int mNumFramesReceived;
214    // mNumFramesEncoded indicates the number of frames passed on to the
215    // encoder
216    int mNumFramesEncoded;
217
218    // mFirstFrameTimestamp is the timestamp of the first received frame.
219    // It is used to offset the output timestamps so recording starts at time 0.
220    int64_t mFirstFrameTimestamp;
221    // mStartTimeNs is the start time passed into the source at start, used to
222    // offset timestamps.
223    int64_t mStartTimeNs;
224
225    size_t mMaxAcquiredBufferCount;
226
227    bool mUseAbsoluteTimestamps;
228
229    // mFrameAvailableCondition condition used to indicate whether there
230    // is a frame available for dequeuing
231    Condition mFrameAvailableCondition;
232
233    Condition mMediaBuffersAvailableCondition;
234
235    // Avoid copying and equating and default constructor
236    DISALLOW_IMPLICIT_CONSTRUCTORS(SurfaceMediaSource);
237};
238
239// ----------------------------------------------------------------------------
240}; // namespace android
241
242#endif // ANDROID_GUI_SURFACEMEDIASOURCE_H
243