* kMetadataBufferTypeGrallocSource is used to indicate that
* the payload of the metadata buffers can be interpreted as
* a buffer_handle_t.
+ * So in this case,the metadata that the encoder receives
+ * will have a byte stream that consists of two parts:
+ * 1. First, there is an integer indicating that it is a GRAlloc
+ * source (kMetadataBufferTypeGrallocSource)
+ * 2. This is followed by the buffer_handle_t that is a handle to the
+ * GRalloc buffer. The encoder needs to interpret this GRalloc handle
+ * and encode the frames.
+ * --------------------------------------------------------------
+ * | kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
+ * --------------------------------------------------------------
*/
kMetadataBufferTypeGrallocSource = 1,
MediaBuffer **buffer, const ReadOptions *options = NULL);
virtual sp<MetaData> getFormat();
+ // Pass the metadata over to the buffer, call when you have the lock
+ void passMetadataBufferLocked(MediaBuffer **buffer);
+ bool checkBufferMatchesSlot(int slot, MediaBuffer *buffer);
+
// Get / Set the frame rate used for encoding. Default fps = 30
status_t setFrameRate(int32_t fps) ;
int32_t getFrameRate( ) const;
status_t setBufferCountServer(int bufferCount);
// getTimestamp retrieves the timestamp associated with the image
- // set by the most recent call to updateFrameInfoLocked().
+ // set by the most recent call to read()
//
// The timestamp is in nanoseconds, and is monotonically increasing. Its
// other semantics (zero point, etc) are source-dependent and should be
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/openmax/OMX_IVCommon.h>
+#include <media/stagefright/MetadataBufferType.h>
#include <surfaceflinger/ISurfaceComposer.h>
#include <surfaceflinger/SurfaceComposerClient.h>
mCurrentBuf = mSlots[mCurrentSlot].mGraphicBuffer;
mCurrentTimestamp = mSlots[mCurrentSlot].mTimestamp;
- // Pass the data to the MediaBuffer
- // TODO: Change later to pass in only the metadata
- *buffer = new MediaBuffer(mCurrentBuf);
+ // Pass the data to the MediaBuffer. Pass in only the metadata
+ passMetadataBufferLocked(buffer);
+
(*buffer)->setObserver(this);
(*buffer)->add_ref();
(*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp);
return OK;
}
+// Pass the data to the MediaBuffer. Pass in only the metadata
+// The metadata passed consists of two parts:
+// 1. First, there is an integer indicating that it is a GRAlloc
+// source (kMetadataBufferTypeGrallocSource)
+// 2. This is followed by the buffer_handle_t that is a handle to the
+// GRalloc buffer. The encoder needs to interpret this GRalloc handle
+// and encode the frames.
+// --------------------------------------------------------------
+// | kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
+// --------------------------------------------------------------
+// Note: Call only when you have the lock
+void SurfaceMediaSource::passMetadataBufferLocked(MediaBuffer **buffer) {
+ LOGV("passMetadataBuffer");
+ // MediaBuffer allocates and owns this data
+ MediaBuffer *tempBuffer =
+ new MediaBuffer(4 + sizeof(buffer_handle_t));
+ char *data = (char *)tempBuffer->data();
+ if (data == NULL) {
+ LOGE("Cannot allocate memory for passing buffer metadata!");
+ return;
+ }
+ OMX_U32 type = kMetadataBufferTypeGrallocSource;
+ memcpy(data, &type, 4);
+ memcpy(data + 4, &(mCurrentBuf->handle), sizeof(buffer_handle_t));
+ *buffer = tempBuffer;
+}
+
+
void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
LOGV("signalBufferReturned");
Mutex::Autolock autoLock(mMutex);
if (!mStarted) {
- LOGV("started = false. Nothing to do");
+ LOGW("signalBufferReturned: mStarted = false! Nothing to do!");
return;
}
for (Fifo::iterator it = mQueue.begin(); it != mQueue.end(); ++it) {
- if (mSlots[*it].mGraphicBuffer == buffer->graphicBuffer()) {
- LOGV("Buffer %d returned. Setting it 'FREE'. New Queue size = %d",
- *it, mQueue.size()-1);
+ CHECK(mSlots[*it].mGraphicBuffer != NULL);
+ if (checkBufferMatchesSlot(*it, buffer)) {
mSlots[*it].mBufferState = BufferSlot::FREE;
mQueue.erase(it);
buffer->setObserver(0);
}
}
+bool SurfaceMediaSource::checkBufferMatchesSlot(int slot, MediaBuffer *buffer) {
+ LOGV("Check if Buffer matches slot");
+ // need to convert to char* for pointer arithmetic and then
+ // copy the byte stream into our handle
+ buffer_handle_t bufferHandle ;
+ memcpy( &bufferHandle, (char *)(buffer->data()) + 4, sizeof(buffer_handle_t));
+ return mSlots[slot].mGraphicBuffer->handle == bufferHandle;
+}
} // end of namespace android
mANW.clear();
}
- const int mYuvTexWidth;// = 64;
- const int mYuvTexHeight;// = 66;
+ const int mYuvTexWidth;
+ const int mYuvTexHeight;
sp<SurfaceMediaSource> mSMS;
sp<SurfaceTextureClient> mSTC;
// TODO: overwriting the colorformat since the format set by GRAlloc
// could be wrong or not be read by OMX
enc_meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
- // colorFormat);
sp<MediaSource> encoder =
ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
0, 0, HAL_PIXEL_FORMAT_YV12));
- // OMX_COLOR_FormatYUV420Planar)); // ));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
// setting the client side buffer size different than the server size
ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
10, 10, HAL_PIXEL_FORMAT_YV12));
- // OMX_COLOR_FormatYUV420Planar)); // ));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
0, 0, HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+
SimpleDummyRecorder writer(mSMS);
writer.start();
// A dummy writer is used to simulate actual MPEG4Writer
TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotMultiBufferPassLag) {
LOGV("Testing MultiBufferPass, Dummy Recorder Lagging **************");
+
ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
0, 0, HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+
SimpleDummyRecorder writer(mSMS);
writer.start();
TEST_F(SurfaceMediaSourceTest, DISABLED_EncodingFromCpuFilledYV12BufferNpotWrite) {
LOGV("Testing the whole pipeline with actual Recorder");
ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- 0, 0, HAL_PIXEL_FORMAT_YV12)); // OMX_COLOR_FormatYUV420Planar)); // ));
+ 0, 0, HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
-
OMXClient client;
CHECK_EQ(OK, client.connect());