GraphicBufferSource.h revision e40cda70eec141fa05cbcca1de420fdb22b98be6
1/*
2 * Copyright (C) 2013 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 GRAPHIC_BUFFER_SOURCE_H_
18
19#define GRAPHIC_BUFFER_SOURCE_H_
20
21#include <gui/IGraphicBufferProducer.h>
22#include <gui/BufferQueue.h>
23#include <utils/RefBase.h>
24
25#include <OMX_Core.h>
26#include "../include/OMXNodeInstance.h"
27#include <media/stagefright/foundation/ABase.h>
28
29namespace android {
30
31/*
32 * This class is used to feed OMX codecs from a Surface via BufferQueue.
33 *
34 * Instances of the class don't run on a dedicated thread.  Instead,
35 * various events trigger data movement:
36 *
37 *  - Availability of a new frame of data from the BufferQueue (notified
38 *    via the onFrameAvailable callback).
39 *  - The return of a codec buffer (via OnEmptyBufferDone).
40 *  - Application signaling end-of-stream.
41 *  - Transition to or from "executing" state.
42 *
43 * Frames of data (and, perhaps, the end-of-stream indication) can arrive
44 * before the codec is in the "executing" state, so we need to queue
45 * things up until we're ready to go.
46 */
47class GraphicBufferSource : public BufferQueue::ConsumerListener {
48public:
49    GraphicBufferSource(OMXNodeInstance* nodeInstance,
50            uint32_t bufferWidth, uint32_t bufferHeight, uint32_t bufferCount);
51    virtual ~GraphicBufferSource();
52
53    // We can't throw an exception if the constructor fails, so we just set
54    // this and require that the caller test the value.
55    status_t initCheck() const {
56        return mInitCheck;
57    }
58
59    // Returns the handle to the producer side of the BufferQueue.  Buffers
60    // queued on this will be received by GraphicBufferSource.
61    sp<IGraphicBufferProducer> getIGraphicBufferProducer() const {
62        return mBufferQueue;
63    }
64
65    // This is called when OMX transitions to OMX_StateExecuting, which means
66    // we can start handing it buffers.  If we already have buffers of data
67    // sitting in the BufferQueue, this will send them to the codec.
68    void omxExecuting();
69
70    // This is called when OMX transitions to OMX_StateLoaded, indicating that
71    // we are shutting down.
72    void omxLoaded();
73
74    // A "codec buffer", i.e. a buffer that can be used to pass data into
75    // the encoder, has been allocated.  (This call does not call back into
76    // OMXNodeInstance.)
77    void addCodecBuffer(OMX_BUFFERHEADERTYPE* header);
78
79    // Called from OnEmptyBufferDone.  If we have a BQ buffer available,
80    // fill it with a new frame of data; otherwise, just mark it as available.
81    void codecBufferEmptied(OMX_BUFFERHEADERTYPE* header);
82
83    // This is called after the last input frame has been submitted.  We
84    // need to submit an empty buffer with the EOS flag set.  If we don't
85    // have a codec buffer ready, we just set the mEndOfStream flag.
86    status_t signalEndOfInputStream();
87
88    // If suspend is true, all incoming buffers (including those currently
89    // in the BufferQueue) will be discarded until the suspension is lifted.
90    void suspend(bool suspend);
91
92protected:
93    // BufferQueue::ConsumerListener interface, called when a new frame of
94    // data is available.  If we're executing and a codec buffer is
95    // available, we acquire the buffer, copy the GraphicBuffer reference
96    // into the codec buffer, and call Empty[This]Buffer.  If we're not yet
97    // executing or there's no codec buffer available, we just increment
98    // mNumFramesAvailable and return.
99    virtual void onFrameAvailable();
100
101    // BufferQueue::ConsumerListener interface, called when the client has
102    // released one or more GraphicBuffers.  We clear out the appropriate
103    // set of mBufferSlot entries.
104    virtual void onBuffersReleased();
105
106private:
107    // Keep track of codec input buffers.  They may either be available
108    // (mGraphicBuffer == NULL) or in use by the codec.
109    struct CodecBuffer {
110        OMX_BUFFERHEADERTYPE* mHeader;
111
112        // buffer producer's frame-number for buffer
113        uint64_t mFrameNumber;
114
115        // buffer producer's buffer slot for buffer
116        int mBuf;
117
118        sp<GraphicBuffer> mGraphicBuffer;
119    };
120
121    // Returns the index of an available codec buffer.  If none are
122    // available, returns -1.  Mutex must be held by caller.
123    int findAvailableCodecBuffer_l();
124
125    // Returns true if a codec buffer is available.
126    bool isCodecBufferAvailable_l() {
127        return findAvailableCodecBuffer_l() >= 0;
128    }
129
130    // Finds the mCodecBuffers entry that matches.  Returns -1 if not found.
131    int findMatchingCodecBuffer_l(const OMX_BUFFERHEADERTYPE* header);
132
133    // Fills a codec buffer with a frame from the BufferQueue.  This must
134    // only be called when we know that a frame of data is ready (i.e. we're
135    // in the onFrameAvailable callback, or if we're in codecBufferEmptied
136    // and mNumFramesAvailable is nonzero).  Returns without doing anything if
137    // we don't have a codec buffer available.
138    //
139    // Returns true if we successfully filled a codec buffer with a BQ buffer.
140    bool fillCodecBuffer_l();
141
142    // Marks the mCodecBuffers entry as in-use, copies the GraphicBuffer
143    // reference into the codec buffer, and submits the data to the codec.
144    status_t submitBuffer_l(const BufferQueue::BufferItem &item, int cbi);
145
146    // Submits an empty buffer, with the EOS flag set.   Returns without
147    // doing anything if we don't have a codec buffer available.
148    void submitEndOfInputStream_l();
149
150    // Lock, covers all member variables.
151    mutable Mutex mMutex;
152
153    // Used to report constructor failure.
154    status_t mInitCheck;
155
156    // Pointer back to the object that contains us.  We send buffers here.
157    OMXNodeInstance* mNodeInstance;
158
159    // Set by omxExecuting() / omxIdling().
160    bool mExecuting;
161
162    bool mSuspended;
163
164    // We consume graphic buffers from this.
165    sp<BufferQueue> mBufferQueue;
166
167    // Number of frames pending in BufferQueue that haven't yet been
168    // forwarded to the codec.
169    size_t mNumFramesAvailable;
170
171    // Set to true if we want to send end-of-stream after we run out of
172    // frames in BufferQueue.
173    bool mEndOfStream;
174    bool mEndOfStreamSent;
175
176    // Cache of GraphicBuffers from the buffer queue.  When the codec
177    // is done processing a GraphicBuffer, we can use this to map back
178    // to a slot number.
179    sp<GraphicBuffer> mBufferSlot[BufferQueue::NUM_BUFFER_SLOTS];
180
181    // Tracks codec buffers.
182    Vector<CodecBuffer> mCodecBuffers;
183
184    DISALLOW_EVIL_CONSTRUCTORS(GraphicBufferSource);
185};
186
187}  // namespace android
188
189#endif  // GRAPHIC_BUFFER_SOURCE_H_
190