[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid.changes
|
|
[-]
[+]
|
Changed |
_service:tar_git:gst-droid.spec
^
|
|
[-]
[+]
|
Changed |
_service
^
|
@@ -2,6 +2,6 @@
<service name="tar_git">
<param name="url">https://github.com/sailfishos/gst-droid.git</param>
<param name="branch">master</param>
- <param name="revision">a6ff1ba94af70125e979d3401d6e3e806a3792a4</param>
+ <param name="revision">e755c8521b3ff0a622fba4c85e57ff41015c7793</param>
</service>
</services>
\ No newline at end of file
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/.gitmodules
^
|
@@ -1,3 +1,3 @@
[submodule "common"]
path = common
- url = https://git.merproject.org/mirror/gstreamer-common.git
+ url = https://git.sailfishos.org/mirror/gstreamer-common.git
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/Makefile.am
^
|
@@ -1,3 +1,8 @@
SUBDIRS = common gst-libs gst tools
-EXTRA_DIST = autogen.sh
+EXTRA_DIST = autogen.sh \
+ gstreamer-droid-1.0.pc.in \
+ gstreamer-droid-1.0.pc
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = gstreamer-droid-1.0.pc
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/configure.ac
^
|
@@ -167,6 +167,7 @@
[GStreamer API Version])
AC_CONFIG_FILES([Makefile
+ gstreamer-droid-1.0.pc
common/Makefile
common/m4/Makefile
gst-libs/Makefile
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst-libs/gst/droid/Makefile.am
^
|
@@ -5,9 +5,13 @@
libgstdroid_@GST_API_VERSION@_la_includedir = \
$(includedir)/gstreamer-@GST_API_VERSION@/gst/allocators
-libgstdroid_@GST_API_VERSION@_la_CFLAGS = $(GST_CFLAGS) -I/usr/include/droidmedia/
+libgstdroid_@GST_API_VERSION@_la_CFLAGS = $(GST_CFLAGS) \
+ $(EGL_CFLAGS) \
+ -DEGL_NO_X11 \
+ -I/usr/include/droidmedia/
-libgstdroid_@GST_API_VERSION@_la_LIBADD = $(GST_LIBS)
+libgstdroid_@GST_API_VERSION@_la_LIBADD = $(GST_LIBS) \
+ $(EGL_LIBS)
noinst_HEADERS =
@@ -24,4 +28,4 @@
gstdroidmediabuffer.h \
gstdroidbufferpool.h \
gstdroidquery.h \
- gstdroidcodec.h
\ No newline at end of file
+ gstdroidcodec.h
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst-libs/gst/droid/gstdroidbufferpool.c
^
|
@@ -21,124 +21,314 @@
#include <gst/gst.h>
#include "gstdroidbufferpool.h"
+#include "gstdroidmediabuffer.h"
+/* Element signals and args */
+enum
+{
+ BUFFERS_INVALIDATED,
+ LAST_SIGNAL
+};
#define gst_droid_buffer_pool_parent_class parent_class
G_DEFINE_TYPE (GstDroidBufferPool, gst_droid_buffer_pool, GST_TYPE_BUFFER_POOL);
-static void
-gst_droid_buffer_pool_reset_buffer (GstBufferPool * pool, GstBuffer * buffer)
+static guint gst_droid_buffer_pool_signals[LAST_SIGNAL] = { 0 };
+
+static gboolean
+gst_droid_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
{
- GstDroidBufferPool *dpool = GST_DROID_BUFFER_POOL (pool);
+ GstCaps *caps;
+ guint size;
+ GstAllocationParams params = { GST_MEMORY_FLAG_NO_SHARE, 0, 0, 0 };
+ GstDroidBufferPool *pool = GST_DROID_BUFFER_POOL (bpool);
- gst_buffer_remove_all_memory (buffer);
- GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
+ if (!gst_buffer_pool_config_get_params (config, &caps, &size, NULL, NULL)) {
+ GST_WARNING_OBJECT (pool, "Invalid pool configuration");
+ return FALSE;
+ }
+ // If we have caps then we can create droid buffers
+ if (caps != NULL) {
+ GstCapsFeatures *features = gst_caps_get_features (caps, 0);
+
+ GST_OBJECT_LOCK (pool);
+
+ if (!gst_video_info_from_caps (&pool->video_info, caps)) {
+ GST_OBJECT_UNLOCK (pool);
+ GST_WARNING_OBJECT (pool, "Invalid video caps %" GST_PTR_FORMAT, caps);
+ return FALSE;
+ }
+
+ pool->video_info.size = size;
+ pool->use_queue_buffers = gst_caps_features_contains
+ (features, GST_CAPS_FEATURE_MEMORY_DROID_MEDIA_QUEUE_BUFFER);
+
+ GST_DEBUG_OBJECT (pool, "Configured pool. caps: %" GST_PTR_FORMAT, caps);
+ pool->allocator = gst_droid_media_buffer_allocator_new ();
+ gst_object_ref (pool->allocator);
+ gst_buffer_pool_config_set_allocator (config,
+ (GstAllocator *) pool->allocator, ¶ms);
+ GST_OBJECT_UNLOCK (pool);
+ }
+
+ return GST_BUFFER_POOL_CLASS (gst_droid_buffer_pool_parent_class)
+ ->set_config (bpool, config);
+}
- g_mutex_lock (&dpool->lock);
- ++dpool->num_buffers;
- GST_DEBUG_OBJECT (dpool, "num buffers: %d", dpool->num_buffers);
- g_cond_signal (&dpool->cond);
- g_mutex_unlock (&dpool->lock);
+static const gchar **
+gst_droid_buffer_pool_get_options (GstBufferPool * bpool)
+{
+ static const gchar *options[] = { GST_BUFFER_POOL_OPTION_VIDEO_META, NULL };
- return GST_BUFFER_POOL_CLASS (parent_class)->reset_buffer (pool, buffer);
+ return options;
}
static GstFlowReturn
-gst_droid_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
+gst_droid_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buf,
GstBufferPoolAcquireParams * params G_GNUC_UNUSED)
{
GstDroidBufferPool *dpool = GST_DROID_BUFFER_POOL (pool);
+ GstBuffer *buffer;
- *buffer = gst_buffer_new ();
- if (!*buffer) {
+ if (!dpool->allocator) {
return GST_FLOW_ERROR;
}
- g_mutex_lock (&dpool->lock);
- ++dpool->num_buffers;
- GST_DEBUG_OBJECT (dpool, "num buffers: %d", dpool->num_buffers);
- g_cond_signal (&dpool->cond);
- g_mutex_unlock (&dpool->lock);
+ buffer = gst_buffer_new ();
+ if (!buffer) {
+ return GST_FLOW_ERROR;
+ }
+
+ if (!dpool->use_queue_buffers) {
+ GstVideoInfo *video_info;
+ GstMemory *memory =
+ gst_droid_media_buffer_allocator_alloc_new (dpool->allocator,
+ &dpool->video_info);
+ if (!memory) {
+ gst_buffer_unref (buffer);
+ return GST_FLOW_ERROR;
+ }
+
+ gst_buffer_insert_memory (buffer, 0, memory);
+
+ video_info = gst_droid_media_buffer_get_video_info (memory);
+
+ gst_buffer_add_video_meta_full (buffer,
+ GST_VIDEO_FRAME_FLAG_NONE, video_info->finfo->format,
+ video_info->width, video_info->height,
+ video_info->finfo->n_planes, video_info->offset, video_info->stride);
+ }
+
+ *buf = buffer;
return GST_FLOW_OK;
}
-gboolean
-gst_droid_buffer_pool_wait_for_buffer (GstBufferPool * pool)
+static void
+gst_droid_buffer_release_buffer (GstBufferPool * pool, GstBuffer * buffer)
{
GstDroidBufferPool *dpool = GST_DROID_BUFFER_POOL (pool);
+ DroidMediaBuffer *droid_buffer = NULL;
- if (GST_BUFFER_POOL_IS_FLUSHING (pool)) {
- return FALSE;
+ if (dpool->use_queue_buffers) {
+ guint index;
+
+ g_mutex_lock (&dpool->binding_lock);
+
+ if (g_ptr_array_find (dpool->acquired_buffers, buffer, &index)) {
+ g_ptr_array_remove_index_fast (dpool->acquired_buffers, index);
+
+ droid_buffer =
+ gst_droid_media_buffer_memory_get_buffer_from_gst_buffer (buffer);
+
+ if (droid_media_buffer_get_user_data (droid_buffer) == buffer) {
+ g_ptr_array_add (dpool->bound_buffers, buffer);
+ } else {
+ droid_buffer = NULL;
+ }
+ }
+
+ g_mutex_unlock (&dpool->binding_lock);
+ }
+
+ if (droid_buffer) {
+ buffer->pool = gst_object_ref (pool);
+
+ droid_media_buffer_release (droid_buffer, dpool->display, NULL);
+ } else {
+ if (dpool->use_queue_buffers) {
+ gst_buffer_remove_all_memory (buffer);
+ GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
+ }
+
+ GST_BUFFER_POOL_CLASS (parent_class)->release_buffer (pool, buffer);
+ }
+}
+
+void
+gst_droid_buffer_pool_set_egl_display (GstBufferPool * pool, EGLDisplay display)
+{
+ GstDroidBufferPool *dpool = GST_DROID_BUFFER_POOL (pool);
+
+ if (dpool) {
+ dpool->display = display;
}
+}
- g_mutex_lock (&dpool->lock);
+gboolean
+gst_droid_buffer_pool_bind_media_buffer (GstBufferPool * pool,
+ DroidMediaBuffer * buffer)
+{
+ GstDroidBufferPool *dpool;
+ GstBuffer *gst_buffer;
+ GstMemory *mem;
+
+ if (!GST_IS_DROID_BUFFER_POOL (pool)) {
+ return FALSE;
+ }
- if (dpool->num_buffers > 0) {
- g_mutex_unlock (&dpool->lock);
- return TRUE;
+ if (gst_buffer_pool_acquire_buffer (pool, &gst_buffer, NULL) != GST_FLOW_OK) {
+ return FALSE;
}
- g_cond_wait (&dpool->cond, &dpool->lock);
- g_mutex_unlock (&dpool->lock);
+ dpool = GST_DROID_BUFFER_POOL (pool);
+
+ mem =
+ gst_droid_media_buffer_allocator_alloc_from_buffer (dpool->allocator,
+ buffer);
+
+ if (!mem) {
+ gst_buffer_unref (gst_buffer);
- if (GST_BUFFER_POOL_IS_FLUSHING (pool)) {
return FALSE;
}
+ gst_buffer_insert_memory (gst_buffer, 0, mem);
+
+ g_mutex_lock (&dpool->binding_lock);
+
+ droid_media_buffer_set_user_data (buffer, gst_buffer);
+
+ g_ptr_array_add (dpool->bound_buffers, gst_buffer);
+
+ g_mutex_unlock (&dpool->binding_lock);
+
return TRUE;
}
static void
-gst_droid_buffer_pool_flush_start (GstBufferPool * pool)
+gst_droid_buffer_pool_clear_buffers_user_data (GPtrArray * buffers)
{
- GstDroidBufferPool *dpool = GST_DROID_BUFFER_POOL (pool);
+ guint i;
- g_mutex_lock (&dpool->lock);
- g_cond_signal (&dpool->cond);
- g_mutex_unlock (&dpool->lock);
+ for (i = 0; i < buffers->len; ++i) {
+ DroidMediaBuffer *buffer =
+ gst_droid_media_buffer_memory_get_buffer_from_gst_buffer ((GstBuffer *)
+ g_ptr_array_index (buffers, i));
+
+ if (buffer) {
+ droid_media_buffer_set_user_data (buffer, NULL);
+ }
+ }
}
-static GstFlowReturn
-gst_droid_buffer_pool_acquire_buffer (GstBufferPool * pool, GstBuffer ** buffer,
- GstBufferPoolAcquireParams * params)
+GstBuffer *
+gst_droid_buffer_pool_acquire_media_buffer (GstBufferPool * pool,
+ DroidMediaBuffer * buffer)
{
+ guint index;
+ GstBuffer *gst_buffer = NULL;
GstDroidBufferPool *dpool = GST_DROID_BUFFER_POOL (pool);
- GstFlowReturn ret;
- ret =
- GST_BUFFER_POOL_CLASS (parent_class)->acquire_buffer (pool, buffer,
- params);
+ if (!dpool) {
+ return NULL;
+ }
+
+ g_mutex_lock (&dpool->binding_lock);
+
+ gst_buffer = (GstBuffer *) droid_media_buffer_get_user_data (buffer);
+
+ if (gst_buffer->pool != pool) {
+ droid_media_buffer_set_user_data (buffer, NULL);
+
+ g_mutex_unlock (&dpool->binding_lock);
+
+ if (!gst_droid_buffer_pool_bind_media_buffer (pool, buffer)) {
+ return NULL;
+ }
+
+ if (gst_buffer) {
+ gst_buffer_unref (gst_buffer);
+ }
+
+ g_mutex_lock (&dpool->binding_lock);
+
+ gst_buffer = (GstBuffer *) droid_media_buffer_get_user_data (buffer);
+ }
+
+ if (gst_buffer && g_ptr_array_find (dpool->bound_buffers, gst_buffer, &index)) {
+ g_ptr_array_remove_index_fast (dpool->bound_buffers, index);
- if (G_LIKELY (ret == GST_FLOW_OK)) {
- g_mutex_lock (&dpool->lock);
- --dpool->num_buffers;
- GST_DEBUG_OBJECT (dpool, "num buffers: %d", dpool->num_buffers);
- g_mutex_unlock (&dpool->lock);
+ g_ptr_array_add (dpool->acquired_buffers, gst_buffer);
}
- return ret;
+ g_mutex_unlock (&dpool->binding_lock);
+
+ return gst_buffer;
}
-static gboolean
-gst_droid_buffer_pool_start (GstBufferPool * pool)
+void
+gst_droid_buffer_pool_media_buffers_invalidated (GstBufferPool * pool)
{
- GstDroidBufferPool *dpool = GST_DROID_BUFFER_POOL (pool);
+ GPtrArray *buffers_to_release = NULL;
+ guint i;
+ GstDroidBufferPool *dpool;
+
+ if (!pool || !GST_IS_DROID_BUFFER_POOL (pool)) {
+ GST_WARNING_OBJECT (pool, "Pool is not a GstDroidBufferPool");
+ return;
+ }
+
+ dpool = GST_DROID_BUFFER_POOL (pool);
+
+ g_mutex_lock (&dpool->binding_lock);
+
+ gst_droid_buffer_pool_clear_buffers_user_data (dpool->bound_buffers);
+ gst_droid_buffer_pool_clear_buffers_user_data (dpool->acquired_buffers);
+
+ if (dpool->bound_buffers->len != 0) {
+ buffers_to_release = dpool->bound_buffers;
- g_mutex_lock (&dpool->lock);
- dpool->num_buffers = 0;
- GST_DEBUG_OBJECT (dpool, "num buffers: %d", dpool->num_buffers);
- g_mutex_unlock (&dpool->lock);
+ dpool->bound_buffers = g_ptr_array_new ();
+ }
+
+ g_ptr_array_set_size (dpool->acquired_buffers, 0);
+
+ g_mutex_unlock (&dpool->binding_lock);
+
+ if (buffers_to_release) {
+ for (i = 0; i < buffers_to_release->len; ++i) {
+ gst_buffer_unref ((GstBuffer *) g_ptr_array_index (buffers_to_release,
+ i));
+ }
+ g_ptr_array_free (buffers_to_release, TRUE);
+ }
- return GST_BUFFER_POOL_CLASS (parent_class)->start (pool);
+ g_signal_emit (pool, gst_droid_buffer_pool_signals[BUFFERS_INVALIDATED], 0);
}
static void
gst_droid_buffer_pool_finalize (GObject * object)
{
GstDroidBufferPool *pool = GST_DROID_BUFFER_POOL (object);
+ if (pool->allocator) {
+ gst_object_unref (pool->allocator);
+ pool->allocator = 0;
+ }
+
+ g_ptr_array_free (pool->bound_buffers, TRUE);
+ g_ptr_array_free (pool->acquired_buffers, TRUE);
- g_mutex_clear (&pool->lock);
- g_cond_clear (&pool->cond);
+ g_mutex_clear (&pool->binding_lock);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -150,18 +340,30 @@
GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
gobject_class->finalize = gst_droid_buffer_pool_finalize;
- gstbufferpool_class->start = gst_droid_buffer_pool_start;
- gstbufferpool_class->acquire_buffer = gst_droid_buffer_pool_acquire_buffer;
- gstbufferpool_class->reset_buffer = gst_droid_buffer_pool_reset_buffer;
gstbufferpool_class->alloc_buffer = gst_droid_buffer_pool_alloc;
- gstbufferpool_class->flush_start = gst_droid_buffer_pool_flush_start;
+ gstbufferpool_class->release_buffer = gst_droid_buffer_release_buffer;
+ gstbufferpool_class->get_options = gst_droid_buffer_pool_get_options;
+ gstbufferpool_class->set_config = gst_droid_buffer_pool_set_config;
+
+ gst_droid_buffer_pool_signals[BUFFERS_INVALIDATED] =
+ g_signal_new ("buffers-invalidated",
+ G_TYPE_FROM_CLASS (gstbufferpool_class), G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GstDroidBufferPoolClass, signal_buffers_invalidated),
+ NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 0);
}
static void
-gst_droid_buffer_pool_init (GstDroidBufferPool * pool G_GNUC_UNUSED)
+gst_droid_buffer_pool_init (GstDroidBufferPool * object)
{
- g_mutex_init (&pool->lock);
- g_cond_init (&pool->cond);
+ GstDroidBufferPool *pool = GST_DROID_BUFFER_POOL (object);
+ pool->allocator = 0;
+
+ g_mutex_init (&pool->binding_lock);
+
+ pool->bound_buffers = g_ptr_array_new ();
+ pool->acquired_buffers = g_ptr_array_new ();
+ pool->use_queue_buffers = FALSE;
+ pool->display = NULL;
}
GstBufferPool *
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst-libs/gst/droid/gstdroidbufferpool.h
^
|
@@ -23,12 +23,16 @@
#define __GST_DROID_BUFFER_POOL_H__
#include <gst/gstbufferpool.h>
+#include <gst/video/video-info.h>
+#include <droidmedia/droidmedia.h>
G_BEGIN_DECLS
typedef struct _GstDroidBufferPool GstDroidBufferPool;
typedef struct _GstDroidBufferPoolClass GstDroidBufferPoolClass;
+typedef void *EGLDisplay;
+
#define GST_TYPE_DROID_BUFFER_POOL (gst_droid_buffer_pool_get_type())
#define GST_IS_DROID_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DROID_BUFFER_POOL))
#define GST_DROID_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DROID_BUFFER_POOL, GstDroidBufferPool))
@@ -37,19 +41,31 @@
struct _GstDroidBufferPool
{
GstBufferPool parent;
- GMutex lock;
- GCond cond;
- gint num_buffers;
+ GstAllocator *allocator;
+ GstVideoInfo video_info;
+ GPtrArray *bound_buffers;
+ GPtrArray *acquired_buffers;
+ GMutex binding_lock;
+ EGLDisplay display;
+ gboolean use_queue_buffers;
};
struct _GstDroidBufferPoolClass
{
GstBufferPoolClass parent_class;
+
+ void (*signal_buffers_invalidated) (GstDroidBufferPool *pool);
};
GType gst_droid_buffer_pool_get_type (void);
GstBufferPool * gst_droid_buffer_pool_new (void);
-gboolean gst_droid_buffer_pool_wait_for_buffer (GstBufferPool * pool);
+
+void gst_droid_buffer_pool_set_egl_display (GstBufferPool *pool, EGLDisplay display);
+gboolean gst_droid_buffer_pool_bind_media_buffer (GstBufferPool *pool,
+ DroidMediaBuffer *buffer);
+void gst_droid_buffer_pool_media_buffers_invalidated (GstBufferPool *pool);
+GstBuffer *gst_droid_buffer_pool_acquire_media_buffer (GstBufferPool *pool,
+ DroidMediaBuffer *buffer);
G_END_DECLS
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst-libs/gst/droid/gstdroidcodec.c
^
|
@@ -31,28 +31,32 @@
#endif /* GST_USE_UNSTABLE_API */
#include <gst/codecparsers/gsth264parser.h>
-GST_DEBUG_CATEGORY_EXTERN (gst_droid_codec_debug);
+GST_DEBUG_CATEGORY (gst_droid_codec_debug);
#define GST_CAT_DEFAULT gst_droid_codec_debug
static GstBuffer *create_mpeg4venc_codec_data (DroidMediaData * data);
static GstBuffer *create_h264enc_codec_data (DroidMediaData * data);
static gboolean create_mpeg4vdec_codec_data_from_codec_data (GstDroidCodec *
codec, GstBuffer * data, DroidMediaData * out);
+static gboolean
+create_mpeg2vdec_codec_data_from_codec_data (GstDroidCodec *
+ codec G_GNUC_UNUSED, GstBuffer * data, DroidMediaData * out);
static gboolean create_h264dec_codec_data_from_codec_data (GstDroidCodec *
codec, GstBuffer * data, DroidMediaData * out);
-static gboolean create_vp8vdec_codec_data_from_codec_data (GstDroidCodec *
+static gboolean create_h265dec_codec_data_from_codec_data (GstDroidCodec *
codec, GstBuffer * data, DroidMediaData * out);
static gboolean create_aacdec_codec_data_from_codec_data (GstDroidCodec * codec,
GstBuffer * data, DroidMediaData * out);
static gboolean create_aacdec_codec_data_from_frame_data (GstDroidCodec * codec,
GstBuffer * frame_data, DroidMediaData * out);
-static gboolean process_h264dec_data (GstDroidCodec * codec, GstBuffer * buffer,
+static gboolean ignore_codec_data (GstDroidCodec * codec, GstBuffer * data,
+ DroidMediaData * out);
+static gboolean process_h26xdec_data (GstDroidCodec * codec, GstBuffer * buffer,
DroidMediaData * out);
static gboolean process_aacdec_data (GstDroidCodec * codec, GstBuffer * buffer,
DroidMediaData * out);
static gboolean is_mpeg4v (GstDroidCodec * codec, const GstStructure * s);
static gboolean is_mpega (GstDroidCodec * codec, const GstStructure * s);
-static gboolean is_mp3 (GstDroidCodec * codec, const GstStructure * s);
static gboolean is_h264_dec (GstDroidCodec * codec, const GstStructure * s);
static gboolean is_h264_enc (GstDroidCodec * codec, const GstStructure * s);
static void h264enc_complement (GstCaps * caps);
@@ -109,9 +113,13 @@
is_mpega, NULL, NULL, NULL, create_aacdec_codec_data_from_codec_data,
create_aacdec_codec_data_from_frame_data, process_aacdec_data},
- {GST_DROID_CODEC_DECODER_AUDIO, "audio/mpeg", "audio/mpeg",
- "audio/mpeg, mpegversion=(int)1, layer=[1, 3]", TRUE,
- is_mp3, NULL, NULL, NULL, NULL, NULL, NULL},
+ {GST_DROID_CODEC_DECODER_AUDIO, "audio/AMR", "audio/3gpp",
+ "audio/AMR", FALSE, NULL, NULL, NULL, NULL,
+ ignore_codec_data, NULL, NULL},
+
+ {GST_DROID_CODEC_DECODER_AUDIO, "audio/AMR-WB", "audio/amr-wb",
+ "audio/AMR-WB", FALSE, NULL, NULL, NULL, NULL,
+ ignore_codec_data, NULL, NULL},
/* video decoders */
{GST_DROID_CODEC_DECODER_VIDEO, "video/mpeg", "video/mp4v-es",
@@ -122,15 +130,26 @@
{GST_DROID_CODEC_DECODER_VIDEO, "video/x-h264", "video/avc",
"video/x-h264, stream-format=avc,alignment=au", TRUE,
is_h264_dec, NULL, NULL, NULL,
- create_h264dec_codec_data_from_codec_data, NULL, process_h264dec_data},
+ create_h264dec_codec_data_from_codec_data, NULL, process_h26xdec_data},
{GST_DROID_CODEC_DECODER_VIDEO, "video/x-h263", "video/3gpp",
"video/x-h263", TRUE, NULL,
NULL, NULL, NULL, NULL, NULL, NULL},
{GST_DROID_CODEC_DECODER_VIDEO, "video/x-vp8", "video/x-vnd.on2.vp8",
- "video/x-vp8", FALSE, NULL, NULL, NULL, NULL,
- create_vp8vdec_codec_data_from_codec_data, NULL, NULL},
+ "video/x-vp8", TRUE, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+
+ {GST_DROID_CODEC_DECODER_VIDEO, "video/x-vp9", "video/x-vnd.on2.vp9",
+ "video/x-vp9", TRUE, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+
+ {GST_DROID_CODEC_DECODER_VIDEO, "video/mpeg", "video/mpeg2",
+ "video/mpeg, mpegversion=2", TRUE,
+ NULL, NULL, NULL, NULL,
+ create_mpeg2vdec_codec_data_from_codec_data, NULL, NULL},
+
+ {GST_DROID_CODEC_DECODER_VIDEO, "video/x-h265", "video/hevc",
+ "video/x-h265", FALSE, NULL, NULL, NULL, NULL,
+ create_h265dec_codec_data_from_codec_data, NULL, process_h26xdec_data},
/* audio encoders */
{GST_DROID_CODEC_ENCODER_AUDIO, "audio/mpeg", "audio/mp4a-latm",
@@ -222,6 +241,20 @@
continue;
}
+ /* Verify that video codec is supported before enabling it */
+ if (type == GST_DROID_CODEC_DECODER_VIDEO
+ || type == GST_DROID_CODEC_ENCODER_VIDEO) {
+ DroidMediaCodecMetaData md;
+ md.type = codecs[x].droid;
+ md.flags = DROID_MEDIA_CODEC_HW_ONLY;
+ if (!droid_media_codec_is_supported (&md,
+ type == GST_DROID_CODEC_ENCODER_VIDEO)) {
+ GST_INFO ("No hardware support found for %s, disabling codec",
+ codecs[x].droid);
+ continue;
+ }
+ }
+
s = gst_structure_new_from_string (codecs[x].caps);
caps = gst_caps_merge_structure (caps, s);
}
@@ -586,15 +619,6 @@
}
static gboolean
-is_mp3 (GstDroidCodec * codec G_GNUC_UNUSED, const GstStructure * s)
-{
- gint val, layer;
-
- return gst_structure_get_int (s, "mpegversion", &val) && val == 1 &&
- gst_structure_get_int (s, "layer", &layer) && (layer == 1 || layer == 3);
-}
-
-static gboolean
is_h264_dec (GstDroidCodec * codec G_GNUC_UNUSED, const GstStructure * s)
{
const char *alignment = gst_structure_get_string (s, "alignment");
@@ -631,6 +655,16 @@
}
static gboolean
+create_mpeg2vdec_codec_data_from_codec_data (GstDroidCodec *
+ codec G_GNUC_UNUSED, GstBuffer * data G_GNUC_UNUSED, DroidMediaData * out)
+{
+ out->size = 0;
+ out->data = NULL;
+
+ return TRUE;
+}
+
+static gboolean
create_mpeg4vdec_codec_data_from_codec_data (GstDroidCodec *
codec G_GNUC_UNUSED, GstBuffer * data, DroidMediaData * out)
{
@@ -691,7 +725,7 @@
}
static gboolean
-create_vp8vdec_codec_data_from_codec_data (GstDroidCodec * codec,
+create_h264dec_codec_data_from_codec_data (GstDroidCodec * codec,
GstBuffer * data, DroidMediaData * out)
{
GstMapInfo info;
@@ -707,6 +741,10 @@
goto out;
}
+ codec->data->h264_nal = (1 + (info.data[4] & 3));
+
+ GST_INFO ("nal prefix length %d", codec->data->h264_nal);
+
out->size = info.size;
out->data = g_malloc (info.size);
memcpy (out->data, info.data, info.size);
@@ -719,7 +757,7 @@
}
static gboolean
-create_h264dec_codec_data_from_codec_data (GstDroidCodec * codec,
+create_h265dec_codec_data_from_codec_data (GstDroidCodec * codec,
GstBuffer * data, DroidMediaData * out)
{
GstMapInfo info;
@@ -735,7 +773,7 @@
goto out;
}
- codec->data->h264_nal = (1 + (info.data[4] & 3));
+ codec->data->h264_nal = (1 + (info.data[21] & 3));
GST_INFO ("nal prefix length %d", codec->data->h264_nal);
@@ -902,7 +940,16 @@
}
static gboolean
-process_h264dec_data (GstDroidCodec * codec, GstBuffer * buffer,
+ignore_codec_data (GstDroidCodec * codec G_GNUC_UNUSED,
+ GstBuffer * data G_GNUC_UNUSED, DroidMediaData * out G_GNUC_UNUSED)
+{
+ /* Some containers have codec_data which can be ignored */
+ GST_WARNING ("Ignoring codec data");
+ return TRUE;
+}
+
+static gboolean
+process_h26xdec_data (GstDroidCodec * codec, GstBuffer * buffer,
DroidMediaData * out)
{
GstMapInfo info;
@@ -1086,6 +1133,7 @@
|| codec->info->type ==
GST_DROID_CODEC_DECODER_VIDEO) ? "decoder-quirks" : "encoder-quirks";
gsize quirks_length = 0;
+ codec->quirks = 0;
int x;
g_key_file_load_from_file (file, path, G_KEY_FILE_NONE, NULL);
@@ -1109,6 +1157,8 @@
codec->quirks |= USE_CODEC_SUPPLIED_HEIGHT_VALUE;
} else if (!g_strcmp0 (quirks_string[x], USE_CODEC_SUPPLIED_WIDTH_NAME)) {
codec->quirks |= USE_CODEC_SUPPLIED_WIDTH_VALUE;
+ } else if (!g_strcmp0 (quirks_string[x], DONT_USE_DROID_CONVERT_NAME)) {
+ codec->quirks |= DONT_USE_DROID_CONVERT_VALUE;
}
}
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst-libs/gst/droid/gstdroidcodec.h
^
|
@@ -35,6 +35,9 @@
#define USE_CODEC_SUPPLIED_WIDTH_NAME "use-codec-supplied-width"
#define USE_CODEC_SUPPLIED_WIDTH_VALUE 0x2
+#define DONT_USE_DROID_CONVERT_NAME "dont-use-droid-convert"
+#define DONT_USE_DROID_CONVERT_VALUE 0x4
+
typedef struct _GstDroidCodec GstDroidCodec;
typedef struct _GstDroidCodecInfo GstDroidCodecInfo;
typedef struct _GstDroidCodecPrivate GstDroidCodecPrivate;
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst-libs/gst/droid/gstdroidmediabuffer.c
^
|
@@ -25,6 +25,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <gst/gst.h>
+#include <gst/interfaces/nemoeglimagememory.h>
#include "gstdroidmediabuffer.h"
#include "droidmediaconstants.h"
@@ -33,14 +34,15 @@
typedef struct
{
- GstAllocator parent;
+ NemoGstEglImageAllocator parent;
- DroidMediaPixelFormatConstants c;
} GstDroidMediaBufferAllocator;
typedef struct
{
- GstAllocatorClass parent_class;
+ NemoGstEglImageAllocatorClass parent_class;
+
+ PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr;
} GstDroidMediaBufferAllocatorClass;
@@ -49,22 +51,167 @@
GstMemory mem;
DroidMediaBuffer *buffer;
+ GstVideoInfo video_info;
+ gpointer map_data;
+ int map_count;
+ GstMapFlags map_flags;
} GstDroidMediaBufferMemory;
+typedef struct
+{
+ int hal_format;
+ GstVideoFormat gst_format;
+ int bytes_per_pixel;
+ int h_align;
+ int v_align;
+
+} GstDroidMediaBufferFormatMap;
+
#define _do_init \
GST_DEBUG_CATEGORY_INIT (droid_memory_debug, "droidmemory", 0, \
"droid memory allocator");
G_DEFINE_TYPE_WITH_CODE (GstDroidMediaBufferAllocator,
- droid_media_buffer_allocator, GST_TYPE_ALLOCATOR, _do_init);
+ droid_media_buffer_allocator, NEMO_GST_TYPE_EGL_IMAGE_ALLOCATOR, _do_init);
#define GST_TYPE_DROID_MEDIA_BUFFER_ALLOCATOR (droid_media_buffer_allocator_get_type())
#define GST_IS_DROID_MEDIA_BUFFER_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DROID_MEDIA_BUFFER_ALLOCATOR))
+#define GST_DROID_MEDIA_BUFFER_ALLOCATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DROID_MEDIA_BUFFER_ALLOCATOR, GstDroidMediaBufferAllocatorClass))
static void gst_droid_media_buffer_allocator_free (GstAllocator * allocator,
GstMemory * mem);
+static gpointer gst_droid_media_buffer_memory_map (GstMemory * mem,
+ gsize maxsize, GstMapFlags flags);
+static void gst_droid_media_buffer_memory_unmap (GstMemory * mem);
+
+static EGLImageKHR gst_droid_media_buffer_create_image (GstMemory * mem,
+ EGLDisplay dpy, EGLContext ctx);
+
+#define GST_DROID_MEDIA_BUFFER_FORMAT_COUNT 11
+
+static GstDroidMediaBufferFormatMap
+ gst_droid_media_buffer_formats[GST_DROID_MEDIA_BUFFER_FORMAT_COUNT];
+
+static void
+gst_droid_media_buffer_initialize_format_map ()
+{
+ DroidMediaPixelFormatConstants constants;
+ static gboolean initialized = FALSE;
+
+ if (!initialized) {
+ droid_media_pixel_format_constants_init (&constants);
+
+ gst_droid_media_buffer_formats[0].hal_format =
+ constants.HAL_PIXEL_FORMAT_RGBA_8888;
+ gst_droid_media_buffer_formats[0].gst_format = GST_VIDEO_FORMAT_RGBA;
+ gst_droid_media_buffer_formats[0].bytes_per_pixel = 4;
+ gst_droid_media_buffer_formats[0].h_align = 4;
+ gst_droid_media_buffer_formats[0].v_align = 1;
+
+ gst_droid_media_buffer_formats[1].hal_format =
+ constants.HAL_PIXEL_FORMAT_RGBX_8888;
+ gst_droid_media_buffer_formats[1].gst_format = GST_VIDEO_FORMAT_RGBx;
+ gst_droid_media_buffer_formats[1].bytes_per_pixel = 4;
+ gst_droid_media_buffer_formats[1].h_align = 4;
+ gst_droid_media_buffer_formats[1].v_align = 1;
+
+ gst_droid_media_buffer_formats[2].hal_format =
+ constants.HAL_PIXEL_FORMAT_RGB_888;
+ gst_droid_media_buffer_formats[2].gst_format = GST_VIDEO_FORMAT_RGB;
+ gst_droid_media_buffer_formats[2].bytes_per_pixel = 3;
+ gst_droid_media_buffer_formats[2].h_align = 4;
+ gst_droid_media_buffer_formats[2].v_align = 1;
+
+ gst_droid_media_buffer_formats[3].hal_format =
+ constants.HAL_PIXEL_FORMAT_RGB_565;
+ gst_droid_media_buffer_formats[3].gst_format = GST_VIDEO_FORMAT_RGB16;
+ gst_droid_media_buffer_formats[3].bytes_per_pixel = 2;
+ gst_droid_media_buffer_formats[3].h_align = 4;
+ gst_droid_media_buffer_formats[3].v_align = 1;
+
+ gst_droid_media_buffer_formats[4].hal_format =
+ constants.HAL_PIXEL_FORMAT_BGRA_8888;
+ gst_droid_media_buffer_formats[4].gst_format = GST_VIDEO_FORMAT_BGRA;
+ gst_droid_media_buffer_formats[4].bytes_per_pixel = 4;
+ gst_droid_media_buffer_formats[4].h_align = 4;
+ gst_droid_media_buffer_formats[4].v_align = 1;
+
+ gst_droid_media_buffer_formats[5].hal_format =
+ constants.HAL_PIXEL_FORMAT_YV12;
+ gst_droid_media_buffer_formats[5].gst_format = GST_VIDEO_FORMAT_YV12;
+ gst_droid_media_buffer_formats[5].bytes_per_pixel = 1;
+ gst_droid_media_buffer_formats[5].h_align = 16;
+ gst_droid_media_buffer_formats[5].v_align = 1;
+
+ gst_droid_media_buffer_formats[6].hal_format =
+ constants.HAL_PIXEL_FORMAT_YCbCr_422_SP;
+ gst_droid_media_buffer_formats[6].gst_format = GST_VIDEO_FORMAT_NV16;
+ gst_droid_media_buffer_formats[6].bytes_per_pixel = 1;
+ gst_droid_media_buffer_formats[6].h_align = 1;
+ gst_droid_media_buffer_formats[6].v_align = 1;
+
+ gst_droid_media_buffer_formats[7].hal_format =
+ constants.HAL_PIXEL_FORMAT_YCrCb_420_SP;
+ gst_droid_media_buffer_formats[7].gst_format = GST_VIDEO_FORMAT_NV21;
+ gst_droid_media_buffer_formats[7].bytes_per_pixel = 1;
+ gst_droid_media_buffer_formats[7].h_align = 1;
+ gst_droid_media_buffer_formats[7].v_align = 1;
+
+ gst_droid_media_buffer_formats[8].hal_format =
+ constants.HAL_PIXEL_FORMAT_YCbCr_422_I;
+ gst_droid_media_buffer_formats[8].gst_format = GST_VIDEO_FORMAT_YUY2;
+ gst_droid_media_buffer_formats[8].bytes_per_pixel = 1;
+ gst_droid_media_buffer_formats[8].h_align = 1;
+ gst_droid_media_buffer_formats[8].v_align = 1;
+
+ gst_droid_media_buffer_formats[9].hal_format =
+ constants.QOMX_COLOR_FormatYUV420PackedSemiPlanar32m;
+ gst_droid_media_buffer_formats[9].gst_format = GST_VIDEO_FORMAT_YV12;
+ gst_droid_media_buffer_formats[9].bytes_per_pixel = 1;
+ gst_droid_media_buffer_formats[9].h_align = 128;
+ gst_droid_media_buffer_formats[9].v_align = 32;
+
+ gst_droid_media_buffer_formats[10].hal_format =
+ constants.QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka;
+ gst_droid_media_buffer_formats[10].gst_format = GST_VIDEO_FORMAT_NV12_64Z32;
+ gst_droid_media_buffer_formats[10].bytes_per_pixel = 0;
+ gst_droid_media_buffer_formats[10].h_align = 0;
+ gst_droid_media_buffer_formats[10].v_align = 0;
+ }
+}
+
+static int
+gst_droid_media_buffer_index_of_hal_format (int format)
+{
+ int i;
+
+ gst_droid_media_buffer_initialize_format_map ();
+
+ for (i = 0; i < GST_DROID_MEDIA_BUFFER_FORMAT_COUNT; ++i) {
+ if (gst_droid_media_buffer_formats[i].hal_format == format) {
+ return i;
+ }
+ }
+ return GST_DROID_MEDIA_BUFFER_FORMAT_COUNT;
+}
+
+static int
+gst_droid_media_buffer_index_of_gst_format (GstVideoFormat format)
+{
+ int i;
+
+ gst_droid_media_buffer_initialize_format_map ();
+
+ for (i = 0; i < GST_DROID_MEDIA_BUFFER_FORMAT_COUNT; ++i) {
+ if (gst_droid_media_buffer_formats[i].gst_format == format) {
+ return i;
+ }
+ }
+ return GST_DROID_MEDIA_BUFFER_FORMAT_COUNT;
+}
+
GstAllocator *
gst_droid_media_buffer_allocator_new (void)
{
@@ -75,39 +222,104 @@
droid_media_buffer_allocator_init (GstDroidMediaBufferAllocator * allocator)
{
GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
+ NemoGstEglImageAllocator *egl_alloc =
+ NEMO_GST_EGL_IMAGE_ALLOCATOR_CAST (allocator);
GST_DEBUG_OBJECT (alloc, "init");
alloc->mem_type = GST_ALLOCATOR_DROID_MEDIA_BUFFER;
- alloc->mem_map = NULL;
- alloc->mem_unmap = NULL;
+ alloc->mem_map = gst_droid_media_buffer_memory_map;
+ alloc->mem_unmap = gst_droid_media_buffer_memory_unmap;
alloc->mem_copy = NULL;
alloc->mem_share = NULL;
alloc->mem_is_span = NULL;
- droid_media_pixel_format_constants_init (&allocator->c);
+ egl_alloc->create_image = gst_droid_media_buffer_create_image;
GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
}
+#define ALIGN_SIZE(size, to) (((size) + to - 1) & ~(to - 1))
+
static void
droid_media_buffer_allocator_class_init (GstDroidMediaBufferAllocatorClass *
klass)
{
GstAllocatorClass *allocator_class = (GstAllocatorClass *) klass;
+ klass->egl_create_image_khr =
+ (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress ("eglCreateImageKHR");
+
allocator_class->alloc = NULL;
allocator_class->free = gst_droid_media_buffer_allocator_free;
}
-GstMemory *
+static GstDroidMediaBufferMemory *
gst_droid_media_buffer_allocator_alloc (GstAllocator * allocator,
- DroidMediaBufferQueue * queue, DroidMediaBufferCallbacks * cb)
+ DroidMediaBuffer * buffer, int format_index, gsize width, gsize height,
+ gsize stride, gsize size)
+{
+ GstDroidMediaBufferMemory *mem = g_slice_new0 (GstDroidMediaBufferMemory);
+ GstFormat format;
+ gsize padded_width = width;
+ gsize padded_height = height;
+
+ mem->buffer = buffer;
+ mem->map_data = NULL;
+ mem->map_flags = 0;
+ mem->map_count = 0;
+
+ if (format_index == GST_DROID_MEDIA_BUFFER_FORMAT_COUNT) {
+ format = GST_VIDEO_FORMAT_ENCODED;
+ } else {
+ format = gst_droid_media_buffer_formats[format_index].gst_format;
+ if (gst_droid_media_buffer_formats[format_index].bytes_per_pixel != 0) {
+ stride =
+ stride * gst_droid_media_buffer_formats[format_index].bytes_per_pixel;
+ padded_width =
+ ALIGN_SIZE (stride,
+ gst_droid_media_buffer_formats[format_index].h_align) /
+ gst_droid_media_buffer_formats[format_index].bytes_per_pixel;
+ padded_height =
+ ALIGN_SIZE (height,
+ gst_droid_media_buffer_formats[format_index].v_align);
+ }
+ }
+
+ gst_video_info_set_format (&mem->video_info, format, padded_width,
+ padded_height);
+ mem->video_info.width = width;
+ mem->video_info.height = height;
+ mem->video_info.size = size;
+
+ // Android YV12 requires alignment of the UV stride too.
+ // So we need to reset the gst UV strides and offsets.
+ if (gst_droid_media_buffer_formats[format_index].gst_format ==
+ GST_VIDEO_FORMAT_YV12) {
+ gsize uvStride = ALIGN_SIZE (stride / 2,
+ gst_droid_media_buffer_formats[format_index].h_align);
+ mem->video_info.stride[1] = uvStride;
+ mem->video_info.stride[2] = uvStride;
+ mem->video_info.offset[1] = stride * padded_height *
+ gst_droid_media_buffer_formats[format_index].bytes_per_pixel;
+ mem->video_info.offset[2] =
+ mem->video_info.offset[1] + uvStride * padded_height / 2;
+ }
+
+ gst_memory_init (GST_MEMORY_CAST (mem),
+ GST_MEMORY_FLAG_NO_SHARE, GST_ALLOCATOR (allocator), NULL,
+ mem->video_info.size, 0, 0, mem->video_info.size);
+ return mem;
+}
+
+GstMemory *
+gst_droid_media_buffer_allocator_alloc_from_buffer (GstAllocator * allocator,
+ DroidMediaBuffer * buffer)
{
GstDroidMediaBufferMemory *mem;
- DroidMediaBuffer *buffer;
- gsize size;
+ DroidMediaBufferInfo info;
+ int format_index;
if (!GST_IS_DROID_MEDIA_BUFFER_ALLOCATOR (allocator)) {
GST_WARNING_OBJECT (allocator,
@@ -115,23 +327,12 @@
return NULL;
}
- mem = g_slice_new0 (GstDroidMediaBufferMemory);
+ droid_media_buffer_get_info (buffer, &info);
- buffer = droid_media_buffer_queue_acquire_buffer (queue, cb);
- if (!buffer) {
- GST_ERROR_OBJECT (allocator, "failed to acquire media buffer");
- g_slice_free (GstDroidMediaBufferMemory, mem);
- return NULL;
- }
-
- mem->buffer = buffer;
-
- /* This is not the correct size of the underlying buffer but there is no way to get that */
- size = sizeof (buffer);
+ format_index = gst_droid_media_buffer_index_of_hal_format (info.format);
- gst_memory_init (GST_MEMORY_CAST (mem),
- GST_MEMORY_FLAG_NO_SHARE | GST_MEMORY_FLAG_NOT_MAPPABLE, allocator, NULL,
- size, 0, 0, size);
+ mem = gst_droid_media_buffer_allocator_alloc (allocator, buffer,
+ format_index, info.width, info.height, info.stride, 1);
GST_DEBUG_OBJECT (allocator, "alloc %p", mem);
@@ -139,53 +340,43 @@
}
GstMemory *
-gst_droid_media_buffer_allocator_alloc_from_data (GstAllocator * allocator,
- GstVideoInfo * info, DroidMediaData * data, DroidMediaBufferCallbacks * cb)
+gst_droid_media_buffer_allocator_alloc_new (GstAllocator * allocator,
+ GstVideoInfo * info)
{
GstDroidMediaBufferMemory *mem;
- DroidMediaBuffer *buffer;
- int format;
- GstDroidMediaBufferAllocator *alloc;
+ DroidMediaBuffer *dbuf;
+ DroidMediaBufferInfo droid_info;
+ int format_index;
if (!GST_IS_DROID_MEDIA_BUFFER_ALLOCATOR (allocator)) {
GST_WARNING_OBJECT (allocator,
"allocator is not the correct allocator for droidmediabuffer");
return NULL;
}
- alloc = (GstDroidMediaBufferAllocator *) allocator;
-
- if (info->finfo->format == GST_VIDEO_FORMAT_YV12) {
- format = alloc->c.HAL_PIXEL_FORMAT_YV12;
- } else if (info->finfo->format == GST_VIDEO_FORMAT_NV21) {
- format = alloc->c.HAL_PIXEL_FORMAT_YCrCb_420_SP;
- } else {
+ format_index =
+ gst_droid_media_buffer_index_of_gst_format (info->finfo->format);
+ if (format_index == GST_DROID_MEDIA_BUFFER_FORMAT_COUNT) {
GST_WARNING_OBJECT (allocator,
"Unknown GStreamer format %s",
gst_video_format_to_string (info->finfo->format));
return NULL;
}
-
- mem = g_slice_new0 (GstDroidMediaBufferMemory);
-
- buffer =
- droid_media_buffer_create_from_raw_data (info->width, info->height,
- GST_VIDEO_INFO_COMP_STRIDE (info, 0),
- GST_VIDEO_INFO_COMP_STRIDE (info, 1), format, data, cb);
- if (!buffer) {
+ GST_WARNING_OBJECT (allocator,
+ "GStreamer format %s", gst_video_format_to_string (info->finfo->format));
+ dbuf =
+ droid_media_buffer_create (info->width, info->height,
+ gst_droid_media_buffer_formats[format_index].hal_format);
+ if (!dbuf) {
GST_ERROR_OBJECT (allocator, "failed to acquire media buffer");
- g_slice_free (GstDroidMediaBufferMemory, mem);
return NULL;
}
- mem->buffer = buffer;
-
- gst_memory_init (GST_MEMORY_CAST (mem),
- GST_MEMORY_FLAG_NO_SHARE | GST_MEMORY_FLAG_NOT_MAPPABLE, allocator, NULL,
- 0, 0, 0, 0);
-
+ droid_media_buffer_get_info (dbuf, &droid_info);
+ mem =
+ gst_droid_media_buffer_allocator_alloc (allocator, dbuf,
+ format_index, info->width, info->height, droid_info.stride, info->size);
GST_DEBUG_OBJECT (allocator, "alloc %p", mem);
-
return GST_MEMORY_CAST (mem);
}
@@ -200,13 +391,10 @@
GstMemory * mem)
{
GstDroidMediaBufferMemory *m = (GstDroidMediaBufferMemory *) mem;
-
GST_DEBUG_OBJECT (allocator, "free %p", m);
- droid_media_buffer_release (m->buffer, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
-
+ droid_media_buffer_destroy (m->buffer);
m->buffer = NULL;
-
g_slice_free (GstDroidMediaBufferMemory, m);
}
@@ -220,3 +408,105 @@
return ((GstDroidMediaBufferMemory *) mem)->buffer;
}
+
+DroidMediaBuffer *
+gst_droid_media_buffer_memory_get_buffer_from_gst_buffer (GstBuffer * buffer)
+{
+ gint i;
+ gint count = gst_buffer_n_memory (buffer);
+
+ for (i = 0; i < count; ++i) {
+ GstMemory *mem = gst_buffer_peek_memory (buffer, i);
+ if (mem && gst_memory_is_type (mem, GST_ALLOCATOR_DROID_MEDIA_BUFFER)) {
+ return ((GstDroidMediaBufferMemory *) mem)->buffer;
+ }
+ }
+ return NULL;
+}
+
+gpointer
+gst_droid_media_buffer_memory_map (GstMemory * mem, gsize maxsize,
+ GstMapFlags flags)
+{
+ GstDroidMediaBufferMemory *m = (GstDroidMediaBufferMemory *) mem;
+ int f = 0;
+ (void) maxsize;
+ if (flags & GST_MAP_READ) {
+ f |= DROID_MEDIA_BUFFER_LOCK_READ;
+ }
+ if (flags & GST_MAP_WRITE) {
+ f |= DROID_MEDIA_BUFFER_LOCK_WRITE;
+ }
+
+ if (m->map_count > 0) {
+ if (m->map_flags != f) {
+ GST_ERROR ("Tried to lock buffer with different flags");
+ return NULL;
+ }
+ } else {
+ m->map_data = droid_media_buffer_lock (m->buffer, f);
+ if (!m->map_data) {
+ GST_ERROR ("Tried to lock buffer with different flags");
+ return NULL;
+ }
+ }
+
+ m->map_flags = f;
+ m->map_count += 1;
+ return m->map_data;
+}
+
+void
+gst_droid_media_buffer_memory_unmap (GstMemory * mem)
+{
+ GstDroidMediaBufferMemory *m = (GstDroidMediaBufferMemory *) mem;
+ if (m->map_count > 0 && (m->map_count -= 1) == 0) {
+ m->map_data = NULL;
+ droid_media_buffer_unlock (m->buffer);
+ }
+}
+
+EGLImageKHR
+gst_droid_media_buffer_create_image (GstMemory * mem, EGLDisplay dpy,
+ EGLContext ctx)
+{
+ GstDroidMediaBufferAllocatorClass *aclass =
+ GST_DROID_MEDIA_BUFFER_ALLOCATOR_GET_CLASS (mem->allocator);
+
+ if (gst_is_droid_media_buffer_memory (mem) && aclass
+ && aclass->egl_create_image_khr) {
+ EGLint eglImgAttrs[] =
+ { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE, EGL_NONE };
+
+ return (*aclass->egl_create_image_khr) (dpy, ctx, EGL_NATIVE_BUFFER_ANDROID,
+ (EGLClientBuffer) gst_droid_media_buffer_memory_get_buffer (mem),
+ eglImgAttrs);
+ } else {
+ return NULL;
+ }
+}
+
+GstVideoInfo *
+gst_droid_media_buffer_get_video_info (GstMemory * mem)
+{
+ if (!gst_is_droid_media_buffer_memory (mem)) {
+ GST_ERROR ("memory %p is not droidmediabuffer memory", mem);
+ return NULL;
+ }
+
+ return &((GstDroidMediaBufferMemory *) mem)->video_info;
+}
+
+GstVideoInfo *
+gst_droid_media_buffer_get_video_info_from_gst_buffer (GstBuffer * buffer)
+{
+ gint i;
+ gint count = gst_buffer_n_memory (buffer);
+ for (i = 0; i < count; ++i) {
+ GstMemory *mem = gst_buffer_peek_memory (buffer, i);
+ if (mem && gst_memory_is_type (mem, GST_ALLOCATOR_DROID_MEDIA_BUFFER)) {
+ return gst_droid_media_buffer_get_video_info (mem);
+ }
+ }
+ return NULL;
+}
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst-libs/gst/droid/gstdroidmediabuffer.h
^
|
@@ -23,25 +23,29 @@
#include <gst/gst.h>
#include <gst/video/video.h>
-#include "droidmedia.h"
+#include <droidmedia/droidmedia.h>
G_BEGIN_DECLS
#define GST_ALLOCATOR_DROID_MEDIA_BUFFER "droidmediabuffer"
#define GST_CAPS_FEATURE_MEMORY_DROID_MEDIA_BUFFER "memory:DroidMediaBuffer"
+#define GST_CAPS_FEATURE_MEMORY_DROID_MEDIA_QUEUE_BUFFER "memory:DroidMediaQueueBuffer"
+#define GST_DROID_MEDIA_BUFFER_MEMORY_VIDEO_FORMATS "{ NV12_64Z32, YV12, NV16, " \
+ "NV12, NV21, YUY2, RGBA, RGBx, RGB, RGB16, BGRA, ENCODED }"
GstAllocator * gst_droid_media_buffer_allocator_new (void);
-GstMemory * gst_droid_media_buffer_allocator_alloc (GstAllocator * allocator,
- DroidMediaBufferQueue *queue,
- DroidMediaBufferCallbacks *cb);
-GstMemory * gst_droid_media_buffer_allocator_alloc_from_data (GstAllocator * allocator,
- GstVideoInfo * info,
- DroidMediaData * data,
- DroidMediaBufferCallbacks *cb);
+GstMemory * gst_droid_media_buffer_allocator_alloc_new (GstAllocator * allocator,
+ GstVideoInfo * info);
+GstMemory * gst_droid_media_buffer_allocator_alloc_from_buffer (GstAllocator * allocator,
+ DroidMediaBuffer * buffer);
DroidMediaBuffer * gst_droid_media_buffer_memory_get_buffer (GstMemory * mem);
+DroidMediaBuffer * gst_droid_media_buffer_memory_get_buffer_from_gst_buffer (GstBuffer *buffer);
gboolean gst_is_droid_media_buffer_memory (GstMemory * mem);
+GstVideoInfo * gst_droid_media_buffer_get_video_info (GstMemory * mem);
+GstVideoInfo * gst_droid_media_buffer_get_video_info_from_gst_buffer (GstBuffer *buffer);
+
G_END_DECLS
#endif /* __GST_DROID_MEDIA_BUFFER_H__ */
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/Makefile.am
^
|
@@ -6,6 +6,7 @@
libgstdroid_la_CFLAGS = $(GST_CFLAGS) $(NGI_CFLAGS) $(EGL_CFLAGS) \
$(NGM_CFLAGS)\
+ -DEGL_NO_X11 \
-I$(top_builddir)/gst-libs/ \
-I/usr/include/droidmedia/ \
-Idroidcamsrc/ \
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/droidcamsrc/Makefile.am
^
|
@@ -2,6 +2,7 @@
noinst_LTLIBRARIES = libgstdroidcamsrc.la
libgstdroidcamsrc_la_CFLAGS = $(GST_CFLAGS) $(NGI_CFLAGS) \
$(NGM_CFLAGS) $(EXIF_CFLAGS) \
+ -DEGL_NO_X11 \
-I$(top_builddir)/gst/ \
-I$(top_builddir)/gst-libs/ \
-I/usr/include/droidmedia/
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/droidcamsrc/gstdroidcamsrc.c
^
|
@@ -28,6 +28,7 @@
#include "gstdroidcamsrcquirks.h"
#include <gst/video/video.h>
#include "gst/droid/gstdroidmediabuffer.h"
+#include "gst/droid/gstdroidbufferpool.h"
#include "gst/droid/gstwrappedmemory.h"
#include "gst/droid/gstdroidquery.h"
#include "gst/droid/gstdroidcodec.h"
@@ -52,7 +53,8 @@
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
- (GST_CAPS_FEATURE_MEMORY_DROID_MEDIA_BUFFER, "{YV12}") ";"
+ (GST_CAPS_FEATURE_MEMORY_DROID_MEDIA_QUEUE_BUFFER,
+ GST_DROID_MEDIA_BUFFER_MEMORY_VIDEO_FORMATS) ";"
GST_VIDEO_CAPS_MAKE ("{NV21}")));
static GstStaticPadTemplate img_src_template_factory =
@@ -183,7 +185,7 @@
src->fps_d = 1;
src->target_bitrate = DEFAULT_TARGET_BITRATE;
- gst_droidcamsrc_photography_init (src, DEFAULT_CAMERA_DEVICE);
+ gst_droidcamsrc_photography_init (src);
src->vfsrc = gst_droidcamsrc_create_pad (src,
GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME, FALSE);
@@ -325,8 +327,8 @@
} else {
src->camera_device = g_value_get_enum (value);
GST_INFO_OBJECT (src, "camera device set to %d", src->camera_device);
- /* load our configuration file */
- gst_droidcamsrc_photography_init (src, src->camera_device);
+ /* initialize empty photo properties */
+ gst_droidcamsrc_photography_init (src);
}
g_rec_mutex_unlock (&src->dev_lock);
break;
@@ -481,8 +483,7 @@
}
if (num > MAX_CAMERAS) {
- GST_ERROR_OBJECT (src, "cannot support %d cameras", num);
- return FALSE;
+ GST_WARNING_OBJECT (src, "cannot support %d cameras", num);
}
src->info[0].num = src->info[1].num = -1;
@@ -598,6 +599,9 @@
/* now that we have camera parameters, we can update min and max ev-compensation */
gst_droidcamsrc_update_ev_compensation_bounds (src);
+ /* and the photography parameters */
+ gst_droidcamsrc_photography_update_params (src);
+
/* And we can also detect the supported image modes. In reality the only thing
we are unable to detect until this moment is _ZSL_AND_HDR */
g_object_notify (G_OBJECT (src), "supported-image-modes");
@@ -1047,6 +1051,37 @@
"Target bitrate", 0, G_MAXINT,
DEFAULT_TARGET_BITRATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class,
+ PROP_SUPPORTED_WB_MODES,
+ g_param_spec_variant ("supported-wb-modes",
+ "Supported white balance modes", "Supported white balance modes",
+ G_VARIANT_TYPE_VARIANT, NULL, G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_SUPPORTED_COLOR_TONES,
+ g_param_spec_variant ("supported-color-tones", "Supported color tones",
+ "Supported color tones", G_VARIANT_TYPE_VARIANT, NULL,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_SUPPORTED_SCENE_MODES,
+ g_param_spec_variant ("supported-scene-modes",
+ "Supported scene modes", "Supported scene modes",
+ G_VARIANT_TYPE_VARIANT, NULL, G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_SUPPORTED_FLASH_MODES,
+ g_param_spec_variant ("supported-flash-modes", "Supported flash modes",
+ "Supported flash modes", G_VARIANT_TYPE_VARIANT, NULL,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_SUPPORTED_FOCUS_MODES,
+ g_param_spec_variant ("supported-focus-modes", "Supported focus modes",
+ "Supported focus modes", G_VARIANT_TYPE_VARIANT, NULL,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_SUPPORTED_ISO_SPEEDS,
+ g_param_spec_variant ("supported-iso-speeds", "Supported ISO speeds",
+ "Supported ISO speeds", G_VARIANT_TYPE_VARIANT, NULL,
+ G_PARAM_READABLE));
+
gst_droidcamsrc_photography_add_overrides (gobject_class);
/* Signals */
@@ -1422,7 +1457,9 @@
g_rec_mutex_lock (&src->dev_lock);
if (src->dev && src->dev->params) {
if (data == src->vfsrc) {
- caps = gst_droidcamsrc_params_get_viewfinder_caps (src->dev->params);
+ caps =
+ gst_droidcamsrc_params_get_viewfinder_caps (src->dev->params,
+ src->dev->viewfinder_format);
} else if (data == src->imgsrc) {
caps = gst_droidcamsrc_params_get_image_caps (src->dev->params);
} else if (data == src->vidsrc) {
@@ -1491,14 +1528,19 @@
gboolean ret = FALSE;
GstCaps *peer = NULL;
GstCaps *our_caps = NULL;
+ GstCapsFeatures *features;
gchar *preview;
GstVideoInfo info;
+ gboolean use_raw_data = TRUE;
+ GstBufferPool *pool = NULL;
g_rec_mutex_lock (&src->dev_lock);
GST_DEBUG_OBJECT (src, "vfsrc negotiate");
- our_caps = gst_droidcamsrc_params_get_viewfinder_caps (src->dev->params);
+ our_caps =
+ gst_droidcamsrc_params_get_viewfinder_caps (src->dev->params,
+ src->dev->viewfinder_format);
GST_DEBUG_OBJECT (src, "our caps %" GST_PTR_FORMAT, our_caps);
if (!our_caps || gst_caps_is_empty (our_caps)) {
@@ -1557,8 +1599,80 @@
gst_droidcamsrc_params_set_string (src->dev->params, "preview-size", preview);
g_free (preview);
+ features = gst_caps_get_features (our_caps, 0);
+
+ use_raw_data =
+ !gst_caps_features_contains (features,
+ GST_CAPS_FEATURE_MEMORY_DROID_MEDIA_QUEUE_BUFFER);
+
+ if (!use_raw_data) {
+ /* Negotiate a buffer pool or allocate one now. */
+ gint i;
+ guint min, max;
+ guint size;
+ gint count;
+ GstQuery *query = gst_query_new_allocation (our_caps, TRUE);
+
+ if (!gst_pad_peer_query (data->pad, query)) {
+ GST_DEBUG_OBJECT (src, "didn't get downstream ALLOCATION hints");
+ }
+
+ count = gst_query_get_n_allocation_pools (query);
+
+ for (i = 0; i < count; ++i) {
+ GstAllocator *allocator;
+ GstStructure *config;
+
+ gst_query_parse_nth_allocation_pool (query, i, &pool, &size, &min, &max);
+ config = gst_buffer_pool_get_config (pool);
+ gst_buffer_pool_config_get_allocator (config, &allocator, NULL);
+ if (allocator
+ && g_strcmp0 (allocator->mem_type,
+ GST_ALLOCATOR_DROID_MEDIA_BUFFER) == 0) {
+ break;
+ } else {
+ gst_object_unref (pool);
+ pool = NULL;
+ }
+ }
+
+ /* The downstream may have other ideas about what the pool size should be but the
+ * queue we're working with has a fixed size so that's the number of buffers we'll
+ * go with. */
+ min = 0;
+ max = droid_media_buffer_queue_length ();
+
+ if (!pool) {
+ /* A downstream which understands the queue buffers should also have provided a pool
+ * but for completeness add this a fallback. */
+ GstStructure *config;
+ GstVideoInfo video_info;
+ gst_video_info_from_caps (&video_info, our_caps);
+
+ pool = gst_droid_buffer_pool_new ();
+ size = video_info.finfo->format == GST_VIDEO_FORMAT_ENCODED
+ ? 1 : video_info.size;
+
+ config = gst_buffer_pool_get_config (pool);
+ gst_buffer_pool_config_set_params (config, our_caps, size, min, max);
+
+ if (!gst_buffer_pool_set_config (pool, config)) {
+ GST_ERROR_OBJECT (src, "Failed to set buffer pool configuration");
+ gst_object_unref (pool);
+ pool = NULL;
+ ret = FALSE;
+ }
+ }
+ }
+
g_rec_mutex_lock (&src->dev_lock);
- src->dev->use_raw_data = info.finfo->format == GST_VIDEO_FORMAT_NV21;
+ src->dev->use_raw_data = use_raw_data;
+
+ if (src->dev->pool) {
+ gst_object_unref (src->dev->pool);
+ }
+ src->dev->pool = pool;
+
g_rec_mutex_unlock (&src->dev_lock);
ret = TRUE;
@@ -1615,9 +1729,7 @@
our_caps = gst_caps_make_writable (our_caps);
our_caps = gst_droidcamsrc_pick_largest_resolution (src, our_caps);
-
- /* imgsrc frame rate is not really important so we will just set it to 30 */
- gst_caps_set_simple (our_caps, "framerate", G_TYPE_INT, 30, NULL);
+ gst_droidcamsrc_params_choose_image_framerate (src->dev->params, our_caps);
if (!gst_pad_set_caps (data->pad, our_caps)) {
GST_ERROR_OBJECT (src, "failed to set caps");
@@ -1712,7 +1824,10 @@
}
vid = g_strdup_printf ("%ix%i", info.width, info.height);
- gst_droidcamsrc_params_set_string (src->dev->params, "video-size", vid);
+ gchar *key =
+ src->dev->params->
+ has_separate_video_size_values ? "video-size" : "preview-size";
+ gst_droidcamsrc_params_set_string (src->dev->params, key, vid);
/* Now we need to find a picture size that is equal to our video size.
* Some devices need to have a picture size otherwise the video mode viewfinder
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/droidcamsrc/gstdroidcamsrcdev.c
^
|
@@ -73,7 +73,7 @@
void gst_droidcamsrc_dev_update_params_locked (GstDroidCamSrcDev * dev);
static void
gst_droidcamsrc_dev_prepare_buffer (GstDroidCamSrcDev * dev, GstBuffer * buffer,
- DroidMediaRect rect, int width, int height, GstVideoFormat format);
+ DroidMediaRect rect, GstVideoInfo * video_info);
static gboolean
gst_droidcamsrc_dev_start_video_recording_recorder_locked (GstDroidCamSrcDev *
dev);
@@ -273,6 +273,7 @@
GstDroidCamSrcDev *dev = (GstDroidCamSrcDev *) user;
GstDroidCamSrc *src = GST_DROIDCAMSRC (GST_PAD_PARENT (dev->imgsrc->pad));
GstDroidCamSrcPad *pad = dev->vfsrc;
+ GstVideoInfo video_info;
GstBuffer *buffer;
gsize width, height;
DroidMediaRect rect;
@@ -298,8 +299,9 @@
rect = src->crop_rect;
GST_OBJECT_UNLOCK (src);
- gst_droidcamsrc_dev_prepare_buffer (dev, buffer, rect, width, height,
- GST_VIDEO_FORMAT_NV21);
+ gst_video_info_set_format (&video_info, GST_VIDEO_FORMAT_NV21, width, height);
+
+ gst_droidcamsrc_dev_prepare_buffer (dev, buffer, rect, &video_info);
g_mutex_lock (&pad->lock);
g_queue_push_tail (pad->queue, buffer);
@@ -420,31 +422,53 @@
gst_droidcamsrc_dev_buffers_released (G_GNUC_UNUSED void *user)
{
GstDroidCamSrcDev *dev = (GstDroidCamSrcDev *) user;
+ GstBufferPool *pool = gst_object_ref (dev->pool);
- GST_FIXME_OBJECT (dev, "Not sure what to do here really");
+ if (pool) {
+ gst_droid_buffer_pool_media_buffers_invalidated (pool);
+ gst_object_unref (pool);
+ }
}
-static void
-gst_droidcamsrc_dev_frame_available (void *user)
+static bool
+gst_droidcamsrc_dev_buffer_created (void *user, DroidMediaBuffer * buffer)
+{
+ GstDroidCamSrcDev *dev = (GstDroidCamSrcDev *) user;
+ bool ret = false;
+ GstBufferPool *pool = gst_object_ref (dev->pool);
+
+ if (pool) {
+ ret = gst_droid_buffer_pool_bind_media_buffer (pool, buffer);
+
+ gst_object_unref (pool);
+ }
+
+ return ret;
+}
+
+static bool
+gst_droidcamsrc_dev_frame_available (void *user, DroidMediaBuffer * buffer)
{
GstDroidCamSrcDev *dev = (GstDroidCamSrcDev *) user;
GstDroidCamSrc *src = GST_DROIDCAMSRC (GST_PAD_PARENT (dev->imgsrc->pad));
GstDroidCamSrcPad *pad = dev->vfsrc;
- DroidMediaBuffer *buffer;
- GstMemory *mem;
DroidMediaRect rect;
- guint width, height;
- GstBuffer *buff;
- DroidMediaBufferCallbacks cb;
- GstFlowReturn flow_ret;
+ GstBuffer *buff = NULL;
+ GstBufferPool *pool;
DroidMediaBufferInfo info;
GST_DEBUG_OBJECT (src, "frame available");
+ droid_media_buffer_get_info (buffer, &info);
+
+ GST_OBJECT_LOCK (src);
+ src->crop_rect = rect;
+ GST_OBJECT_UNLOCK (src);
+
if (!pad->running) {
GST_DEBUG_OBJECT (src, "vfsrc pad task is not running");
- goto acquire_and_release;
+ return false;
}
/* We are accessing this without a lock because:
@@ -452,58 +476,34 @@
* 2) We can get called when we start the preview and we will deadlock because the lock is already held
*/
if (dev->use_raw_data) {
- goto acquire_and_release;
+ return false;
}
- flow_ret = gst_buffer_pool_acquire_buffer (dev->pool, &buff, NULL);
- if (flow_ret != GST_FLOW_OK) {
- GST_WARNING_OBJECT (src, "failed to acquire buffer from pool: %s",
- gst_flow_get_name (flow_ret));
+ pool = gst_object_ref (dev->pool);
- goto acquire_and_release;
- }
-
- cb.ref = (DroidMediaCallback) gst_buffer_ref;
- cb.unref = (DroidMediaCallback) gst_buffer_unref;
- cb.data = buff;
+ if (G_UNLIKELY (!pool)) {
+ GST_WARNING_OBJECT (src, "camera source doesn't have a buffer pool");
+ } else {
+ buff = gst_droid_buffer_pool_acquire_media_buffer (pool, buffer);
- mem =
- gst_droid_media_buffer_allocator_alloc (dev->media_allocator, dev->queue,
- &cb);
- if (!mem) {
- GST_ERROR_OBJECT (src, "failed to acquire buffer from droidmedia");
- gst_buffer_unref (buff);
- return;
+ gst_object_unref (pool);
}
- buffer = gst_droid_media_buffer_memory_get_buffer (mem);
-
- gst_buffer_insert_memory (buff, 0, mem);
- gst_droidcamsrc_timestamp (src, buff);
-
- rect = droid_media_buffer_get_crop_rect (buffer);
- width = droid_media_buffer_get_width (buffer);
- height = droid_media_buffer_get_height (buffer);
+ if (G_UNLIKELY (!buff)) {
+ GST_WARNING_OBJECT (src,
+ "unable to acquire a gstreamer buffer for a droid media buffer");
+ return false;
+ }
- gst_droidcamsrc_dev_prepare_buffer (dev, buff, rect, width, height,
- GST_VIDEO_FORMAT_YV12);
+ gst_droidcamsrc_dev_prepare_buffer (dev, buff, rect,
+ gst_droid_media_buffer_get_video_info_from_gst_buffer (buff));
g_mutex_lock (&pad->lock);
g_queue_push_tail (pad->queue, buff);
g_cond_signal (&pad->cond);
g_mutex_unlock (&pad->lock);
- GST_OBJECT_LOCK (src);
- src->crop_rect = rect;
- GST_OBJECT_UNLOCK (src);
- return;
-
-acquire_and_release:
- if (droid_media_buffer_queue_acquire_and_release (dev->queue, &info)) {
- GST_OBJECT_LOCK (src);
- src->crop_rect = info.crop_rect;
- GST_OBJECT_UNLOCK (src);
- }
+ return true;
}
GstDroidCamSrcDev *
@@ -534,13 +534,14 @@
dev->lock = lock;
- dev->pool = gst_droid_buffer_pool_new ();
-
+ dev->pool = NULL;
dev->use_recorder = FALSE;
dev->recorder = gst_droidcamsrc_recorder_create (vidsrc);
droid_media_camera_constants_init (&dev->c);
+ dev->viewfinder_format = GST_VIDEO_FORMAT_UNKNOWN;
+
return dev;
}
@@ -548,6 +549,10 @@
gst_droidcamsrc_dev_open (GstDroidCamSrcDev * dev, GstDroidCamSrcCamInfo * info)
{
GstDroidCamSrc *src;
+ DroidMediaColourFormatConstants constants;
+ int hal_format;
+
+ droid_media_colour_format_constants_init (&constants);
g_rec_mutex_lock (dev->lock);
@@ -565,6 +570,23 @@
return FALSE;
}
+ hal_format = droid_media_camera_get_video_color_format (dev->cam);
+
+ if (hal_format == constants.OMX_COLOR_FormatYUV420Planar) {
+ dev->viewfinder_format = GST_VIDEO_FORMAT_YV12;
+ } else if (hal_format == constants.OMX_COLOR_FormatYUV422SemiPlanar) {
+ dev->viewfinder_format = GST_VIDEO_FORMAT_NV16;
+ } else if (hal_format == constants.OMX_COLOR_FormatYUV420SemiPlanar) {
+ dev->viewfinder_format = GST_VIDEO_FORMAT_NV21;
+ } else if (hal_format == constants.OMX_COLOR_FormatYCbYCr) {
+ dev->viewfinder_format = GST_VIDEO_FORMAT_YUY2;
+ } else if (hal_format == constants.OMX_COLOR_Format16bitRGB565) {
+ dev->viewfinder_format = GST_VIDEO_FORMAT_RGB16;
+ } else {
+ GST_WARNING_OBJECT (src, "Unknown HAL color format 0x%x", hal_format);
+ dev->viewfinder_format = GST_VIDEO_FORMAT_ENCODED;
+ }
+
dev->queue = droid_media_camera_get_buffer_queue (dev->cam);
if (!droid_media_camera_lock (dev->cam)) {
@@ -618,7 +640,9 @@
g_mutex_clear (&dev->vid->lock);
g_cond_clear (&dev->vid->cond);
- gst_object_unref (dev->pool);
+ if (dev->pool) {
+ gst_object_unref (dev->pool);
+ }
gst_droidcamsrc_recorder_destroy (dev->recorder);
@@ -631,22 +655,10 @@
gboolean
gst_droidcamsrc_dev_init (GstDroidCamSrcDev * dev)
{
- GstStructure *config;
-
GST_DEBUG ("dev init");
g_rec_mutex_lock (dev->lock);
- /* first the buffer pool */
- config = gst_buffer_pool_get_config (dev->pool);
- gst_buffer_pool_config_set_params (config, NULL, 0,
- GST_DROIDCAMSRC_NUM_BUFFERS, GST_DROIDCAMSRC_NUM_BUFFERS);
-
- if (!gst_buffer_pool_set_config (dev->pool, config)) {
- GST_ERROR ("Failed to configure buffer pool");
- return FALSE;
- }
-
/* now the callbacks */
{
DroidMediaCameraCallbacks cb;
@@ -670,6 +682,7 @@
DroidMediaBufferQueueCallbacks cb;
cb.buffers_released = gst_droidcamsrc_dev_buffers_released;
cb.frame_available = gst_droidcamsrc_dev_frame_available;
+ cb.buffer_created = gst_droidcamsrc_dev_buffer_created;
droid_media_buffer_queue_set_callbacks (dev->queue, &cb, dev);
}
@@ -1115,7 +1128,7 @@
static void
gst_droidcamsrc_dev_prepare_buffer (GstDroidCamSrcDev * dev, GstBuffer * buffer,
- DroidMediaRect rect, int width, int height, GstVideoFormat format)
+ DroidMediaRect rect, GstVideoInfo * video_info)
{
GstDroidCamSrc *src = GST_DROIDCAMSRC (GST_PAD_PARENT (dev->imgsrc->pad));
GstVideoCropMeta *crop;
@@ -1133,11 +1146,13 @@
gst_buffer_add_gst_buffer_orientation_meta (buffer,
dev->info->orientation, dev->info->direction);
- gst_buffer_add_video_meta (buffer, GST_VIDEO_FRAME_FLAG_NONE,
- format, width, height);
+ gst_buffer_add_video_meta_full (buffer, GST_VIDEO_FRAME_FLAG_NONE,
+ video_info->finfo->format, video_info->width, video_info->height,
+ video_info->finfo->n_planes, video_info->offset, video_info->stride);
GST_LOG_OBJECT (src, "preview info: w=%d, h=%d, crop: x=%d, y=%d, w=%d, h=%d",
- width, height, crop->x, crop->y, crop->width, crop->height);
+ video_info->width, video_info->height, crop->x, crop->y, crop->width,
+ crop->height);
}
static gboolean
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/droidcamsrc/gstdroidcamsrcdev.h
^
|
@@ -54,6 +54,7 @@
GstDroidCamSrcVideoCaptureState *vid;
GstBufferPool *pool;
DroidMediaCameraConstants c;
+ GstVideoFormat viewfinder_format;
gboolean use_recorder;
GstDroidCamSrcRecorder *recorder;
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/droidcamsrc/gstdroidcamsrcexif.c
^
|
@@ -160,11 +160,7 @@
EXIF_TAG_ISO_SPEED_RATINGS);
if (iso) {
-#ifdef __arm__
- guint16 val = exif_get_short (iso->data, EXIF_BYTE_ORDER_MOTOROLA);
-#else
- guint16 val = exif_get_short (iso->data, EXIF_BYTE_ORDER_INTEL);
-#endif
+ guint16 val = exif_get_short (iso->data, exif_data_get_byte_order(exif));
gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
GST_TAG_CAPTURING_ISO_SPEED, val, NULL);
}
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/droidcamsrc/gstdroidcamsrcparams.c
^
|
@@ -51,6 +51,12 @@
g_strfreev (parts);
}
+gboolean
+gst_droidcamsrc_has_param (GstDroidCamSrcParams * params, const char *key)
+{
+ return g_hash_table_contains (params->params, key);
+}
+
static int
gst_droidcamsrc_params_get_int_locked (GstDroidCamSrcParams * params,
const char *key)
@@ -120,7 +126,7 @@
return;
}
- if (!range[0] == '(') {
+ if (range[0] != '(') {
GST_ERROR ("invalid preview-fps-range-values");
return;
}
@@ -195,6 +201,8 @@
gst_droidcamsrc_params_fill_fps_range_arrays_locked (params);
params->is_dirty = FALSE;
+ params->has_separate_video_size_values =
+ g_hash_table_lookup (params->params, "video-size-values") != NULL;
}
GstDroidCamSrcParams *
@@ -367,7 +375,8 @@
}
GstCaps *
-gst_droidcamsrc_params_get_viewfinder_caps (GstDroidCamSrcParams * params)
+gst_droidcamsrc_params_get_viewfinder_caps (GstDroidCamSrcParams * params,
+ GstVideoFormat format)
{
GstCaps *caps;
@@ -375,7 +384,8 @@
caps =
gst_caps_merge (gst_droidcamsrc_params_get_caps_locked (params,
"preview-size-values", "video/x-raw",
- GST_CAPS_FEATURE_MEMORY_DROID_MEDIA_BUFFER, "YV12"),
+ GST_CAPS_FEATURE_MEMORY_DROID_MEDIA_QUEUE_BUFFER,
+ gst_video_format_to_string (format)),
gst_droidcamsrc_params_get_caps_locked (params, "preview-size-values",
"video/x-raw", NULL, "NV21"));
g_mutex_unlock (¶ms->lock);
@@ -389,8 +399,14 @@
GstCaps *caps;
g_mutex_lock (¶ms->lock);
- caps = gst_droidcamsrc_params_get_caps_locked (params, "video-size-values",
+
+ gchar *key =
+ params->has_separate_video_size_values ? "video-size-values" :
+ "preview-size-values";
+
+ caps = gst_droidcamsrc_params_get_caps_locked (params, key,
"video/x-raw", GST_CAPS_FEATURE_MEMORY_DROID_VIDEO_META_DATA, "YV12");
+
g_mutex_unlock (¶ms->lock);
return caps;
@@ -477,17 +493,8 @@
gst_caps_unref (c);
- /* the fps we have is valid. We are trying to pick the widest range */
- if (target_min == -1) {
- target_min = min;
- }
-
- if (target_max == -1) {
- target_max = max;
- }
-
- if (min <= target_min && max >= target_max) {
- /* we need to pick the widest range */
+ /* the fps we have is valid. Select it if higher than our current target, or wider */
+ if (max > target_max || max == target_max && min < target_min) {
target_min = min;
target_max = max;
}
@@ -537,17 +544,8 @@
gst_caps_unref (c);
- /* the fps we have is valid. We are trying to pick the widest range */
- if (target_min == -1) {
- target_min = min;
- }
-
- if (target_max == -1) {
- target_max = max;
- }
-
- if (min >= target_min && max <= target_max) {
- /* we need to pick the narrowest range */
+ /* the fps we have is valid. Select it if higher than our current target, or narrower */
+ if (max > target_max || max == target_max && min > target_min) {
target_min = min;
target_max = max;
}
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/droidcamsrc/gstdroidcamsrcparams.h
^
|
@@ -22,6 +22,7 @@
#define __GST_DROIDCAMSRC_PARAMS_H__
#include <gst/gst.h>
+#include <gst/video/video.h>
G_BEGIN_DECLS
@@ -32,22 +33,23 @@
GHashTable *params;
gboolean is_dirty;
GArray *min_fps_range, *max_fps_range;
+ gboolean has_separate_video_size_values;
GMutex lock;
};
GstDroidCamSrcParams * gst_droidcamsrc_params_new (const gchar * params);
void gst_droidcamsrc_params_destroy (GstDroidCamSrcParams *params);
+gboolean gst_droidcamsrc_has_param (GstDroidCamSrcParams * params, const char *key);
void gst_droidcamsrc_params_reload (GstDroidCamSrcParams *params, const gchar * str);
gchar *gst_droidcamsrc_params_to_string (GstDroidCamSrcParams *params);
gboolean gst_droidcamsrc_params_is_dirty (GstDroidCamSrcParams *params);
-GstCaps *gst_droidcamsrc_params_get_viewfinder_caps (GstDroidCamSrcParams *params);
+GstCaps *gst_droidcamsrc_params_get_viewfinder_caps (GstDroidCamSrcParams *params, GstVideoFormat format);
GstCaps *gst_droidcamsrc_params_get_video_caps (GstDroidCamSrcParams *params);
GstCaps *gst_droidcamsrc_params_get_image_caps (GstDroidCamSrcParams *params);
-void gst_droidcamsrc_params_set_string (GstDroidCamSrcParams *params, const gchar *key,
- const gchar *value);
+void gst_droidcamsrc_params_set_string (GstDroidCamSrcParams *params, const gchar *key, const gchar *value);
const gchar *gst_droidcamsrc_params_get_string (GstDroidCamSrcParams * params, const char *key);
int gst_droidcamsrc_params_get_int (GstDroidCamSrcParams * params, const char *key);
float gst_droidcamsrc_params_get_float (GstDroidCamSrcParams * params, const char *key);
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/droidcamsrc/gstdroidcamsrcphotography.c
^
|
@@ -76,6 +76,7 @@
GList *scene;
GList *wb;
GList *iso;
+ gchar *iso_key;
GList *flicker;
};
@@ -85,8 +86,116 @@
gchar *value;
};
-static GList *gst_droidcamsrc_photography_load (GKeyFile * file,
- const gchar * property);
+struct DataEntry FlashValues[] = {
+ {GST_PHOTOGRAPHY_FLASH_MODE_AUTO, "auto"},
+ {GST_PHOTOGRAPHY_FLASH_MODE_OFF, "off"},
+ {GST_PHOTOGRAPHY_FLASH_MODE_ON, "on"},
+ {GST_PHOTOGRAPHY_FLASH_MODE_RED_EYE, "red-eye"}
+};
+
+struct DataEntry FocusValues[] = {
+ {GST_PHOTOGRAPHY_FOCUS_MODE_AUTO, "auto"},
+ {GST_PHOTOGRAPHY_FOCUS_MODE_MACRO, "macro"},
+ {GST_PHOTOGRAPHY_FOCUS_MODE_INFINITY, "infinity"},
+ {GST_PHOTOGRAPHY_FOCUS_MODE_HYPERFOCAL, "fixed"},
+ {GST_PHOTOGRAPHY_FOCUS_MODE_EXTENDED, "edof"},
+ {GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_NORMAL, "continuous"},
+ {GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_EXTENDED, "continuous"},
+ {GST_PHOTOGRAPHY_FOCUS_MODE_MANUAL, "manual"}
+};
+
+struct DataEntry ISOValues[] = {
+ {0, "auto"},
+ {0, "iso-auto"},
+ {1, "ISO_HJR"},
+ {100, "ISO100"},
+ {100, "iso-100"},
+ {100, "100"},
+ {200, "ISO200"},
+ {200, "iso-200"},
+ {200, "200"},
+ {400, "ISO400"},
+ {400, "iso-400"},
+ {400, "400"},
+ {800, "ISO800"},
+ {800, "iso-800"},
+ {800, "800"},
+ {1600, "ISO1600"},
+ {1600, "1600"},
+ {3200, "ISO3200"},
+ {3200, "3200"},
+ {6400, "ISO6400"},
+ {6400, "6400"},
+ {12800, "ISO12800"},
+ {12800, "12800"}
+};
+
+struct DataEntry WhiteBalanceValues[] = {
+ {GST_PHOTOGRAPHY_WB_MODE_AUTO, "auto"},
+ {GST_PHOTOGRAPHY_WB_MODE_DAYLIGHT, "daylight"},
+ {GST_PHOTOGRAPHY_WB_MODE_CLOUDY, "cloudy-daylight"},
+ {GST_PHOTOGRAPHY_WB_MODE_SUNSET, "twilight"},
+ {GST_PHOTOGRAPHY_WB_MODE_TUNGSTEN, "incandescent"},
+ {GST_PHOTOGRAPHY_WB_MODE_FLUORESCENT, "fluorescent"},
+ {GST_PHOTOGRAPHY_WB_MODE_MANUAL, "manual"},
+ {GST_PHOTOGRAPHY_WB_MODE_WARM_FLUORESCENT, "warm-fluorescent"},
+ {GST_PHOTOGRAPHY_WB_MODE_SHADE, "shade"}
+};
+
+struct DataEntry SceneValues[] = {
+ {GST_PHOTOGRAPHY_SCENE_MODE_PORTRAIT, "portrait"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_LANDSCAPE, "landscape"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_SPORT, "sports"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_NIGHT, "night"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_MANUAL, "auto"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_AUTO, "asd"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_ACTION, "action"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_NIGHT_PORTRAIT, "night-portrait"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_THEATRE, "theatre"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_BEACH, "beach"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_SNOW, "snow"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_SUNSET, "sunset"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_STEADY_PHOTO, "steadyphoto"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_FIREWORKS, "fireworks"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_PARTY, "party"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_CANDLELIGHT, "candlelight"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_BARCODE, "barcode"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_BACKLIGHT, "backlight"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_FLOWERS, "flowers"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_AR, "AR"},
+ {GST_PHOTOGRAPHY_SCENE_MODE_HDR, "hdr"}
+};
+
+struct DataEntry ColourToneValues[] = {
+ {GST_PHOTOGRAPHY_COLOR_TONE_MODE_NORMAL, "none"},
+ {GST_PHOTOGRAPHY_COLOR_TONE_MODE_SEPIA, "sepia"},
+ {GST_PHOTOGRAPHY_COLOR_TONE_MODE_NEGATIVE, "negative"},
+ {GST_PHOTOGRAPHY_COLOR_TONE_MODE_GRAYSCALE, "mono"},
+ {GST_PHOTOGRAPHY_COLOR_TONE_MODE_VIVID, "vivid"},
+ {GST_PHOTOGRAPHY_COLOR_TONE_MODE_SOLARIZE, "solarize"},
+ {GST_PHOTOGRAPHY_COLOR_TONE_MODE_SKY_BLUE, "still-sky-blue"},
+ {GST_PHOTOGRAPHY_COLOR_TONE_MODE_GRASS_GREEN, "still-grass-green"},
+ {GST_PHOTOGRAPHY_COLOR_TONE_MODE_SKIN_WHITEN, "still-skin-whiten-medium"},
+ {GST_PHOTOGRAPHY_COLOR_TONE_MODE_POSTERIZE, "posterize"},
+ {GST_PHOTOGRAPHY_COLOR_TONE_MODE_WHITEBOARD, "whiteboard"},
+ {GST_PHOTOGRAPHY_COLOR_TONE_MODE_BLACKBOARD, "blackboard"},
+ {GST_PHOTOGRAPHY_COLOR_TONE_MODE_AQUA, "aqua"},
+ {GST_PHOTOGRAPHY_COLOR_TONE_MODE_EMBOSS, "emboss"},
+ {GST_PHOTOGRAPHY_COLOR_TONE_MODE_SKETCH, "sketch"},
+ {GST_PHOTOGRAPHY_COLOR_TONE_MODE_NEON, "neon"}
+};
+
+struct DataEntry FlickerValues[] = {
+ {GST_PHOTOGRAPHY_FLICKER_REDUCTION_OFF, "off"},
+ {GST_PHOTOGRAPHY_FLICKER_REDUCTION_50HZ, "50hz"},
+ {GST_PHOTOGRAPHY_FLICKER_REDUCTION_60HZ, "60hz"},
+ {GST_PHOTOGRAPHY_FLICKER_REDUCTION_AUTO, "auto"}
+};
+
+static GList *gst_droidcamsrc_photography_append_list (GList * list,
+ const int key, const gchar * value);
+static GList *gst_droidcamsrc_photography_create_list (const gchar * params,
+ struct DataEntry entries[], gsize len);
#define PHOTO_IFACE_FUNC(name, tset, tget) \
static gboolean gst_droidcamsrc_get_##name (GstDroidCamSrc * src, tget val); \
@@ -124,6 +233,14 @@
#define SET_ENUM(table,val,droid,memb) \
int x; \
int len = g_list_length (table); \
+ if (len == 0) { \
+ GST_WARNING_OBJECT (src, "params for %s not yet available. not applying value %d yet", droid, val); \
+ GST_OBJECT_LOCK (src); \
+ src->photo->settings.memb = val; \
+ GST_OBJECT_UNLOCK (src); \
+ return FALSE; \
+ } \
+ \
const gchar *value = NULL; \
for (x = 0; x < len; x++) { \
struct DataEntry *entry = (struct DataEntry *) g_list_nth_data (table, x); \
@@ -210,6 +327,31 @@
capture_caps, user_data);
}
+GVariant *
+gst_droid_camsrc_glist_to_array (GList * list)
+{
+ int len = g_list_length (list);
+
+ if (len == 0) {
+ return 0;
+ }
+
+ GVariant *modes;
+ GVariantBuilder *builder;
+ builder = g_variant_builder_new (G_VARIANT_TYPE ("ai"));
+
+ struct DataEntry *entry;
+ GList *l;
+ for (l = list; l != NULL; l = l->next) {
+ entry = l->data;
+ g_variant_builder_add (builder, "i", entry->key);
+ }
+
+ modes = g_variant_new ("ai", builder);
+ g_variant_builder_unref (builder);
+ return modes;
+}
+
static void
gst_droidcamsrc_photography_set_autofocus (GstPhotography * photo, gboolean on)
{
@@ -490,6 +632,53 @@
{
/* not supported */
}
+
+ return TRUE;
+
+ case PROP_SUPPORTED_WB_MODES:
+ {
+ GVariant *wb_modes = gst_droid_camsrc_glist_to_array (src->photo->wb);
+ g_value_set_variant (value, wb_modes);
+ }
+ return TRUE;
+
+ case PROP_SUPPORTED_COLOR_TONES:
+ {
+ GVariant *effects =
+ gst_droid_camsrc_glist_to_array (src->photo->color_tone);
+ g_value_set_variant (value, effects);
+ }
+ return TRUE;
+
+ case PROP_SUPPORTED_SCENE_MODES:
+ {
+ GVariant *exposure_modes =
+ gst_droid_camsrc_glist_to_array (src->photo->scene);
+ g_value_set_variant (value, exposure_modes);
+ }
+ return TRUE;
+
+ case PROP_SUPPORTED_FLASH_MODES:
+ {
+ GVariant *flash_modes =
+ gst_droid_camsrc_glist_to_array (src->photo->flash);
+ g_value_set_variant (value, flash_modes);
+ }
+ return TRUE;
+
+ case PROP_SUPPORTED_FOCUS_MODES:
+ {
+ GVariant *focus_modes =
+ gst_droid_camsrc_glist_to_array (src->photo->focus);
+ g_value_set_variant (value, focus_modes);
+ }
+ return TRUE;
+
+ case PROP_SUPPORTED_ISO_SPEEDS:
+ {
+ GVariant *iso_modes = gst_droid_camsrc_glist_to_array (src->photo->iso);
+ g_value_set_variant (value, iso_modes);
+ }
return TRUE;
}
@@ -599,21 +788,15 @@
}
void
-gst_droidcamsrc_photography_init (GstDroidCamSrc * src, gint dev)
+gst_droidcamsrc_photography_init (GstDroidCamSrc * src)
{
int x;
- GKeyFile *file = g_key_file_new ();
- gchar *file_path =
- g_strdup_printf ("/%s/gst-droid/gstdroidcamsrc-%d.conf", SYSCONFDIR, dev);
- GError *err = NULL;
-
- GST_INFO_OBJECT (src, "using configuration file %s", file_path);
if (!src->photo) {
src->photo = g_slice_new0 (GstDroidCamSrcPhotography);
src->photo->settings.wb_mode = GST_PHOTOGRAPHY_WB_MODE_AUTO;
src->photo->settings.tone_mode = GST_PHOTOGRAPHY_COLOR_TONE_MODE_NORMAL;
- src->photo->settings.scene_mode = GST_PHOTOGRAPHY_SCENE_MODE_AUTO;
+ src->photo->settings.scene_mode = GST_PHOTOGRAPHY_SCENE_MODE_MANUAL;
src->photo->settings.flash_mode = GST_PHOTOGRAPHY_FLASH_MODE_AUTO;
src->photo->settings.ev_compensation = 0.0;
src->photo->settings.iso_speed = 0;
@@ -636,59 +819,87 @@
src->photo->settings.white_point[x] = 0;
}
}
+}
- if (!g_key_file_load_from_file (file, file_path, G_KEY_FILE_NONE, &err)) {
- GST_WARNING ("failed to load configuration file %s: %s", file_path,
- err->message);
- }
-
- if (err) {
- g_error_free (err);
- err = NULL;
- }
+void
+gst_droidcamsrc_photography_update_params (GstDroidCamSrc * src)
+{
+ /* Set photography parameters from Android HAL */
- /* load settings */
+ /* Flash */
if (src->photo->flash) {
g_list_free_full (src->photo->flash, (GDestroyNotify) free_data_entry);
}
- src->photo->flash = gst_droidcamsrc_photography_load (file, "flash-mode");
+ src->photo->flash =
+ gst_droidcamsrc_photography_create_list (gst_droidcamsrc_params_get_string
+ (src->dev->params, "flash-mode-values"), FlashValues,
+ G_N_ELEMENTS (FlashValues));
+ /* Colour tone / Effects */
if (src->photo->color_tone) {
g_list_free_full (src->photo->color_tone, (GDestroyNotify) free_data_entry);
}
src->photo->color_tone =
- gst_droidcamsrc_photography_load (file, "color-tone-mode");
+ gst_droidcamsrc_photography_create_list (gst_droidcamsrc_params_get_string
+ (src->dev->params, "effect-values"), ColourToneValues,
+ G_N_ELEMENTS (ColourToneValues));
+ /* Focus */
if (src->photo->focus) {
g_list_free_full (src->photo->focus, (GDestroyNotify) free_data_entry);
}
- src->photo->focus = gst_droidcamsrc_photography_load (file, "focus-mode");
+ src->photo->focus =
+ gst_droidcamsrc_photography_create_list (gst_droidcamsrc_params_get_string
+ (src->dev->params, "focus-mode-values"), FocusValues,
+ G_N_ELEMENTS (FocusValues));
+ /* Scene Mode */
if (src->photo->scene) {
g_list_free_full (src->photo->scene, (GDestroyNotify) free_data_entry);
}
- src->photo->scene = gst_droidcamsrc_photography_load (file, "scene-mode");
+ src->photo->scene =
+ gst_droidcamsrc_photography_create_list (gst_droidcamsrc_params_get_string
+ (src->dev->params, "scene-mode-values"), SceneValues,
+ G_N_ELEMENTS (SceneValues));
+ /* White Balance */
if (src->photo->wb) {
g_list_free_full (src->photo->wb, (GDestroyNotify) free_data_entry);
}
src->photo->wb =
- gst_droidcamsrc_photography_load (file, "white-balance-mode");
+ gst_droidcamsrc_photography_create_list (gst_droidcamsrc_params_get_string
+ (src->dev->params, "whitebalance-values"), WhiteBalanceValues,
+ G_N_ELEMENTS (WhiteBalanceValues));
+ /* ISO speed */
if (src->photo->iso) {
g_list_free_full (src->photo->iso, (GDestroyNotify) free_data_entry);
}
- src->photo->iso = gst_droidcamsrc_photography_load (file, "iso-speed");
+ if (gst_droidcamsrc_has_param (src->dev->params, "iso-values")) {
+ src->photo->iso =
+ gst_droidcamsrc_photography_create_list
+ (gst_droidcamsrc_params_get_string (src->dev->params, "iso-values"),
+ ISOValues, G_N_ELEMENTS (ISOValues));
+ src->photo->iso_key = "iso";
+ } else if (gst_droidcamsrc_has_param (src->dev->params, "iso-speed-values")) {
+ src->photo->iso =
+ gst_droidcamsrc_photography_create_list
+ (gst_droidcamsrc_params_get_string (src->dev->params,
+ "iso-speed-values"), ISOValues, G_N_ELEMENTS (ISOValues));
+ src->photo->iso_key = "iso-speed";
+ }
+ // This list should be sorted
src->photo->iso = g_list_sort (src->photo->iso, sort_desc);
+ /* Flicker / Anti-banding */
if (src->photo->flicker) {
g_list_free_full (src->photo->flicker, (GDestroyNotify) free_data_entry);
}
- src->photo->flicker = gst_droidcamsrc_photography_load (file, "flicker-mode");
+ src->photo->flicker =
+ gst_droidcamsrc_photography_create_list (gst_droidcamsrc_params_get_string
+ (src->dev->params, "antibanding-values"), FlickerValues,
+ G_N_ELEMENTS (FlickerValues));
- /* free our stuff */
- g_free (file_path);
- g_key_file_unref (file);
}
void
@@ -772,41 +983,44 @@
}
static GList *
-gst_droidcamsrc_photography_load (GKeyFile * file, const gchar * property)
+gst_droidcamsrc_photography_append_list (GList * list, const int key,
+ const gchar * value)
+{
+ struct DataEntry *entry = g_slice_new (struct DataEntry);
+ entry->key = key;
+ entry->value = g_strdup (value);
+ return g_list_append (list, entry);
+}
+
+static GList *
+gst_droidcamsrc_photography_create_list (const gchar * params,
+ struct DataEntry entries[], gsize len)
{
- gchar **keys;
int x;
- GError *err = NULL;
- gsize len = 0;
GList *list = NULL;
-
- keys = g_key_file_get_keys (file, property, &len, &err);
-
- if (err) {
- GST_WARNING ("failed to load %s: %s", property, err->message);
- g_error_free (err);
- err = NULL;
- }
-
- for (x = 0; x < len; x++) {
- gchar *value = g_key_file_get_value (file, property, keys[x], &err);
-
- if (err) {
- GST_WARNING ("failed to load %s (%s): %s", property, keys[x],
- err->message);
- g_error_free (err);
- err = NULL;
- }
-
- if (value) {
- int key = atoi (keys[x]);
- struct DataEntry *entry = g_slice_new (struct DataEntry);
- entry->key = key;
- entry->value = value;
- list = g_list_append (list, entry);
+ if (params == NULL) {
+ GST_WARNING ("No params supplied. Returning empty list");
+ return list;
+ }
+ // Split the params
+ gchar **p = g_strsplit (params, ",", -1);
+ for (x = 0; x < len; x++) { // look for each entry, so they can each occur only once
+ gchar **tmp = p;
+ while (*tmp) {
+ // Special handling for continuous focus - we have to choose -picture or -video depending on mode
+ if (!g_strcmp0 (*tmp, entries[x].value)
+ || (!g_strcmp0 (entries[x].value, "continuous")
+ && (!g_strcmp0 (*tmp, "continuous-picture")
+ || !g_strcmp0 (*tmp, "continuous-video")))) {
+ list =
+ gst_droidcamsrc_photography_append_list (list, entries[x].key,
+ entries[x].value);
+ break;
+ }
+ ++tmp;
}
}
-
+ g_strfreev (p);
return list;
}
@@ -1027,6 +1241,15 @@
int len = g_list_length (src->photo->iso);
gchar *value = NULL;
+ if (len == 0 || src->photo->iso_key == NULL) {
+ GST_DEBUG_OBJECT (src,
+ "params not yet fetched. not applying iso speed yet");
+ GST_OBJECT_LOCK (src);
+ src->photo->settings.iso_speed = iso_speed;
+ GST_OBJECT_UNLOCK (src);
+ return FALSE;
+ }
+
for (x = 0; x < len; x++) {
struct DataEntry *entry =
(struct DataEntry *) g_list_nth_data (src->photo->iso, x);
@@ -1044,8 +1267,7 @@
GST_OBJECT_LOCK (src);
src->photo->settings.iso_speed = iso_speed;
GST_OBJECT_UNLOCK (src);
-
- return gst_droidcamsrc_set_and_apply (src, "iso", value);
+ return gst_droidcamsrc_set_and_apply (src, src->photo->iso_key, value);
}
static gboolean
@@ -1140,6 +1362,16 @@
{
int x;
int len = g_list_length (src->photo->focus);
+
+ if (len == 0) {
+ GST_DEBUG_OBJECT (src,
+ "params not yet fetched. not applying focus mode yet");
+ GST_OBJECT_LOCK (src);
+ src->photo->settings.focus_mode = focus_mode;
+ GST_OBJECT_UNLOCK (src);
+ return FALSE;
+ }
+
const gchar *value = NULL;
for (x = 0; x < len; x++) {
struct DataEntry *entry =
@@ -1392,6 +1624,10 @@
int len = g_list_length (src->photo->iso);
gchar *value = NULL;
+ if (!src->dev || !src->dev->params) {
+ return;
+ }
+
for (x = 0; x < len; x++) {
struct DataEntry *entry =
(struct DataEntry *) g_list_nth_data (src->photo->iso, x);
@@ -1407,7 +1643,8 @@
return;
}
- gst_droidcamsrc_params_set_string (src->dev->params, "iso", value);
+ gst_droidcamsrc_params_set_string (src->dev->params, src->photo->iso_key,
+ value);
}
static void
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/droidcamsrc/gstdroidcamsrcphotography.h
^
|
@@ -47,6 +47,12 @@
PROP_SENSOR_ORIENTATION,
PROP_SENSOR_MOUNT_ANGLE,
PROP_TARGET_BITRATE,
+ PROP_SUPPORTED_WB_MODES,
+ PROP_SUPPORTED_COLOR_TONES,
+ PROP_SUPPORTED_SCENE_MODES,
+ PROP_SUPPORTED_FLASH_MODES,
+ PROP_SUPPORTED_FOCUS_MODES,
+ PROP_SUPPORTED_ISO_SPEEDS,
/* photography interface */
PROP_WB_MODE,
@@ -70,12 +76,13 @@
PROP_MIN_EXPOSURE_TIME,
PROP_MAX_EXPOSURE_TIME,
PROP_NOISE_REDUCTION,
- PROP_EXPOSURE_MODE,
+ PROP_EXPOSURE_MODE
} GstDroidCamSrcProperties;
void gst_droidcamsrc_photography_register (gpointer g_iface, gpointer iface_data);
void gst_droidcamsrc_photography_add_overrides (GObjectClass * klass);
-void gst_droidcamsrc_photography_init (GstDroidCamSrc * src, gint dev);
+void gst_droidcamsrc_photography_init (GstDroidCamSrc * src);
+void gst_droidcamsrc_photography_update_params (GstDroidCamSrc * src);
void gst_droidcamsrc_photography_destroy (GstDroidCamSrc * src);
gboolean gst_droidcamsrc_photography_get_property (GstDroidCamSrc * src, guint prop_id,
GValue * value, GParamSpec * pspec);
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/droidcamsrc/gstdroidcamsrcrecorder.c
^
|
@@ -67,9 +67,6 @@
recorder->md.bitrate = target_bitrate;
- /* set the color format */
- recorder->md.color_format = droid_media_camera_get_video_color_format (cam);
-
recorder->recorder = droid_media_recorder_create (cam, &recorder->md);
if (!recorder->recorder) {
@@ -88,6 +85,10 @@
gst_droidcamsrc_recorder_update_vid (GstDroidCamSrcRecorder * recorder,
GstVideoInfo * info, GstCaps * caps)
{
+ if (recorder->codec) {
+ gst_droid_codec_unref (recorder->codec);
+ }
+
recorder->codec =
gst_droid_codec_new_from_caps (caps, GST_DROID_CODEC_ENCODER_VIDEO);
recorder->md.parent.width = info->width;
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/droidcodec/gstdroidaenc.c
^
|
@@ -115,6 +115,14 @@
md.max_input_size = info.bpf * enc->rate;
enc->codec = droid_media_codec_create_encoder (&md);
+ // Reset timestamp clock
+ GstClock *clock = GST_ELEMENT_CLOCK (enc);
+ if (clock) {
+ gst_object_ref (clock);
+ GST_ELEMENT_CAST (enc)->base_time = gst_clock_get_time (clock);
+ gst_object_unref (clock);
+ }
+
if (!enc->codec) {
GST_ELEMENT_ERROR (enc, LIBRARY, SETTINGS, NULL,
("Failed to create encoder"));
@@ -507,8 +515,23 @@
data.data.size = info.size;
data.data.data = g_malloc (info.size);
data.sync = false;
- data.ts = GST_TIME_AS_USECONDS (buffer->pts);
+/* Check if the buffer has a valid timestamp, and if not then set it from the
+ * encoder's clock, as some versions of libstagefright throw away frames if
+ * it doesn't increase
+ */
+ GstClockTime ts = GST_BUFFER_TIMESTAMP (buffer);
+ if (!GST_CLOCK_TIME_IS_VALID (ts)) {
+ GST_DEBUG_OBJECT (enc, "Replacing invalid timestamp: %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (ts));
+ GstClock *clock = gst_element_get_clock (enc);
+ if (clock) {
+ ts = gst_clock_get_time (clock) - GST_ELEMENT_CAST (enc)->base_time;
+ GST_DEBUG_OBJECT (enc, "New timestamp: %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (ts));
+ }
+ }
+ data.ts = GST_TIME_AS_USECONDS (ts);
memcpy (data.data.data, info.data, info.size);
gst_buffer_unmap (buffer, &info);
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/droidcodec/gstdroidvdec.c
^
|
@@ -27,6 +27,7 @@
#include "gst/droid/gstdroidmediabuffer.h"
#include "gst/droid/gstdroidbufferpool.h"
#include "plugin.h"
+#include "droidmediaconstants.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <string.h> /* memset() */
@@ -44,12 +45,30 @@
GST_DEBUG_CATEGORY_EXTERN (gst_droid_vdec_debug);
#define GST_CAT_DEFAULT gst_droid_vdec_debug
+#define GST_DROIDVDEC_STATE_LOCK(decoder) \
+ g_mutex_lock (&(decoder)->state_lock)
+
+#define GST_DROIDVDEC_STATE_UNLOCK(decoder) \
+ g_mutex_unlock (&(decoder)->state_lock)
+
+typedef struct
+{
+ int *hal_format;
+ GstVideoFormat gst_format;
+ GstDroidVideoConvertToI420 convert_to_i420;
+ gsize bytes_per_pixel;
+ gsize h_align;
+ gsize v_align;
+
+} GstDroidVideoFormatMap;
+
static GstStaticPadTemplate gst_droidvdec_src_template_factory =
GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SRC_NAME,
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
- (GST_CAPS_FEATURE_MEMORY_DROID_MEDIA_BUFFER, "{YV12}") ";"
+ (GST_CAPS_FEATURE_MEMORY_DROID_MEDIA_QUEUE_BUFFER,
+ GST_DROID_MEDIA_BUFFER_MEMORY_VIDEO_FORMATS) ";"
GST_VIDEO_CAPS_MAKE ("I420")));
static gboolean gst_droidvdec_configure_state (GstVideoDecoder * decoder,
@@ -59,7 +78,10 @@
int32_t height);
static void gst_droidvdec_signal_eos (void *data);
static void gst_droidvdec_buffers_released (void *user);
-static void gst_droidvdec_frame_available (void *user);
+static bool gst_droidvdec_buffer_created (void *user,
+ DroidMediaBuffer * buffer);
+static bool gst_droidvdec_frame_available (void *user,
+ DroidMediaBuffer * buffer);
static void gst_droidvdec_data_available (void *data,
DroidMediaCodecData * encoded);
static gboolean gst_droidvdec_convert_buffer (GstDroidVDec * dec,
@@ -73,25 +95,191 @@
{
GST_LOG_OBJECT (dec, "loop");
- if (!gst_droid_buffer_pool_wait_for_buffer (dec->pool)) {
- goto out;
+ if (droid_media_codec_loop (dec->codec) == DROID_MEDIA_CODEC_LOOP_OK) {
+ GST_LOG_OBJECT (dec, "tick");
+ } else {
+ GST_INFO_OBJECT (dec, "pausing task");
+ gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (GST_VIDEO_DECODER (dec)));
}
+}
- while (droid_media_codec_loop (dec->codec)
- == DROID_MEDIA_CODEC_LOOP_OK) {
- GST_LOG_OBJECT (dec, "tick");
- return;
+static void
+gst_droidvec_copy_plane (guint8 * out, gint stride_out, guint8 * in,
+ gint stride_in, gint width, gint height)
+{
+ int i;
+ for (i = 0; i < height; i++) {
+ orc_memcpy (out, in, width);
+ out += stride_out;
+ in += stride_in;
}
+}
-out:
- GST_INFO_OBJECT (dec, "pausing task");
- gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (GST_VIDEO_DECODER (dec)));
+static void
+gst_droidvec_copy_packed_planes (guint8 * out0, guint8 * out1, gint stride_out,
+ guint8 * in, gint stride_in, gint width, gint height)
+{
+ int x, y;
+ for (y = 0; y < height; y++) {
+ guint8 *row = in;
+ for (x = 0; x < width; x++) {
+ out0[x] = row[0];
+ out1[x] = row[1];
+ row += 2;
+ }
+
+ out0 += stride_out;
+ out1 += stride_out;
+ in += stride_in;
+ }
+}
+
+#define ALIGN_SIZE(size, to) (((size) + to - 1) & ~(to - 1))
+
+static gboolean
+gst_droidvdec_convert_native_to_i420 (GstDroidVDec * dec, GstMapInfo * out,
+ DroidMediaData * in, GstVideoInfo * info, gsize width, gsize height)
+{
+ gsize size = width * height * 3 / 2;
+ gboolean use_external_buffer = out->size != size;
+ guint8 *data = NULL;
+ gboolean ret = TRUE;
+
+ if (use_external_buffer) {
+ GST_DEBUG_OBJECT (dec, "using an external buffer for I420 conversion.");
+ data = g_malloc (size);
+ } else {
+ data = out->data;
+ }
+
+ if (droid_media_convert_to_i420 (dec->convert, in, data) != true) {
+ GST_ELEMENT_ERROR (dec, LIBRARY, FAILED, (NULL),
+ ("failed to convert frame"));
+
+ ret = FALSE;
+ } else if (use_external_buffer) {
+ /* fix up the buffer */
+ /* Code is based on gst-colorconv qcom backend */
+
+ gint stride = GST_VIDEO_INFO_COMP_STRIDE (info, 0);
+ gint strideUV = GST_VIDEO_INFO_COMP_STRIDE (info, 1);
+ guint8 *p = data;
+ guint8 *dst = out->data;
+ int i;
+ int x;
+
+ /* Y */
+ for (i = 0; i < info->height; i++) {
+ orc_memcpy (dst, p, info->width);
+ dst += stride;
+ p += width;
+ }
+
+ /* NOP if height == info->height */
+ p += (height - info->height) * width;
+ /* U and V */
+ for (x = 0; x < 2; x++) {
+ for (i = 0; i < info->height / 2; i++) {
+ orc_memcpy (dst, p, info->width / 2);
+ dst += strideUV;
+ p += width / 2;
+ }
+
+ /* NOP if height == info->height */
+ p += (height - info->height) / 2 * width / 2;
+ }
+ }
+
+ if (use_external_buffer && data) {
+ g_free (data);
+ }
+
+ return ret;
+}
+
+static gboolean
+gst_droidvdec_convert_yuv420_planar_to_i420 (GstDroidVDec * dec,
+ GstMapInfo * out, DroidMediaData * in, GstVideoInfo * info, gsize width,
+ gsize height)
+{
+ /* Buffer is already I420, so we can copy it straight over */
+ /* though we need to handle the cropping */
+
+ GST_DEBUG_OBJECT (dec, "Copying I420 buffer");
+ gint top = dec->crop_rect.top;
+ gint left = dec->crop_rect.left;
+ gint crop_width = dec->crop_rect.right - left;
+ gint crop_height = dec->crop_rect.bottom - top;
+
+ guint8 *y = in->data + (top * width) + left;
+ guint8 *u = in->data + (width * height) + (top * width / 2) + (left / 2);
+ guint8 *v =
+ in->data + (width * height) + (width * height / 4) +
+ (top * width / 2) + (left / 2);
+
+ gst_droidvec_copy_plane (out->data + info->offset[0],
+ info->stride[0], y, width, crop_width, crop_height);
+ gst_droidvec_copy_plane (out->data + info->offset[1],
+ info->stride[1], u, width / 2, crop_width / 2, crop_height / 2);
+ gst_droidvec_copy_plane (out->data + info->offset[2],
+ info->stride[2], v, width / 2, crop_width / 2, crop_height / 2);
+
+ return TRUE;
+}
+
+static gboolean
+gst_droidvdec_convert_yuv420_semi_planar_to_i420 (GstDroidVDec * dec,
+ GstMapInfo * out, DroidMediaData * in, GstVideoInfo * info, gsize width,
+ gsize height)
+{
+ GST_DEBUG_OBJECT (dec, "Converting from OMX_COLOR_FormatYUV420SemiPlanar");
+ gint stride = width;
+ gint slice_height = ALIGN_SIZE (height, 16);
+ gint top = dec->crop_rect.top;
+ gint left = dec->crop_rect.left;
+
+ guint8 *y = in->data + (top * stride) + left;
+ guint8 *uv = in->data + (stride * slice_height) + (top * stride / 2) + left;
+
+ gst_droidvec_copy_plane (out->data + info->offset[0],
+ info->stride[0], y, stride, info->width, info->height);
+ gst_droidvec_copy_packed_planes (out->data + info->offset[1],
+ out->data + info->offset[2], info->stride[1], uv, stride,
+ info->width / 2, info->height / 2);
+
+ return TRUE;
+}
+
+static gboolean
+gst_droidvdec_convert_yuv420_packed_semi_planar_to_i420 (GstDroidVDec * dec,
+ GstMapInfo * out, DroidMediaData * in, GstVideoInfo * info, gsize width,
+ gsize height)
+{
+ /* copy to the output buffer swapping the u and v planes and cropping if necessary */
+ /* NV12 format with 128 byte alignment */
+ GST_DEBUG_OBJECT (dec, "Converting from qcom NV12 semi planar");
+ gint stride = ALIGN_SIZE (width, 128);
+ gint slice_height = ALIGN_SIZE (height, 32);
+ gint top = ALIGN_SIZE (dec->crop_rect.top, 2);
+ gint left = ALIGN_SIZE (dec->crop_rect.left, 2);
+
+ guint8 *y = in->data + (top * stride) + left;
+ guint8 *uv = in->data + (stride * slice_height) + (top * stride / 2) + left;
+
+ gst_droidvec_copy_plane (out->data + info->offset[0],
+ info->stride[0], y, stride, info->width, info->height);
+ gst_droidvec_copy_packed_planes (out->data + info->offset[1],
+ out->data + info->offset[2], info->stride[1], uv, stride,
+ info->width / 2, info->height / 2);
+
+ return TRUE;
}
static gboolean
gst_droidvdec_create_codec (GstDroidVDec * dec, GstBuffer * input)
{
DroidMediaCodecDecoderMetaData md;
+ DroidMediaBufferQueue *queue;
const gchar *droid = gst_droid_codec_get_droid_type (dec->codec_type);
GST_INFO_OBJECT (dec, "create codec of type %s: %dx%d",
@@ -99,31 +287,6 @@
memset (&md, 0x0, sizeof (md));
- /* Let's take care of the buffer pool first */
- if (!dec->pool) {
- GstStructure *config;
-
- dec->pool = gst_droid_buffer_pool_new ();
- config = gst_buffer_pool_get_config (dec->pool);
- /* pass NULL for the caps. We don't have it yet */
- gst_buffer_pool_config_set_params (config, NULL, 0,
- GST_DROID_DEC_NUM_BUFFERS, GST_DROID_DEC_NUM_BUFFERS);
-
- if (!gst_buffer_pool_set_config (dec->pool, config)) {
- GST_ELEMENT_ERROR (dec, STREAM, FAILED, (NULL),
- ("Failed to configure buffer pool"));
- return FALSE;
- }
-
- if (!gst_buffer_pool_set_active (dec->pool, TRUE)) {
- GST_ELEMENT_ERROR (dec, STREAM, FAILED, (NULL),
- ("Failed to activate buffer pool"));
- return FALSE;
- }
- } else {
- gst_buffer_pool_set_flushing (dec->pool, FALSE);
- }
-
md.parent.type = droid;
md.parent.width = dec->in_state->info.width;
md.parent.height = dec->in_state->info.height;
@@ -132,7 +295,7 @@
DROID_MEDIA_CODEC_HW_ONLY | DROID_MEDIA_CODEC_USE_EXTERNAL_LOOP;
md.codec_data.size = 0;
- if (dec->format == GST_VIDEO_FORMAT_I420) {
+ if (!dec->use_hardware_buffers) {
md.parent.flags |= DROID_MEDIA_CODEC_NO_MEDIA_BUFFER;
}
@@ -164,7 +327,7 @@
goto error;
}
- dec->queue = droid_media_codec_get_buffer_queue (dec->codec);
+ queue = droid_media_codec_get_buffer_queue (dec->codec);
{
DroidMediaCodecCallbacks cb;
@@ -174,11 +337,12 @@
droid_media_codec_set_callbacks (dec->codec, &cb, dec);
}
- if (dec->queue) {
+ if (queue) {
DroidMediaBufferQueueCallbacks cb;
cb.buffers_released = gst_droidvdec_buffers_released;
+ cb.buffer_created = gst_droidvdec_buffer_created;
cb.frame_available = gst_droidvdec_frame_available;
- droid_media_buffer_queue_set_callbacks (dec->queue, &cb, dec);
+ droid_media_buffer_queue_set_callbacks (queue, &cb, dec);
} else {
DroidMediaCodecDataCallbacks cb;
cb.data_available = gst_droidvdec_data_available;
@@ -191,7 +355,6 @@
droid_media_codec_destroy (dec->codec);
dec->codec = NULL;
- dec->queue = NULL;
goto error;
}
@@ -205,14 +368,62 @@
return TRUE;
error:
- gst_buffer_pool_set_active (dec->pool, FALSE);
return FALSE;
}
static void
-gst_droidvdec_buffers_released (G_GNUC_UNUSED void *user)
+gst_droidvdec_buffers_released (void *user)
+{
+ GstVideoDecoder *dec = (GstVideoDecoder *) user;
+
+ GstBufferPool *pool = gst_video_decoder_get_buffer_pool (dec);
+
+ if (pool) {
+ gst_droid_buffer_pool_media_buffers_invalidated (pool);
+ gst_object_unref (pool);
+ }
+}
+
+static bool
+gst_droidvdec_buffer_created (void *user, DroidMediaBuffer * buffer)
{
- GST_FIXME ("Not sure what to do here really");
+ GstDroidVDec *dec = (GstDroidVDec *) user;
+ GstVideoDecoder *decoder = GST_VIDEO_DECODER (dec);
+ bool ret = false;
+ GstBufferPool *pool = NULL;
+
+ GST_VIDEO_DECODER_STREAM_LOCK (decoder);
+
+ if (dec->dirty) {
+ GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
+ return false;
+ }
+
+ /* Now we can configure the state */
+ if (G_UNLIKELY (!dec->out_state)) {
+ DroidMediaBufferInfo droid_info;
+
+ droid_media_buffer_get_info (buffer, &droid_info);
+
+ if (!gst_droidvdec_configure_state (decoder, droid_info.width,
+ droid_info.height)) {
+ dec->downstream_flow_ret = GST_FLOW_ERROR;
+ GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
+ return false;
+ }
+ }
+
+ pool = gst_video_decoder_get_buffer_pool (decoder);
+
+ GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
+
+ if (pool) {
+ ret = gst_droid_buffer_pool_bind_media_buffer (pool, buffer);
+
+ gst_object_unref (pool);
+ }
+
+ return ret;
}
static gboolean
@@ -221,9 +432,6 @@
{
gsize height = info->height;
gsize width = info->width;
- gsize size;
- gboolean use_external_buffer;
- guint8 *data = NULL;
gboolean ret;
GstMapInfo map_info;
@@ -231,7 +439,7 @@
if (dec->codec_type->quirks & USE_CODEC_SUPPLIED_WIDTH_VALUE) {
width = dec->codec_reported_width;
- GST_INFO_OBJECT (dec, "using codec supplied width %d", height);
+ GST_INFO_OBJECT (dec, "using codec supplied width %d", width);
}
if (dec->codec_type->quirks & USE_CODEC_SUPPLIED_HEIGHT_VALUE) {
@@ -239,196 +447,123 @@
GST_INFO_OBJECT (dec, "using codec supplied height %d", height);
}
- size = width * height * 3 / 2;
- use_external_buffer = gst_buffer_get_size (out) != size;
- map_info.data = NULL;
-
- if (!gst_buffer_map (out, &map_info, GST_MAP_WRITE)) {
+ if (!dec->convert_to_i420) {
+ GST_ERROR_OBJECT (dec, "no i420 conversion function");
+ ret = FALSE;
+ } else if (!gst_buffer_map (out, &map_info, GST_MAP_WRITE)) {
GST_ERROR_OBJECT (dec, "failed to map buffer");
ret = FALSE;
- goto out;
- }
-
- if (use_external_buffer) {
- GST_DEBUG_OBJECT (dec, "using an external buffer for I420 conversion.");
- data = g_malloc (size);
} else {
- data = map_info.data;
- }
-
- if (droid_media_convert_to_i420 (dec->convert, in, data) != true) {
- GST_ELEMENT_ERROR (dec, LIBRARY, FAILED, (NULL),
- ("failed to convert frame"));
-
- ret = FALSE;
- goto out;
- }
-
- if (use_external_buffer) {
- /* fix up the buffer */
- /* Code is based on gst-colorconv qcom backend */
-
- gint stride = GST_VIDEO_INFO_COMP_STRIDE (info, 0);
- gint strideUV = GST_VIDEO_INFO_COMP_STRIDE (info, 1);
- guint8 *p = data;
- guint8 *dst = map_info.data;
- int i;
- int x;
-
- /* Y */
- for (i = 0; i < info->height; i++) {
- orc_memcpy (dst, p, info->width);
- dst += stride;
- p += width;
- }
-
- /* NOP if height == info->height */
- p += (height - info->height) * width;
- /* U and V */
- for (x = 0; x < 2; x++) {
- for (i = 0; i < info->height / 2; i++) {
- orc_memcpy (dst, p, info->width / 2);
- dst += strideUV;
- p += width / 2;
- }
+ ret = dec->convert_to_i420 (dec, &map_info, in, info, width, height);
- /* NOP if height == info->height */
- p += (height - info->height) / 2 * width / 2;
- }
- }
-
- ret = TRUE;
-
-out:
- if (use_external_buffer && data) {
- g_free (data);
- }
-
- if (map_info.data) {
gst_buffer_unmap (out, &map_info);
}
return ret;
}
-static void
-gst_droidvdec_frame_available (void *user)
+static bool
+gst_droidvdec_frame_available (void *user, DroidMediaBuffer * buffer)
{
GstDroidVDec *dec = (GstDroidVDec *) user;
GstVideoDecoder *decoder = GST_VIDEO_DECODER (dec);
- GstMemory *mem;
guint width, height;
GstVideoCodecFrame *frame;
- DroidMediaBuffer *buffer;
- GstBuffer *buff;
- DroidMediaRect rect;
+ GstBuffer *buff = NULL;
+ GstBufferPool *pool;
GstVideoCropMeta *crop_meta;
- DroidMediaBufferCallbacks cb;
- GstFlowReturn flow_ret;
- int64_t ts;
+ DroidMediaBufferInfo droid_info;
+ GstVideoInfo video_info;
+ bool ret = true;
GST_DEBUG_OBJECT (dec, "frame available");
GST_VIDEO_DECODER_STREAM_LOCK (decoder);
if (dec->dirty) {
- goto acquire_and_release;
+ goto error;
}
if (dec->downstream_flow_ret != GST_FLOW_OK) {
GST_DEBUG_OBJECT (dec, "not handling frame in error state: %s",
gst_flow_get_name (dec->downstream_flow_ret));
- goto acquire_and_release;
- }
-
- flow_ret = gst_buffer_pool_acquire_buffer (dec->pool, &buff, NULL);
-
- if (flow_ret != GST_FLOW_OK) {
- GST_WARNING_OBJECT (dec, "failed to acquire buffer from pool: %s",
- gst_flow_get_name (flow_ret));
- goto acquire_and_release;
+ goto error;
}
- cb.ref = (DroidMediaCallback) gst_buffer_ref;
- cb.unref = (DroidMediaCallback) gst_buffer_unref;
- cb.data = buff;
+ pool = gst_video_decoder_get_buffer_pool (decoder);
- mem =
- gst_droid_media_buffer_allocator_alloc (dec->allocator, dec->queue, &cb);
+ if (G_UNLIKELY (!pool)) {
+ GST_WARNING_OBJECT (dec, "video decoder doesn't have a buffer pool");
+ } else {
+ buff = gst_droid_buffer_pool_acquire_media_buffer (pool, buffer);
- if (!mem) {
- /* TODO: what should we do here? */
- GST_ERROR_OBJECT (dec, "failed to acquire buffer from droidmedia");
- gst_buffer_unref (buff);
- GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
- return;
+ gst_object_unref (pool);
}
- buffer = gst_droid_media_buffer_memory_get_buffer (mem);
- width = droid_media_buffer_get_width (buffer);
- height = droid_media_buffer_get_height (buffer);
- rect = droid_media_buffer_get_crop_rect (buffer);
- ts = droid_media_buffer_get_timestamp (buffer);
+ if (G_UNLIKELY (!buff)) {
+ GST_DEBUG_OBJECT (dec,
+ "unable to acquire a gstreamer buffer for a droid media buffer");
+ goto error;
+ }
- gst_buffer_insert_memory (buff, 0, mem);
+ droid_media_buffer_get_info (buffer, &droid_info);
- /* Now we can configure the state */
- if (G_UNLIKELY (!dec->out_state)) {
- if (!gst_droidvdec_configure_state (decoder, width, height)) {
- dec->downstream_flow_ret = GST_FLOW_ERROR;
- gst_buffer_unref (buff);
- GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
- return;
- }
+ if (dec->bytes_per_pixel != 0) {
+ width = ALIGN_SIZE (droid_info.stride, dec->h_align) / dec->bytes_per_pixel;
+ height = ALIGN_SIZE (droid_info.height, dec->v_align);
+ } else {
+ width = droid_info.width;
+ height = droid_info.height;
}
- /* we don't want to access the memory afterwards */
- mem = NULL;
- buffer = NULL;
+ gst_video_info_set_format (&video_info, dec->format, width, height);
crop_meta = gst_buffer_add_video_crop_meta (buff);
- crop_meta->x = rect.left;
- crop_meta->y = rect.top;
- crop_meta->width = rect.right - rect.left;
- crop_meta->height = rect.bottom - rect.top;
+ crop_meta->x = droid_info.crop_rect.left;
+ crop_meta->y = droid_info.crop_rect.top;
+ crop_meta->width = droid_info.crop_rect.right - droid_info.crop_rect.left;
+ crop_meta->height = droid_info.crop_rect.bottom - droid_info.crop_rect.top;
GST_LOG_OBJECT (dec, "crop info: x=%d, y=%d, w=%d, h=%d", crop_meta->x,
crop_meta->y, crop_meta->width, crop_meta->height);
- gst_buffer_add_video_meta (buff, GST_VIDEO_FRAME_FLAG_NONE,
- GST_VIDEO_FORMAT_YV12, width, height);
+ gst_buffer_add_video_meta_full (buff, GST_VIDEO_FRAME_FLAG_NONE, dec->format,
+ droid_info.width, droid_info.height, video_info.finfo->n_planes,
+ video_info.offset, video_info.stride);
frame = gst_video_decoder_get_oldest_frame (decoder);
if (G_UNLIKELY (!frame)) {
/* TODO: what should we do here? */
GST_WARNING_OBJECT (dec, "buffer without frame");
- gst_buffer_unref (buff);
- GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
- return;
- }
- frame->output_buffer = buff;
+ /* We've acquired the droid media buffer at this point and unref'ing the GstBuffer
+ * will release it back to the queue, so from a queue manangement perspective this
+ * function has succeeded. */
+ gst_buffer_unref (buff);
+ } else {
+ frame->output_buffer = buff;
- /* We get the timestamp in ns already */
- frame->pts = ts;
+ /* We get the timestamp in ns already */
+ frame->pts = droid_info.timestamp;
- /* we have a ref acquired by _get_oldest_frame()
- * but we don't drop it because _finish_frame() assumes 2 refs.
- * A ref that we obtained via _handle_frame() which we dropped already
- * so we need to compensate it and the 2nd ref which is already owned by
- * the base class GstVideoDecoder
- */
- dec->downstream_flow_ret = gst_droidvdec_finish_frame (decoder, frame);
+ /* we have a ref acquired by _get_oldest_frame()
+ * but we don't drop it because _finish_frame() assumes 2 refs.
+ * A ref that we obtained via _handle_frame() which we dropped already
+ * so we need to compensate it and the 2nd ref which is already owned by
+ * the base class GstVideoDecoder
+ */
+ dec->downstream_flow_ret = gst_droidvdec_finish_frame (decoder, frame);
+ }
+out:
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
- return;
-acquire_and_release:
- /* we can not use our cb struct here so ask droidmedia to do
- * the work instead */
- droid_media_buffer_queue_acquire_and_release (dec->queue, NULL);
- GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
+ return ret;
+
+error:
+ ret = false;
+ goto out;
}
static void
@@ -536,20 +671,16 @@
GST_DEBUG_OBJECT (dec, "codec signaled EOS");
- g_mutex_lock (&dec->state_lock);
+ GST_DROIDVDEC_STATE_LOCK (dec);
if (dec->state != GST_DROID_VDEC_STATE_WAITING_FOR_EOS) {
GST_WARNING_OBJECT (dec, "codec signaled EOS but we are not expecting it");
}
- if (dec->pool) {
- gst_buffer_pool_set_flushing (dec->pool, TRUE);
- }
-
dec->state = GST_DROID_VDEC_STATE_EOS;
g_cond_signal (&dec->state_cond);
- g_mutex_unlock (&dec->state_lock);
+ GST_DROIDVDEC_STATE_UNLOCK (dec);
}
static void
@@ -559,19 +690,19 @@
GST_DEBUG_OBJECT (dec, "codec error");
- g_mutex_lock (&dec->state_lock);
+ GST_DROIDVDEC_STATE_LOCK (dec);
if (dec->state == GST_DROID_VDEC_STATE_WAITING_FOR_EOS) {
/* Gotta love Android. We will ignore errors if we are expecting EOS */
g_cond_signal (&dec->state_cond);
- g_mutex_unlock (&dec->state_lock);
- goto out;
+ GST_DROIDVDEC_STATE_UNLOCK (dec);
+ return;
}
/* just in case */
g_cond_signal (&dec->state_cond);
- g_mutex_unlock (&dec->state_lock);
+ GST_DROIDVDEC_STATE_UNLOCK (dec);
GST_VIDEO_DECODER_STREAM_LOCK (dec);
dec->downstream_flow_ret = GST_FLOW_ERROR;
@@ -579,11 +710,6 @@
GST_ELEMENT_ERROR (dec, LIBRARY, FAILED, NULL,
("error 0x%x from android codec", -err));
-
-out:
- if (dec->pool) {
- gst_buffer_pool_set_flushing (dec->pool, TRUE);
- }
}
static int
@@ -614,22 +740,122 @@
GstDroidVDec *dec = GST_DROIDVDEC (decoder);
DroidMediaCodecMetaData md;
DroidMediaRect rect;
+ DroidMediaColourFormatConstants constants;
+ int format_index, format_count;
+
+ const GstDroidVideoFormatMap formats[] = {
+ {&constants.QOMX_COLOR_FormatYUV420PackedSemiPlanar32m,
+ GST_VIDEO_FORMAT_NV12,
+ gst_droidvdec_convert_yuv420_packed_semi_planar_to_i420, 1, 128, 32},
+ {&constants.QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka,
+ GST_VIDEO_FORMAT_NV12_64Z32, NULL, 0, 0, 0},
+ {&constants.OMX_COLOR_FormatYUV420Planar,
+ GST_VIDEO_FORMAT_I420,
+ gst_droidvdec_convert_yuv420_planar_to_i420, 1, 4, 1},
+ {&constants.OMX_COLOR_FormatYUV420PackedPlanar,
+ GST_VIDEO_FORMAT_I420, NULL,
+ 1, 1, 1},
+ {&constants.OMX_COLOR_FormatYUV420SemiPlanar, GST_VIDEO_FORMAT_NV12,
+ gst_droidvdec_convert_yuv420_semi_planar_to_i420, 1, 1, 1},
+ {&constants.OMX_COLOR_FormatL8, GST_VIDEO_FORMAT_GRAY8, NULL, 1, 1,
+ 1},
+ {&constants.OMX_COLOR_FormatYUV422SemiPlanar, GST_VIDEO_FORMAT_NV16,
+ NULL,
+ 1, 1, 1},
+ {&constants.OMX_COLOR_FormatYCbYCr, GST_VIDEO_FORMAT_YUY2, NULL, 1,
+ 1, 1},
+ {&constants.OMX_COLOR_FormatYCrYCb, GST_VIDEO_FORMAT_YVYU, NULL, 1,
+ 1, 1},
+ {&constants.OMX_COLOR_FormatCbYCrY, GST_VIDEO_FORMAT_UYVY, NULL, 1,
+ 1, 1},
+ {&constants.OMX_COLOR_Format32bitARGB8888,
+ /* There is a mismatch in omxil specification 4.2.1 between
+ * OMX_COLOR_Format32bitARGB8888 and its description
+ * Follow the description */
+ GST_VIDEO_FORMAT_ABGR,
+ NULL,
+ 4, 4, 1},
+ {&constants.OMX_COLOR_Format32bitBGRA8888,
+ /* Same issue as OMX_COLOR_Format32bitARGB8888 */
+ GST_VIDEO_FORMAT_ARGB,
+ NULL,
+ 4, 4, 1},
+ {&constants.OMX_COLOR_Format16bitRGB565, GST_VIDEO_FORMAT_RGB16,
+ NULL, 2, 4,
+ 1},
+ {&constants.OMX_COLOR_Format16bitBGR565, GST_VIDEO_FORMAT_BGR16,
+ NULL, 2, 4,
+ 1}
+ };
memset (&md, 0x0, sizeof (md));
memset (&rect, 0x0, sizeof (rect));
+ droid_media_colour_format_constants_init (&constants);
droid_media_codec_get_output_info (dec->codec, &md, &rect);
GST_INFO_OBJECT (dec,
- "codec reported state: width: %d, height: %d, crop: %d,%d %d,%d",
- md.width, md.height, rect.left, rect.top, rect.right, rect.bottom);
+ "codec reported state: colour: %d, width: %d, height: %d, crop: %d,%d %d,%d",
+ md.hal_format, md.width, md.height, rect.left, rect.top, rect.right,
+ rect.bottom);
dec->codec_reported_height = md.height;
dec->codec_reported_width = md.width;
+ dec->hal_format = md.hal_format;
+
+ if (!dec->use_hardware_buffers && !dec->convert) {
+ if (dec->codec_type->quirks & DONT_USE_DROID_CONVERT_VALUE) {
+ GST_INFO_OBJECT (dec, "not using droid convert binary");
+ } else {
+ dec->convert = droid_media_convert_create ();
+ }
+ }
- if (dec->format == GST_VIDEO_FORMAT_I420) {
- width = rect.right - rect.left;
- height = rect.bottom - rect.top;
+ format_count = sizeof (formats) / sizeof (formats[0]);
+ for (format_index = 0; format_index < format_count; ++format_index) {
+ if (*formats[format_index].hal_format == md.hal_format) {
+ break;
+ }
+ }
+
+ if (dec->use_hardware_buffers) {
+ if (format_index < format_count) {
+ dec->format = formats[format_index].gst_format;
+ dec->bytes_per_pixel = formats[format_index].bytes_per_pixel;
+ dec->h_align = formats[format_index].h_align;
+ dec->v_align = formats[format_index].v_align;
+ } else {
+ GST_INFO_OBJECT (dec, "The HAL codec format 0x%x is unrecognized",
+ md.hal_format);
+ /* This should be GST_VIDEO_FORMAT_ENCODED but the videoconv? element
+ can't do passthrough of that format. Since the format can't be
+ identified the reported size of the buffer will be zero and it
+ won't be possible to map it so reporting the wrong format should
+ be harmless. */
+ dec->format = GST_VIDEO_FORMAT_YV12;
+ dec->bytes_per_pixel = 0;
+ dec->h_align = 0;
+ dec->v_align = 0;
+ }
+ } else {
+ if (dec->convert) {
+ dec->convert_to_i420 = gst_droidvdec_convert_native_to_i420;
+ } else if (format_index < format_count) {
+ dec->convert_to_i420 = formats[format_index].convert_to_i420;
+ } else {
+ dec->convert_to_i420 = NULL;
+ }
+
+ if (dec->convert_to_i420) {
+ dec->format = GST_VIDEO_FORMAT_I420;
+
+ width = rect.right - rect.left;
+ height = rect.bottom - rect.top;
+ } else {
+ GST_ELEMENT_ERROR (dec, STREAM, FORMAT, (NULL),
+ ("HAL codec format 0x%x is unsupported", md.hal_format));
+ goto error;
+ }
}
GST_INFO_OBJECT (dec, "configuring state: width=%d, height=%d", width,
@@ -642,25 +868,19 @@
g_assert (dec->out_state->caps == NULL);
dec->out_state->caps = gst_video_info_to_caps (&dec->out_state->info);
- if (dec->out_state->info.finfo->format == GST_VIDEO_FORMAT_YV12) {
+ if (dec->use_hardware_buffers) {
GstCapsFeatures *feature =
- gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_DROID_MEDIA_BUFFER,
+ gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_DROID_MEDIA_QUEUE_BUFFER,
NULL);
gst_caps_set_features (dec->out_state->caps, 0, feature);
} else {
memcpy (&dec->crop_rect, &rect, sizeof (rect));
- if (!dec->convert) {
- dec->convert = droid_media_convert_create ();
- }
- if (!dec->convert) {
- GST_ELEMENT_ERROR (dec, LIBRARY, INIT, (NULL),
- ("Failed to create I420 converter"));
- goto error;
+ if (dec->convert) {
+ droid_media_convert_set_crop_rect (dec->convert, rect, md.width,
+ md.height);
+ GST_INFO_OBJECT (dec, "using colour conversion for output buffers");
}
-
- droid_media_convert_set_crop_rect (dec->convert, rect, md.width, md.height);
- GST_INFO_OBJECT (dec, "using I420 conversion for output buffers");
}
if (!gst_video_decoder_negotiate (decoder)) {
@@ -688,6 +908,80 @@
}
static gboolean
+gst_droidvdec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query)
+{
+ GstCaps *caps;
+ GstCapsFeatures *features;
+
+ gst_query_parse_allocation (query, &caps, NULL);
+
+ features = gst_caps_get_features (caps, 0);
+
+ /* If we've negotiated caps with the droid memory queue buffers feature then ensure we use
+ * a buffer pool that supports that. Otherwise let the default implementation decide. */
+ if (gst_caps_features_contains (features,
+ GST_CAPS_FEATURE_MEMORY_DROID_MEDIA_QUEUE_BUFFER)) {
+ GstBufferPool *pool = NULL;
+ gint i;
+ guint min, max;
+ guint size;
+ gint count = gst_query_get_n_allocation_pools (query);
+
+ for (i = 0; i < count; ++i) {
+ GstAllocator *allocator;
+ GstStructure *config;
+
+ gst_query_parse_nth_allocation_pool (query, i, &pool, &size, &min, &max);
+ config = gst_buffer_pool_get_config (pool);
+ gst_buffer_pool_config_get_allocator (config, &allocator, NULL);
+ if (allocator
+ && g_strcmp0 (allocator->mem_type,
+ GST_ALLOCATOR_DROID_MEDIA_BUFFER) == 0) {
+ break;
+ } else {
+ gst_object_unref (pool);
+ pool = NULL;
+ }
+ }
+
+ /* The downstream may have other ideas about what the pool size should be but the
+ * queue we're working with has a fixed size so that's the number of buffers we'll
+ * go with. */
+ min = 0;
+ max = droid_media_buffer_queue_length ();
+
+ if (!pool) {
+ /* A downstream which understands the queue buffers should also have provided a pool
+ * but for completeness add this a fallback. */
+ GstStructure *config;
+ GstVideoInfo video_info;
+ gst_video_info_from_caps (&video_info, caps);
+
+ pool = gst_droid_buffer_pool_new ();
+ size = video_info.finfo->format == GST_VIDEO_FORMAT_ENCODED
+ ? 1 : video_info.size;
+
+ config = gst_buffer_pool_get_config (pool);
+ gst_buffer_pool_config_set_params (config, caps, size, min, max);
+
+ if (!gst_buffer_pool_set_config (pool, config)) {
+ GST_ERROR_OBJECT (decoder, "Failed to set buffer pool configuration");
+ }
+ }
+
+ gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
+ while (gst_query_get_n_allocation_pools (query) > 1)
+ gst_query_remove_nth_allocation_pool (query, 1);
+
+ gst_object_unref (pool);
+ pool = NULL;
+ }
+
+ return GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (decoder,
+ query);
+}
+
+static gboolean
gst_droidvdec_stop (GstVideoDecoder * decoder)
{
GstDroidVDec *dec = GST_DROIDVDEC (decoder);
@@ -698,7 +992,6 @@
droid_media_codec_stop (dec->codec);
droid_media_codec_destroy (dec->codec);
dec->codec = NULL;
- dec->queue = NULL;
}
if (dec->in_state) {
@@ -723,10 +1016,6 @@
dec->convert = NULL;
}
- if (dec->pool) {
- gst_buffer_pool_set_active (dec->pool, FALSE);
- }
-
return TRUE;
}
@@ -740,16 +1029,8 @@
*/
GST_DEBUG_OBJECT (dec, "stop loop");
- if (dec->pool) {
- gst_buffer_pool_set_flushing (dec->pool, TRUE);
- }
-
gst_pad_stop_task (GST_VIDEO_DECODER_SRC_PAD (GST_VIDEO_DECODER (dec)));
- if (dec->pool) {
- gst_buffer_pool_set_flushing (dec->pool, FALSE);
- }
-
dec->running = FALSE;
}
@@ -762,11 +1043,6 @@
gst_droidvdec_stop (GST_VIDEO_DECODER (dec));
- if (dec->pool) {
- gst_object_unref (dec->pool);
- dec->pool = NULL;
- }
-
gst_object_unref (dec->allocator);
dec->allocator = NULL;
@@ -824,8 +1100,8 @@
{
GstDroidVDec *dec = GST_DROIDVDEC (decoder);
GstCaps *caps, *template_caps;
- GstStructure *s;
- const gchar *format;
+ GstCapsFeatures *features;
+ guint i, count;
/*
* destroying the droidmedia codec here will cause stagefright to call abort.
@@ -860,15 +1136,20 @@
GST_DEBUG_OBJECT (dec, "peer caps %" GST_PTR_FORMAT, caps);
- caps = gst_caps_truncate (caps);
- caps = gst_caps_fixate (caps);
+ dec->use_hardware_buffers = FALSE;
+
+ count = gst_caps_get_size (caps);
+ for (i = 0; i < count; ++i) {
+ features = gst_caps_get_features (caps, i);
+ if (gst_caps_features_contains
+ (features, GST_CAPS_FEATURE_MEMORY_DROID_MEDIA_QUEUE_BUFFER)) {
+ dec->use_hardware_buffers = TRUE;
+ }
+ }
- s = gst_caps_get_structure (caps, 0);
- format = gst_structure_get_string (s, "format");
- dec->format = gst_video_format_from_string (format);
gst_caps_unref (caps);
- if (G_UNLIKELY (format == GST_VIDEO_FORMAT_UNKNOWN)) {
+ if (G_UNLIKELY (count == 0)) {
GST_ELEMENT_ERROR (dec, STREAM, FORMAT, (NULL), ("Failed to parse caps"));
return FALSE;
}
@@ -895,47 +1176,56 @@
GST_DEBUG_OBJECT (dec, "finish");
- g_mutex_lock (&dec->state_lock);
+ GST_DROIDVDEC_STATE_LOCK (dec);
/* since we release the stream lock, we can get called again */
if (dec->state == GST_DROID_VDEC_STATE_WAITING_FOR_EOS) {
GST_DEBUG_OBJECT (dec, "already finishing");
- g_mutex_unlock (&dec->state_lock);
+ GST_DROIDVDEC_STATE_UNLOCK (dec);
return GST_FLOW_NOT_SUPPORTED;
}
if (dec->codec && dec->state == GST_DROID_VDEC_STATE_OK) {
+ GstBufferPool *pool = gst_video_decoder_get_buffer_pool (decoder);
+
GST_INFO_OBJECT (dec, "draining");
dec->state = GST_DROID_VDEC_STATE_WAITING_FOR_EOS;
droid_media_codec_drain (dec->codec);
- } else {
- goto out;
- }
- /* release the lock to allow _frame_available () to do its job */
- GST_LOG_OBJECT (dec, "releasing stream lock");
- GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
- /* Now we wait for the codec to signal EOS */
- g_cond_wait (&dec->state_cond, &dec->state_lock);
- GST_VIDEO_DECODER_STREAM_LOCK (decoder);
- GST_LOG_OBJECT (dec, "acquired stream lock");
+ /* release the lock to allow _frame_available () to do its job */
+ GST_LOG_OBJECT (dec, "releasing stream lock");
+ GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
+ /* Now we wait for the codec to signal EOS */
+ g_cond_wait (&dec->state_cond, &dec->state_lock);
- /* We drained the codec. Better to recreate it. */
- if (dec->codec) {
- droid_media_codec_stop (dec->codec);
- droid_media_codec_destroy (dec->codec);
- dec->codec = NULL;
- dec->queue = NULL;
- }
+ droid_media_buffer_queue_set_callbacks (droid_media_codec_get_buffer_queue
+ (dec->codec), NULL, NULL);
- dec->dirty = TRUE;
+ GST_DROIDVDEC_STATE_UNLOCK (dec);
+
+ if (pool) {
+ gst_droid_buffer_pool_media_buffers_invalidated (pool);
+ gst_object_unref (pool);
+ }
+
+ GST_VIDEO_DECODER_STREAM_LOCK (decoder);
+ GST_DROIDVDEC_STATE_LOCK (dec);
+ GST_LOG_OBJECT (dec, "acquired stream lock");
+
+ if (dec->codec) {
+ droid_media_codec_stop (dec->codec);
+ droid_media_codec_destroy (dec->codec);
+ dec->codec = NULL;
+ }
+
+ dec->dirty = TRUE;
+ }
-out:
dec->state = GST_DROID_VDEC_STATE_OK;
- GST_DEBUG_OBJECT (dec, "finished");
+ GST_DROIDVDEC_STATE_UNLOCK (dec);
- g_mutex_unlock (&dec->state_lock);
+ GST_DEBUG_OBJECT (dec, "finished");
return GST_FLOW_OK;
}
@@ -972,14 +1262,18 @@
goto error;
}
- g_mutex_lock (&dec->state_lock);
+ GST_DROIDVDEC_STATE_LOCK (dec);
if (dec->state == GST_DROID_VDEC_STATE_EOS) {
GST_WARNING_OBJECT (dec, "got frame in eos state");
- g_mutex_unlock (&dec->state_lock);
+ GST_DROIDVDEC_STATE_UNLOCK (dec);
ret = GST_FLOW_EOS;
goto error;
+ } else if (dec->state == GST_DROID_VDEC_STATE_WAITING_FOR_EOS) {
+ GST_DROIDVDEC_STATE_UNLOCK (dec);
+ ret = GST_FLOW_FLUSHING;
+ goto error;
}
- g_mutex_unlock (&dec->state_lock);
+ GST_DROIDVDEC_STATE_UNLOCK (dec);
/* We must create the codec before we process any data. _create_codec will call
* construct_decoder_codec_data which will store the nal prefix length for H264.
@@ -1034,6 +1328,7 @@
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
droid_media_codec_queue (dec->codec, &data, &cb);
GST_VIDEO_DECODER_STREAM_LOCK (decoder);
+
GST_LOG_OBJECT (dec, "acquired stream lock");
/* from now on decoder owns a frame reference */
@@ -1045,15 +1340,15 @@
goto unref;
}
- g_mutex_lock (&dec->state_lock);
+ GST_DROIDVDEC_STATE_LOCK (dec);
if (dec->state == GST_DROID_VDEC_STATE_EOS) {
GST_WARNING_OBJECT (dec, "got frame in eos state");
- g_mutex_unlock (&dec->state_lock);
+ GST_DROIDVDEC_STATE_UNLOCK (dec);
ret = GST_FLOW_EOS;
goto unref;
}
- g_mutex_unlock (&dec->state_lock);
+ GST_DROIDVDEC_STATE_UNLOCK (dec);
ret = GST_FLOW_OK;
@@ -1070,7 +1365,7 @@
/* don't leak the frame */
gst_video_decoder_release_frame (decoder, frame);
- return ret;
+ goto out;
}
static gboolean
@@ -1089,12 +1384,15 @@
* We will just mark the decoder as "dirty" so the next handle_frame can recreate it
*/
- dec->dirty = TRUE;
+
dec->downstream_flow_ret = GST_FLOW_OK;
- g_mutex_lock (&dec->state_lock);
- dec->state = GST_DROID_VDEC_STATE_OK;
- g_mutex_unlock (&dec->state_lock);
+ GST_DROIDVDEC_STATE_LOCK (dec);
+ if (dec->state != GST_DROID_VDEC_STATE_WAITING_FOR_EOS) {
+ dec->dirty = TRUE;
+ dec->state = GST_DROID_VDEC_STATE_OK;
+ }
+ GST_DROIDVDEC_STATE_UNLOCK (dec);
return TRUE;
}
@@ -1143,7 +1441,6 @@
gst_video_decoder_set_needs_format (GST_VIDEO_DECODER (dec), TRUE);
dec->codec = NULL;
- dec->queue = NULL;
dec->codec_type = NULL;
dec->downstream_flow_ret = GST_FLOW_OK;
dec->state = GST_DROID_VDEC_STATE_OK;
@@ -1158,7 +1455,6 @@
dec->in_state = NULL;
dec->out_state = NULL;
dec->convert = NULL;
- dec->pool = NULL;
}
static void
@@ -1196,6 +1492,8 @@
gstvideodecoder_class->stop = GST_DEBUG_FUNCPTR (gst_droidvdec_stop);
gstvideodecoder_class->set_format =
GST_DEBUG_FUNCPTR (gst_droidvdec_set_format);
+ gstvideodecoder_class->decide_allocation =
+ GST_DEBUG_FUNCPTR (gst_droidvdec_decide_allocation);
gstvideodecoder_class->finish = GST_DEBUG_FUNCPTR (gst_droidvdec_finish);
gstvideodecoder_class->handle_frame =
GST_DEBUG_FUNCPTR (gst_droidvdec_handle_frame);
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/droidcodec/gstdroidvdec.h
^
|
@@ -44,6 +44,10 @@
typedef struct _GstDroidVDecClass GstDroidVDecClass;
typedef enum _GstDroidVDecState GstDroidVDecState;
+typedef gboolean (*GstDroidVideoConvertToI420) (GstDroidVDec * dec,
+ GstMapInfo * out, DroidMediaData * in, GstVideoInfo * info, gsize width,
+ gsize height);
+
enum _GstDroidVDecState
{
GST_DROID_VDEC_STATE_OK,
@@ -56,7 +60,6 @@
{
GstVideoDecoder parent;
DroidMediaCodec *codec;
- DroidMediaBufferQueue *queue;
GstAllocator *allocator;
GstDroidCodec *codec_type;
@@ -65,22 +68,26 @@
GMutex state_lock;
GCond state_cond;
- GstBufferPool *pool;
-
/* protected by decoder stream lock */
GstFlowReturn downstream_flow_ret;
GstBuffer *codec_data;
gboolean dirty;
DroidMediaRect crop_rect;
gboolean running;
+ gboolean use_hardware_buffers;
GstVideoFormat format;
gsize codec_reported_height;
gsize codec_reported_width;
+ gsize bytes_per_pixel;
+ gsize v_align;
+ gsize h_align;
GstVideoCodecState *in_state;
GstVideoCodecState *out_state;
DroidMediaConvert *convert;
+ GstDroidVideoConvertToI420 convert_to_i420;
+ gint32 hal_format;
};
struct _GstDroidVDecClass
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/droideglsink/Makefile.am
^
|
@@ -5,5 +5,5 @@
libgstdroideglsink_la_LIBADD = $(GST_LIBS) $(NGI_LIBS) $(EGL_LIBS)
-libgstdroideglsink_la_SOURCES = gstdroideglsink.c
-noinst_HEADERS = gstdroideglsink.h
+libgstdroideglsink_la_SOURCES = gstdroideglsink.c gstdroidvideotexturesink.c
+noinst_HEADERS = gstdroideglsink.h gstdroidvideotexturesink.h
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/droideglsink/gstdroideglsink.c
^
|
@@ -27,25 +27,16 @@
#include <gst/video/video.h>
#include <gst/interfaces/nemovideotexture.h>
#include "gst/droid/gstdroidmediabuffer.h"
+#include "gst/droid/gstdroidbufferpool.h"
-GST_DEBUG_CATEGORY_EXTERN (gst_droid_eglsink_debug);
-#define GST_CAT_DEFAULT gst_droid_eglsink_debug
-
-static void gst_droideglsink_video_texture_init (NemoGstVideoTextureClass *
- iface);
-
-#define gst_droideglsink_parent_class parent_class
-G_DEFINE_TYPE_WITH_CODE (GstDroidEglSink, gst_droideglsink, GST_TYPE_VIDEO_SINK,
- G_IMPLEMENT_INTERFACE (NEMO_GST_TYPE_VIDEO_TEXTURE,
- gst_droideglsink_video_texture_init));
-
-static GstStaticPadTemplate gst_droideglsink_sink_template_factory =
- GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{YV12, NV21}") "; "
- GST_VIDEO_CAPS_MAKE_WITH_FEATURES
- (GST_CAPS_FEATURE_MEMORY_DROID_MEDIA_BUFFER, "{YV12}")));
+/* Element signals and args */
+enum
+{
+ SHOW_FRAME,
+ FLUSH,
+ BUFFERS_INVALIDATED,
+ LAST_SIGNAL
+};
enum
{
@@ -53,35 +44,29 @@
PROP_EGL_DISPLAY
};
-static void
-gst_droideglsink_destroy_sync (GstDroidEglSink * sink)
-{
- GST_DEBUG_OBJECT (sink, "destroy sync %p", sink->sync);
-
- if (sink->sync) {
- sink->eglDestroySyncKHR (sink->dpy, sink->sync);
- sink->sync = NULL;
- }
-}
+GST_DEBUG_CATEGORY_EXTERN (gst_droid_eglsink_debug);
+#define GST_CAT_DEFAULT gst_droid_eglsink_debug
-static void
-gst_droideglsink_wait_sync (GstDroidEglSink * sink)
-{
- GST_DEBUG_OBJECT (sink, "wait sync %p", sink->sync);
+#define gst_droideglsink_parent_class parent_class
+G_DEFINE_TYPE (GstDroidEglSink, gst_droideglsink, GST_TYPE_VIDEO_SINK);
- if (sink->sync) {
- /* We will behave like Android does */
- EGLint result =
- sink->eglClientWaitSyncKHR (sink->dpy, sink->sync, 0, EGL_FOREVER_KHR);
- if (result == EGL_FALSE) {
- GST_WARNING_OBJECT (sink, "error 0x%x waiting for fence", eglGetError ());
- } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
- GST_WARNING_OBJECT (sink, "timeout waiting for fence");
- }
+static guint gst_droideglsink_signals[LAST_SIGNAL] = { 0 };
- gst_droideglsink_destroy_sync (sink);
- }
-}
+static GstStaticPadTemplate gst_droideglsink_sink_template_factory =
+ GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
+ (GST_CAPS_FEATURE_MEMORY_DROID_MEDIA_BUFFER,
+ GST_DROID_MEDIA_BUFFER_MEMORY_VIDEO_FORMATS) "; "
+ GST_VIDEO_CAPS_MAKE_WITH_FEATURES
+ (GST_CAPS_FEATURE_MEMORY_DROID_MEDIA_QUEUE_BUFFER,
+ GST_DROID_MEDIA_BUFFER_MEMORY_VIDEO_FORMATS) "; "
+ GST_VIDEO_CAPS_MAKE (GST_DROID_MEDIA_BUFFER_MEMORY_VIDEO_FORMATS)));
+
+static void gst_droideglsink_buffer_pool_invalidated (GstBufferPool * pool,
+ GstDroidEglSink * sink);
+static void gst_droideglsink_buffers_invalidated (GstDroidEglSink * sink);
static GstCaps *
gst_droideglsink_get_caps (GstBaseSink * bsink, GstCaps * filter)
@@ -122,171 +107,196 @@
if (!gst_video_info_from_caps (&info, caps)) {
GST_ELEMENT_ERROR (sink, STREAM, FORMAT, (NULL),
- ("ould not locate image format from caps %" GST_PTR_FORMAT, caps));
+ ("Could not locate image format from caps %" GST_PTR_FORMAT, caps));
return FALSE;
}
- sink->fps_n = info.fps_n;
- sink->fps_d = info.fps_d;
-
GST_VIDEO_SINK_WIDTH (vsink) = info.width;
GST_VIDEO_SINK_HEIGHT (vsink) = info.height;
return TRUE;
}
-static void
-gst_droideglsink_get_times (GstBaseSink * bsink, GstBuffer * buf,
- GstClockTime * start, GstClockTime * end)
+static gboolean
+gst_droideglsink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
{
- GstDroidEglSink *sink;
+ GstDroidEglSink *sink = GST_DROIDEGLSINK (bsink);
+ GstBufferPool *previous_pool = NULL;
+ gulong previous_pool_signal_id = 0;
+ GstCaps *caps;
+ guint size;
+ gboolean need_pool;
+ gboolean queue_pool = FALSE;
+ GstVideoInfo video_info;
+ gboolean ret = FALSE;
- sink = GST_DROIDEGLSINK (bsink);
+ gst_query_parse_allocation (query, &caps, &need_pool);
- if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
- *start = GST_BUFFER_TIMESTAMP (buf);
- if (GST_BUFFER_DURATION_IS_VALID (buf)) {
- *end = *start + GST_BUFFER_DURATION (buf);
- } else {
- if (sink->fps_n > 0) {
- *end = *start +
- gst_util_uint64_scale_int (GST_SECOND, sink->fps_d, sink->fps_n);
- }
- }
+ if (!caps) {
+ GST_ERROR_OBJECT (sink, "No query caps");
+ return FALSE;
}
-}
-static gboolean
-gst_droideglsink_start (GstBaseSink * bsink)
-{
- GstDroidEglSink *sink;
+ if (!gst_video_info_from_caps (&video_info, caps)) {
+ GST_ERROR_OBJECT (sink, "Unable to get video caps");
+ return FALSE;
+ }
- sink = GST_DROIDEGLSINK (bsink);
+ g_mutex_lock (&sink->lock);
- GST_DEBUG_OBJECT (sink, "start");
+ previous_pool = sink->pool;
+ previous_pool_signal_id = sink->invalidated_signal_id;
- sink->fps_n = 0;
- sink->fps_d = 1;
+ sink->pool = NULL;
+ sink->invalidated_signal_id = 0;
- sink->image = EGL_NO_IMAGE_KHR;
- sink->sync = NULL;
- sink->eglCreateImageKHR = NULL;
- sink->eglDestroyImageKHR = NULL;
- sink->eglClientWaitSyncKHR = NULL;
- sink->eglDestroySyncKHR = NULL;
+ if (need_pool) {
+ GstBufferPool *pool = NULL;
+ GstStructure *config;
+ guint min = 2;
+ guint max = 0;
+ GstCapsFeatures *features = gst_caps_get_features (caps, 0);
+
+ if (gst_caps_features_contains
+ (features, GST_CAPS_FEATURE_MEMORY_DROID_MEDIA_QUEUE_BUFFER)) {
+ min = 0;
+ max = droid_media_buffer_queue_length ();
+ queue_pool = true;
+ }
- sink->allocator = gst_droid_media_buffer_allocator_new ();
+ size = video_info.finfo->format == GST_VIDEO_FORMAT_ENCODED
+ ? 1 : video_info.size;
- return TRUE;
-}
+ if (previous_pool) {
+ GstCaps *pool_caps;
-static gboolean
-gst_droideglsink_stop (GstBaseSink * bsink)
-{
- GstDroidEglSink *sink;
+ config = gst_buffer_pool_get_config (previous_pool);
+ if (config
+ && gst_buffer_pool_config_get_params (config, &pool_caps, NULL, NULL,
+ NULL) && gst_caps_is_equal (caps, pool_caps)) {
+ gst_buffer_pool_config_set_params (config, caps, size, min, max);
+
+ if (gst_buffer_pool_set_config (previous_pool, config)) {
+ pool = previous_pool;
+ sink->invalidated_signal_id = previous_pool_signal_id;
- sink = GST_DROIDEGLSINK (bsink);
+ previous_pool = NULL;
+ }
+ }
+ }
- GST_DEBUG_OBJECT (sink, "stop");
+ if (!pool) {
+ pool = gst_droid_buffer_pool_new ();
- if (sink->sync) {
- gst_droideglsink_destroy_sync (sink);
- }
+ gst_droid_buffer_pool_set_egl_display (pool, sink->dpy);
- g_mutex_lock (&sink->lock);
+ config = gst_buffer_pool_get_config (pool);
+ gst_buffer_pool_config_set_params (config, caps, size, min, max);
+ if (!gst_buffer_pool_set_config (pool, config)) {
+ GST_ERROR_OBJECT (sink, "Failed to set buffer pool configuration");
+ gst_object_unref (pool);
+ goto out;
+ }
- if (sink->image) {
- GST_WARNING_OBJECT (sink, "destroying leftover EGLImageKHR");
- sink->eglDestroyImageKHR (sink->dpy, sink->image);
- sink->image = EGL_NO_IMAGE_KHR;
- }
+ if (queue_pool) {
+ sink->invalidated_signal_id =
+ g_signal_connect (pool, "buffers-invalidated",
+ G_CALLBACK (gst_droideglsink_buffer_pool_invalidated), sink);
+ }
+ }
+
+ gst_query_add_allocation_pool (query, pool, size, min,
+ min > max ? min : max);
- if (sink->acquired_buffer) {
- GST_WARNING_OBJECT (sink, "freeing leftover acquired buffer");
- gst_buffer_unref (sink->acquired_buffer);
- sink->acquired_buffer = NULL;
+ sink->pool = pool;
}
+ gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
+
+ GST_DEBUG_OBJECT (sink, "proposed allocation");
+
+ ret = TRUE;
+
+out:
g_mutex_unlock (&sink->lock);
- if (sink->last_buffer) {
- GST_INFO_OBJECT (sink, "freeing leftover last buffer");
- gst_buffer_unref (sink->last_buffer);
- sink->last_buffer = NULL;
+ if (previous_pool) {
+ GST_DEBUG_OBJECT (sink, "freed previous pool\n");
+ g_signal_handler_disconnect (previous_pool, previous_pool_signal_id);
+
+ gst_buffer_pool_set_flushing (previous_pool, TRUE);
+ gst_object_unref (previous_pool);
+
+ gst_droideglsink_buffers_invalidated (sink);
}
- gst_object_unref (sink->allocator);
- sink->allocator = NULL;
- return TRUE;
+ return ret;
}
static GstFlowReturn
gst_droideglsink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
{
- GstDroidEglSink *sink;
- gint n_memory;
+ g_signal_emit (vsink, gst_droideglsink_signals[SHOW_FRAME], 0, buf);
- sink = GST_DROIDEGLSINK (vsink);
+ return GST_FLOW_OK;
+}
- GST_DEBUG_OBJECT (sink, "show frame");
+static void
+gst_droideglsink_buffers_invalidated (GstDroidEglSink * sink)
+{
+ g_signal_emit (sink, gst_droideglsink_signals[BUFFERS_INVALIDATED], 0);
+}
- n_memory = gst_buffer_n_memory (buf);
+void
+gst_droideglsink_buffer_pool_invalidated (GstBufferPool * pool,
+ GstDroidEglSink * sink)
+{
+ GstDroidEglSinkClass *klass;
- if (G_UNLIKELY (n_memory == 0)) {
- GST_WARNING_OBJECT (sink, "received an empty buffer");
- /* we will just drop the buffer without errors */
- return GST_FLOW_OK;
- }
+ klass = GST_DROIDEGLSINK_GET_CLASS (sink);
- g_mutex_lock (&sink->lock);
- if (sink->acquired_buffer) {
- GST_INFO_OBJECT (sink,
- "acquired buffer exists. Not replacing current buffer");
- g_mutex_unlock (&sink->lock);
- return GST_FLOW_OK;
+ if (klass->buffers_invalidated) {
+ klass->buffers_invalidated (sink);
}
+}
- GST_LOG_OBJECT (sink, "replacing buffer %p with buffer %p", sink->last_buffer,
- buf);
-
- gst_buffer_replace (&sink->last_buffer, buf);
-
- g_mutex_unlock (&sink->lock);
-
- nemo_gst_video_texture_frame_ready (NEMO_GST_VIDEO_TEXTURE (sink), 0);
-
- return GST_FLOW_OK;
+static void
+gst_droideglsink_free_pool (GstDroidEglSink * sink)
+{
+ if (sink->pool) {
+ if (sink->invalidated_signal_id != 0) {
+ g_signal_handler_disconnect (sink->pool, sink->invalidated_signal_id);
+ sink->invalidated_signal_id = 0;
+ }
+ gst_buffer_pool_set_flushing (sink->pool, TRUE);
+ gst_object_unref (sink->pool);
+ sink->pool = NULL;
+ }
}
-static gboolean
-gst_droideglsink_event (GstBaseSink * bsink, GstEvent * event)
+static GstStateChangeReturn
+gst_droideglsink_change_state (GstElement * element, GstStateChange transition)
{
GstDroidEglSink *sink;
+ GstStateChangeReturn ret;
- sink = GST_DROIDEGLSINK (bsink);
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH_START:
- case GST_EVENT_EOS:
- GST_INFO_OBJECT (sink,
- "emitting frame-ready with -1 after %" GST_PTR_FORMAT, event);
- g_mutex_lock (&sink->lock);
+ sink = GST_DROIDEGLSINK (element);
- if (sink->last_buffer) {
- gst_buffer_unref (sink->last_buffer);
- sink->last_buffer = NULL;
- }
-
- g_mutex_unlock (&sink->lock);
- nemo_gst_video_texture_frame_ready (NEMO_GST_VIDEO_TEXTURE (sink), -1);
- break;
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
- default:
- break;
+ if (ret == GST_STATE_CHANGE_SUCCESS) {
+ switch (transition) {
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ gst_droideglsink_show_frame (GST_VIDEO_SINK (element), NULL);
+ gst_droideglsink_free_pool (sink);
+ break;
+ default:
+ break;
+ }
}
- return GST_BASE_SINK_CLASS (parent_class)->event (bsink, event);
+ return ret;
}
static void
@@ -303,6 +313,7 @@
case PROP_EGL_DISPLAY:
g_mutex_lock (&sink->lock);
sink->dpy = g_value_get_pointer (value);
+ GST_DROIDEGLSINK (sink)->dpy = sink->dpy;
g_mutex_unlock (&sink->lock);
break;
default:
@@ -337,9 +348,9 @@
static void
gst_droideglsink_finalize (GObject * object)
{
- GstDroidEglSink *sink;
+ GstDroidEglSink *sink = GST_DROIDEGLSINK (object);
- sink = GST_DROIDEGLSINK (object);
+ gst_droideglsink_free_pool (sink);
g_mutex_clear (&sink->lock);
@@ -349,21 +360,9 @@
static void
gst_droideglsink_init (GstDroidEglSink * sink)
{
- gst_base_sink_set_last_sample_enabled (GST_BASE_SINK (sink), FALSE);
-
- sink->fps_n = 0;
- sink->fps_d = 0;
- sink->acquired_buffer = NULL;
- sink->last_buffer = NULL;
+ sink->pool = NULL;
sink->dpy = EGL_NO_DISPLAY;
- sink->image = EGL_NO_IMAGE_KHR;
- sink->sync = NULL;
- sink->allocator = NULL;
g_mutex_init (&sink->lock);
- sink->eglCreateImageKHR = NULL;
- sink->eglDestroyImageKHR = NULL;
- sink->eglClientWaitSyncKHR = NULL;
- sink->eglDestroySyncKHR = NULL;
}
static void
@@ -386,386 +385,35 @@
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&gst_droideglsink_sink_template_factory));
- gobject_class->finalize = gst_droideglsink_finalize;
gobject_class->set_property = gst_droideglsink_set_property;
gobject_class->get_property = gst_droideglsink_get_property;
+ gobject_class->finalize = gst_droideglsink_finalize;
+
+ gstelement_class->change_state =
+ GST_DEBUG_FUNCPTR (gst_droideglsink_change_state);
gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_droideglsink_get_caps);
gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_droideglsink_set_caps);
- gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_droideglsink_get_times);
- gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_droideglsink_start);
- gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_droideglsink_stop);
- gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_droideglsink_event);
-
+ gstbasesink_class->propose_allocation =
+ GST_DEBUG_FUNCPTR (gst_droideglsink_propose_allocation);
videosink_class->show_frame = GST_DEBUG_FUNCPTR (gst_droideglsink_show_frame);
+ klass->buffers_invalidated =
+ GST_DEBUG_FUNCPTR (gst_droideglsink_buffers_invalidated);
- g_object_class_override_property (gobject_class, PROP_EGL_DISPLAY,
- "egl-display");
-}
-
-static GstMemory *
-gst_droideglsink_get_droid_media_buffer_memory (GstDroidEglSink * sink,
- GstBuffer * buffer)
-{
- int x, num;
-
- GST_DEBUG_OBJECT (sink, "get droid media buffer memory");
-
- num = gst_buffer_n_memory (buffer);
-
- GST_DEBUG_OBJECT (sink, "examining %d memory items", num);
-
- for (x = 0; x < num; x++) {
- GstMemory *mem = gst_buffer_peek_memory (buffer, x);
-
- if (mem && gst_memory_is_type (mem, GST_ALLOCATOR_DROID_MEDIA_BUFFER)) {
- return mem;
- }
- }
-
- return NULL;
-}
-
-static GstBuffer *
-gst_droideglsink_copy_buffer (GstDroidEglSink * sink, GstBuffer * buffer)
-{
- GstMapInfo info;
- GstVideoInfo format;
- GstBuffer *buff = gst_buffer_new ();
- GstMemory *mem = NULL;
- GstCaps *caps = NULL;
- DroidMediaData data;
- gboolean unmap = FALSE;
- DroidMediaBufferCallbacks cb;
-
- GST_DEBUG_OBJECT (sink, "copy buffer");
-
- if (!gst_pad_has_current_caps (GST_BASE_SINK_PAD (sink))) {
- goto free_and_out;
- }
-
- if (!gst_buffer_copy_into (buff, buffer,
- GST_BUFFER_COPY_FLAGS |
- GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_META, 0, -1)) {
- goto free_and_out;
- }
-
- if (!gst_buffer_map (buffer, &info, GST_MAP_READ)) {
- goto free_and_out;
- }
-
- unmap = TRUE;
-
- caps = gst_pad_get_current_caps (GST_BASE_SINK_PAD (sink));
- if (!gst_video_info_from_caps (&format, caps)) {
- goto free_and_out;
- }
-
- cb.ref = (DroidMediaCallback) gst_buffer_ref;
- cb.unref = (DroidMediaCallback) gst_buffer_unref;
- cb.data = buff;
-
- data.size = info.size;
- data.data = info.data;
-
- mem = gst_droid_media_buffer_allocator_alloc_from_data (sink->allocator,
- &format, &data, &cb);
-
- if (!mem) {
- goto free_and_out;
- }
-
- gst_buffer_append_memory (buff, mem);
- gst_buffer_unmap (buffer, &info);
- gst_caps_unref (caps);
-
- return buff;
-
-free_and_out:
- if (unmap) {
- gst_buffer_unmap (buffer, &info);
- }
-
- gst_buffer_unref (buff);
-
- if (mem) {
- gst_memory_unref (mem);
- }
-
- if (caps) {
- gst_caps_unref (caps);
- }
-
- return NULL;
-}
-
-static gboolean
-gst_droideglsink_populate_egl_proc (GstDroidEglSink * sink)
-{
- GST_DEBUG_OBJECT (sink, "populate egl proc");
-
- if (G_UNLIKELY (!sink->eglCreateImageKHR)) {
- sink->eglCreateImageKHR =
- (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress ("eglCreateImageKHR");
- }
-
- if (G_UNLIKELY (!sink->eglCreateImageKHR)) {
- return FALSE;
- }
-
- if (G_UNLIKELY (!sink->eglDestroyImageKHR)) {
- sink->eglDestroyImageKHR =
- (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress ("eglDestroyImageKHR");
- }
-
- if (G_UNLIKELY (!sink->eglDestroyImageKHR)) {
- return FALSE;
- }
-
- if (G_UNLIKELY (!sink->eglClientWaitSyncKHR)) {
- sink->eglClientWaitSyncKHR = (PFNEGLCLIENTWAITSYNCKHRPROC)
- eglGetProcAddress ("eglClientWaitSyncKHR");
- }
-
- if (G_UNLIKELY (!sink->eglClientWaitSyncKHR)) {
- return FALSE;
- }
-
- if (G_UNLIKELY (!sink->eglDestroySyncKHR)) {
- sink->eglDestroySyncKHR =
- (PFNEGLDESTROYSYNCKHRPROC) eglGetProcAddress ("eglDestroySyncKHR");
- }
-
- if (G_UNLIKELY (!sink->eglDestroySyncKHR)) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* interfaces */
-static gboolean
-gst_droideglsink_acquire_frame (NemoGstVideoTexture * iface)
-{
- GstDroidEglSink *sink;
- gboolean ret = TRUE;
- GstMemory *mem;
-
- sink = GST_DROIDEGLSINK (iface);
-
- GST_DEBUG_OBJECT (sink, "acquire frame");
-
- g_mutex_lock (&sink->lock);
-
- if (sink->acquired_buffer) {
- GST_WARNING_OBJECT (sink, "buffer %p already acquired",
- sink->acquired_buffer);
- ret = FALSE;
- goto unlock_and_out;
- }
-
- if (!sink->last_buffer) {
- GST_WARNING_OBJECT (sink, "no buffers available for acquisition");
- ret = FALSE;
- goto unlock_and_out;
- }
-
- mem =
- gst_droideglsink_get_droid_media_buffer_memory (sink, sink->last_buffer);
-
- if (mem) {
- sink->acquired_buffer = gst_buffer_ref (sink->last_buffer);
- } else {
- /* Construct a new buffer */
- sink->acquired_buffer =
- gst_droideglsink_copy_buffer (sink, sink->last_buffer);
- }
-
- if (!sink->acquired_buffer) {
- ret = FALSE;
- GST_INFO_OBJECT (sink, "failed to acquire a buffer");
- }
-
-unlock_and_out:
- g_mutex_unlock (&sink->lock);
- return ret;
-}
-
-static gboolean
-gst_droideglsink_bind_frame (NemoGstVideoTexture * iface, EGLImageKHR * image)
-{
- GstDroidEglSink *sink;
- gboolean ret = FALSE;
- EGLint eglImgAttrs[] =
- { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE, EGL_NONE };
- GstMemory *mem;
-
- sink = GST_DROIDEGLSINK (iface);
-
- GST_DEBUG_OBJECT (sink, "bind frame");
-
- g_mutex_lock (&sink->lock);
-
- if (sink->dpy == EGL_NO_DISPLAY) {
- GST_WARNING_OBJECT (sink, "can not bind a frame without an EGLDisplay");
- ret = FALSE;
- goto unlock_and_out;
- }
-
- if (!gst_droideglsink_populate_egl_proc (sink)) {
- GST_WARNING_OBJECT (sink, "failed to get needed EGL function pointers");
- ret = FALSE;
- goto unlock_and_out;
- }
-
- if (!sink->acquired_buffer) {
- GST_WARNING_OBJECT (sink, "no frames have been acquired");
- ret = FALSE;
- goto unlock_and_out;
- }
-
- /* Now we are ready */
-
- /* We can safely use peek here because we have an extra ref to the buffer */
- mem =
- gst_droideglsink_get_droid_media_buffer_memory (sink,
- sink->acquired_buffer);
- g_assert (mem);
-
- sink->image =
- sink->eglCreateImageKHR (sink->dpy, EGL_NO_CONTEXT,
- EGL_NATIVE_BUFFER_ANDROID,
- (EGLClientBuffer) gst_droid_media_buffer_memory_get_buffer (mem),
- eglImgAttrs);
-
- /* Buffer will not go anywhere so we should be safe to unlock. */
- g_mutex_unlock (&sink->lock);
-
- *image = sink->image;
-
- ret = TRUE;
- goto out;
-
-unlock_and_out:
- g_mutex_unlock (&sink->lock);
-
-out:
- return ret;
-}
-
-static void
-gst_droideglsink_unbind_frame (NemoGstVideoTexture * iface)
-{
- GstDroidEglSink *sink;
-
- sink = GST_DROIDEGLSINK (iface);
-
- GST_DEBUG_OBJECT (sink, "unbind frame");
-
- g_mutex_lock (&sink->lock);
-
- if (sink->image == EGL_NO_IMAGE_KHR) {
- GST_WARNING_OBJECT (sink, "Cannot unbind without a valid EGLImageKHR");
- goto out;
- }
-
- if (sink->eglDestroyImageKHR (sink->dpy, sink->image) != EGL_TRUE) {
- GST_WARNING_OBJECT (sink, "failed to destroy EGLImageKHR %p", sink->image);
- }
-
- sink->image = EGL_NO_IMAGE_KHR;
-
-out:
- g_mutex_unlock (&sink->lock);
-}
-
-static void
-gst_droideglsink_release_frame (NemoGstVideoTexture * iface, EGLSyncKHR sync)
-{
- GstDroidEglSink *sink;
-
- sink = GST_DROIDEGLSINK (iface);
-
- GST_DEBUG_OBJECT (sink, "release frame");
-
- g_mutex_lock (&sink->lock);
-
- if (sink->acquired_buffer) {
- gst_buffer_unref (sink->acquired_buffer);
- sink->acquired_buffer = NULL;
- }
-
- g_mutex_unlock (&sink->lock);
-
- /* Destroy any previous fence */
- gst_droideglsink_wait_sync (sink);
-
- /* move on */
- sink->sync = sync;
-}
-
-static gboolean
-gst_droideglsink_get_frame_info (NemoGstVideoTexture * iface,
- NemoGstVideoTextureFrameInfo * info)
-{
- GstDroidEglSink *sink;
- gboolean ret;
-
- sink = GST_DROIDEGLSINK (iface);
-
- GST_DEBUG_OBJECT (sink, "get frame info");
-
- g_mutex_lock (&sink->lock);
-
- if (!sink->acquired_buffer->pts) {
- GST_INFO_OBJECT (sink, "no buffer has been acquired");
-
- ret = FALSE;
- goto unlock_and_out;
- }
-
- info->pts = sink->acquired_buffer->pts;
- info->dts = sink->acquired_buffer->dts;
- info->duration = sink->acquired_buffer->duration;
- info->offset = sink->acquired_buffer->offset;
- info->offset_end = sink->acquired_buffer->offset_end;
-
- ret = TRUE;
-
-unlock_and_out:
- g_mutex_unlock (&sink->lock);
-
- return ret;
-}
-
-static GstMeta *
-gst_droideglsink_get_frame_meta (NemoGstVideoTexture * iface, GType api)
-{
- GstDroidEglSink *sink;
- GstMeta *meta = NULL;
-
- sink = GST_DROIDEGLSINK (iface);
-
- GST_DEBUG_OBJECT (sink, "get frame meta");
-
- g_mutex_lock (&sink->lock);
-
- if (sink->acquired_buffer) {
- meta = gst_buffer_get_meta (sink->acquired_buffer, api);
- }
-
- g_mutex_unlock (&sink->lock);
-
- return meta;
-}
-
-static void
-gst_droideglsink_video_texture_init (NemoGstVideoTextureClass * iface)
-{
- iface->acquire_frame = gst_droideglsink_acquire_frame;
- iface->bind_frame = gst_droideglsink_bind_frame;
- iface->unbind_frame = gst_droideglsink_unbind_frame;
- iface->release_frame = gst_droideglsink_release_frame;
- iface->get_frame_info = gst_droideglsink_get_frame_info;
- iface->get_frame_meta = gst_droideglsink_get_frame_meta;
+ gst_droideglsink_signals[SHOW_FRAME] =
+ g_signal_new ("show-frame", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDroidEglSinkClass,
+ signal_show_frame), NULL, NULL, g_cclosure_marshal_generic,
+ G_TYPE_NONE, 1, GST_TYPE_BUFFER);
+ gst_droideglsink_signals[BUFFERS_INVALIDATED] =
+ g_signal_new ("buffers-invalidated", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDroidEglSinkClass,
+ signal_buffers_invalidated), NULL, NULL, g_cclosure_marshal_generic,
+ G_TYPE_NONE, 0);
+
+ g_object_class_install_property (gobject_class, PROP_EGL_DISPLAY,
+ g_param_spec_pointer ("egl-display",
+ "EGL display ",
+ "The application provided EGL display to be used for creating EGLImageKHR objects.",
+ G_PARAM_READWRITE));
}
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/droideglsink/gstdroideglsink.h
^
|
@@ -39,6 +39,8 @@
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_DROIDEGLSINK))
#define GST_IS_DROIDEGLSINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_DROIDEGLSINK))
+#define GST_DROIDEGLSINK_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DROIDEGLSINK, GstDroidEglSinkClass))
typedef struct _GstDroidEglSink GstDroidEglSink;
typedef struct _GstDroidEglSinkClass GstDroidEglSinkClass;
@@ -47,27 +49,20 @@
{
GstVideoSink parent;
- gint fps_n;
- gint fps_d;
-
- GstBuffer *acquired_buffer;
- GstBuffer *last_buffer;
+ GstBufferPool *pool;
+ gulong invalidated_signal_id;
EGLDisplay dpy;
- EGLImageKHR image;
- EGLSyncKHR sync;
GMutex lock;
-
- GstAllocator *allocator;
-
- PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
- PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
- PFNEGLCLIENTWAITSYNCKHRPROC eglClientWaitSyncKHR;
- PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR;
};
struct _GstDroidEglSinkClass
{
GstVideoSinkClass parent_class;
+
+ void (*signal_show_frame) (GstVideoSink *sink, GstBuffer *buffer);
+ void (*signal_buffers_invalidated) (GstVideoSink *sink);
+
+ void (* buffers_invalidated) (GstDroidEglSink *sink);
};
GType gst_droideglsink_get_type (void);
|
[-]
[+]
|
Added |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/droideglsink/gstdroidvideotexturesink.c
^
|
@@ -0,0 +1,648 @@
+/*
+ * gst-droid
+ *
+ * Copyright (C) 2014 Mohammed Sameer <msameer@foolab.org>
+ * Copyright (C) 2015 Jolla LTD.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gstdroidvideotexturesink.h"
+#include <gst/video/video.h>
+#include <gst/interfaces/nemoeglimagememory.h>
+#include <gst/interfaces/nemovideotexture.h>
+#include "gst/droid/gstdroidmediabuffer.h"
+#include "gst/droid/gstdroidbufferpool.h"
+
+GST_DEBUG_CATEGORY_EXTERN (gst_droid_videotexturesink_debug);
+#define GST_CAT_DEFAULT gst_droid_videotexturesink_debug
+
+static void
+gst_droidvideotexturesink_video_texture_init (NemoGstVideoTextureClass * iface);
+
+#define gst_droidvideotexturesink_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstDroidVideoTextureSink, gst_droidvideotexturesink,
+ GST_TYPE_DROIDEGLSINK, G_IMPLEMENT_INTERFACE (NEMO_GST_TYPE_VIDEO_TEXTURE,
+ gst_droidvideotexturesink_video_texture_init));
+
+enum
+{
+ PROP_0,
+ PROP_EGL_DISPLAY
+};
+
+static void
+gst_droidvideotexturesink_destroy_sync (GstDroidVideoTextureSink * sink)
+{
+ GST_DEBUG_OBJECT (sink, "destroy sync %p", sink->sync);
+
+ if (sink->sync) {
+ sink->eglDestroySyncKHR (sink->dpy, sink->sync);
+ sink->sync = NULL;
+ }
+}
+
+static void
+gst_droidvideotexturesink_wait_sync (GstDroidVideoTextureSink * sink)
+{
+ GST_DEBUG_OBJECT (sink, "wait sync %p", sink->sync);
+
+ if (sink->sync) {
+ /* We will behave like Android does */
+ EGLint result =
+ sink->eglClientWaitSyncKHR (sink->dpy, sink->sync, 0, EGL_FOREVER_KHR);
+ if (result == EGL_FALSE) {
+ GST_WARNING_OBJECT (sink, "error 0x%x waiting for fence", eglGetError ());
+ } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+ GST_WARNING_OBJECT (sink, "timeout waiting for fence");
+ }
+
+ gst_droidvideotexturesink_destroy_sync (sink);
+ }
+}
+
+static gboolean
+gst_droidvideotexturesink_set_caps (GstBaseSink * bsink, GstCaps * caps)
+{
+ GstDroidVideoTextureSink *sink;
+ GstVideoSink *vsink;
+ GstVideoInfo info;
+
+ sink = GST_DROIDVIDEOTEXTURESINK (bsink);
+ vsink = GST_VIDEO_SINK (bsink);
+
+ GST_DEBUG_OBJECT (sink, "set caps with %" GST_PTR_FORMAT, caps);
+
+ if (!gst_video_info_from_caps (&info, caps)) {
+ GST_ELEMENT_ERROR (sink, STREAM, FORMAT, (NULL),
+ ("Could not locate image format from caps %" GST_PTR_FORMAT, caps));
+ return FALSE;
+ }
+
+ sink->fps_n = info.fps_n;
+ sink->fps_d = info.fps_d;
+
+ GST_VIDEO_SINK_WIDTH (vsink) = info.width;
+ GST_VIDEO_SINK_HEIGHT (vsink) = info.height;
+
+ return TRUE;
+}
+
+static void
+gst_droidvideotexturesink_get_times (GstBaseSink * bsink, GstBuffer * buf,
+ GstClockTime * start, GstClockTime * end)
+{
+ GstDroidVideoTextureSink *sink;
+
+ sink = GST_DROIDVIDEOTEXTURESINK (bsink);
+
+ if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
+ *start = GST_BUFFER_TIMESTAMP (buf);
+ if (GST_BUFFER_DURATION_IS_VALID (buf)) {
+ *end = *start + GST_BUFFER_DURATION (buf);
+ } else {
+ if (sink->fps_n > 0) {
+ *end = *start +
+ gst_util_uint64_scale_int (GST_SECOND, sink->fps_d, sink->fps_n);
+ }
+ }
+ }
+}
+
+static gboolean
+gst_droidvideotexturesink_start (GstBaseSink * bsink)
+{
+ GstDroidVideoTextureSink *sink;
+
+ sink = GST_DROIDVIDEOTEXTURESINK (bsink);
+
+ GST_DEBUG_OBJECT (sink, "start");
+
+ sink->fps_n = 0;
+ sink->fps_d = 1;
+
+ sink->image = EGL_NO_IMAGE_KHR;
+ sink->sync = NULL;
+ sink->eglDestroyImageKHR = NULL;
+ sink->eglClientWaitSyncKHR = NULL;
+ sink->eglDestroySyncKHR = NULL;
+
+ return TRUE;
+}
+
+static gboolean
+gst_droidvideotexturesink_stop (GstBaseSink * bsink)
+{
+ GstDroidVideoTextureSink *sink;
+
+ sink = GST_DROIDVIDEOTEXTURESINK (bsink);
+
+ GST_DEBUG_OBJECT (sink, "stop");
+
+ if (sink->sync) {
+ gst_droidvideotexturesink_destroy_sync (sink);
+ }
+
+ g_mutex_lock (&sink->lock);
+
+ if (sink->image) {
+ GST_WARNING_OBJECT (sink, "destroying leftover EGLImageKHR");
+ sink->eglDestroyImageKHR (sink->dpy, sink->image);
+ sink->image = EGL_NO_IMAGE_KHR;
+ }
+
+ if (sink->acquired_buffer) {
+ GST_WARNING_OBJECT (sink, "freeing leftover acquired buffer");
+ gst_buffer_unref (sink->acquired_buffer);
+ sink->acquired_buffer = NULL;
+ }
+
+ g_mutex_unlock (&sink->lock);
+
+ if (sink->last_buffer) {
+ GST_INFO_OBJECT (sink, "freeing leftover last buffer");
+ gst_buffer_unref (sink->last_buffer);
+ sink->last_buffer = NULL;
+ }
+
+ return TRUE;
+}
+
+static GstFlowReturn
+gst_droidvideotexturesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
+{
+ GstDroidVideoTextureSink *sink;
+ gint n_memory;
+
+ sink = GST_DROIDVIDEOTEXTURESINK (vsink);
+
+ GST_DEBUG_OBJECT (sink, "show frame");
+
+ n_memory = gst_buffer_n_memory (buf);
+
+ if (G_UNLIKELY (n_memory == 0)) {
+ GST_WARNING_OBJECT (sink, "received an empty buffer");
+ /* we will just drop the buffer without errors */
+ return GST_FLOW_OK;
+ }
+
+ g_mutex_lock (&sink->lock);
+ if (sink->acquired_buffer) {
+ GST_INFO_OBJECT (sink,
+ "acquired buffer exists. Not replacing current buffer");
+ g_mutex_unlock (&sink->lock);
+ return GST_FLOW_OK;
+ }
+
+ GST_LOG_OBJECT (sink, "replacing buffer %p with buffer %p", sink->last_buffer,
+ buf);
+
+ gst_buffer_replace (&sink->last_buffer, buf);
+
+ g_mutex_unlock (&sink->lock);
+
+ nemo_gst_video_texture_frame_ready (NEMO_GST_VIDEO_TEXTURE (sink), 0);
+
+ return GST_FLOW_OK;
+}
+
+static gboolean
+gst_droidvideotexturesink_event (GstBaseSink * bsink, GstEvent * event)
+{
+ GstDroidVideoTextureSink *sink;
+
+ sink = GST_DROIDVIDEOTEXTURESINK (bsink);
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_FLUSH_START:
+ case GST_EVENT_EOS:
+ GST_INFO_OBJECT (sink,
+ "emitting frame-ready with -1 after %" GST_PTR_FORMAT, event);
+ g_mutex_lock (&sink->lock);
+
+ if (sink->last_buffer) {
+ gst_buffer_unref (sink->last_buffer);
+ sink->last_buffer = NULL;
+ }
+
+ g_mutex_unlock (&sink->lock);
+ nemo_gst_video_texture_frame_ready (NEMO_GST_VIDEO_TEXTURE (sink), -1);
+ break;
+
+ default:
+ break;
+ }
+
+ return GST_BASE_SINK_CLASS (parent_class)->event (bsink, event);
+}
+
+static void
+gst_droidvideotexturesink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstDroidVideoTextureSink *sink;
+
+ g_return_if_fail (GST_IS_DROIDVIDEOTEXTURESINK (object));
+
+ sink = GST_DROIDVIDEOTEXTURESINK (object);
+
+ switch (prop_id) {
+ case PROP_EGL_DISPLAY:
+ g_mutex_lock (&sink->lock);
+ sink->dpy = g_value_get_pointer (value);
+ g_mutex_unlock (&sink->lock);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_droidvideotexturesink_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstDroidVideoTextureSink *sink;
+
+ g_return_if_fail (GST_IS_DROIDVIDEOTEXTURESINK (object));
+
+ sink = GST_DROIDVIDEOTEXTURESINK (object);
+
+ switch (prop_id) {
+ case PROP_EGL_DISPLAY:
+ g_mutex_lock (&sink->lock);
+ g_value_set_pointer (value, sink->dpy);
+ g_mutex_unlock (&sink->lock);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_droidvideotexturesink_finalize (GObject * object)
+{
+ GstDroidVideoTextureSink *sink;
+
+ sink = GST_DROIDVIDEOTEXTURESINK (object);
+
+ g_mutex_clear (&sink->lock);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_droidvideotexturesink_init (GstDroidVideoTextureSink * sink)
+{
+ gst_base_sink_set_last_sample_enabled (GST_BASE_SINK (sink), FALSE);
+
+ sink->fps_n = 0;
+ sink->fps_d = 0;
+ sink->acquired_buffer = NULL;
+ sink->last_buffer = NULL;
+ sink->dpy = EGL_NO_DISPLAY;
+ sink->image = EGL_NO_IMAGE_KHR;
+ sink->sync = NULL;
+ g_mutex_init (&sink->lock);
+ sink->eglDestroyImageKHR = NULL;
+ sink->eglClientWaitSyncKHR = NULL;
+ sink->eglDestroySyncKHR = NULL;
+}
+
+static void
+gst_droidvideotexturesink_class_init (GstDroidVideoTextureSinkClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+ GstBaseSinkClass *gstbasesink_class;
+ GstVideoSinkClass *videosink_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+ gstbasesink_class = (GstBaseSinkClass *) klass;
+ videosink_class = (GstVideoSinkClass *) klass;
+
+ gst_element_class_set_static_metadata (gstelement_class,
+ "Video sink", "Sink/Video/Device",
+ "EGL based videosink", "Mohammed Sameer <msameer@foolab.org>");
+
+ gobject_class->finalize = gst_droidvideotexturesink_finalize;
+ gobject_class->set_property = gst_droidvideotexturesink_set_property;
+ gobject_class->get_property = gst_droidvideotexturesink_get_property;
+
+ gstbasesink_class->set_caps =
+ GST_DEBUG_FUNCPTR (gst_droidvideotexturesink_set_caps);
+ gstbasesink_class->get_times =
+ GST_DEBUG_FUNCPTR (gst_droidvideotexturesink_get_times);
+ gstbasesink_class->start =
+ GST_DEBUG_FUNCPTR (gst_droidvideotexturesink_start);
+ gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_droidvideotexturesink_stop);
+ gstbasesink_class->event =
+ GST_DEBUG_FUNCPTR (gst_droidvideotexturesink_event);
+ videosink_class->show_frame =
+ GST_DEBUG_FUNCPTR (gst_droidvideotexturesink_show_frame);
+
+ g_object_class_override_property (gobject_class, PROP_EGL_DISPLAY,
+ "egl-display");
+}
+
+static GstMemory *gst_droidvideotexturesink_get_droid_media_buffer_memory
+ (GstDroidVideoTextureSink * sink, GstBuffer * buffer)
+{
+ int x, num;
+
+ GST_DEBUG_OBJECT (sink, "get droid media buffer memory");
+
+ num = gst_buffer_n_memory (buffer);
+
+ GST_DEBUG_OBJECT (sink, "examining %d memory items", num);
+
+ for (x = 0; x < num; x++) {
+ GstMemory *mem = gst_buffer_peek_memory (buffer, x);
+
+ if (mem && gst_memory_is_type (mem, GST_ALLOCATOR_DROID_MEDIA_BUFFER)) {
+ return mem;
+ }
+ }
+
+ return NULL;
+}
+
+static gboolean
+gst_droidvideotexturesink_populate_egl_proc (GstDroidVideoTextureSink * sink)
+{
+ GST_DEBUG_OBJECT (sink, "populate egl proc");
+
+ if (G_UNLIKELY (!sink->eglDestroyImageKHR)) {
+ sink->eglDestroyImageKHR =
+ (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress ("eglDestroyImageKHR");
+ }
+
+ if (G_UNLIKELY (!sink->eglDestroyImageKHR)) {
+ return FALSE;
+ }
+
+ if (G_UNLIKELY (!sink->eglClientWaitSyncKHR)) {
+ sink->eglClientWaitSyncKHR = (PFNEGLCLIENTWAITSYNCKHRPROC)
+ eglGetProcAddress ("eglClientWaitSyncKHR");
+ }
+
+ if (G_UNLIKELY (!sink->eglClientWaitSyncKHR)) {
+ return FALSE;
+ }
+
+ if (G_UNLIKELY (!sink->eglDestroySyncKHR)) {
+ sink->eglDestroySyncKHR =
+ (PFNEGLDESTROYSYNCKHRPROC) eglGetProcAddress ("eglDestroySyncKHR");
+ }
+
+ if (G_UNLIKELY (!sink->eglDestroySyncKHR)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* interfaces */
+static gboolean
+gst_droidvideotexturesink_acquire_frame (NemoGstVideoTexture * iface)
+{
+ GstDroidVideoTextureSink *sink;
+ gboolean ret = TRUE;
+ GstMemory *mem;
+
+ sink = GST_DROIDVIDEOTEXTURESINK (iface);
+
+ GST_DEBUG_OBJECT (sink, "acquire frame");
+
+ g_mutex_lock (&sink->lock);
+
+ if (sink->acquired_buffer) {
+ GST_WARNING_OBJECT (sink, "buffer %p already acquired",
+ sink->acquired_buffer);
+ ret = FALSE;
+ goto unlock_and_out;
+ }
+
+ if (!sink->last_buffer) {
+ GST_WARNING_OBJECT (sink, "no buffers available for acquisition");
+ ret = FALSE;
+ goto unlock_and_out;
+ }
+
+ mem =
+ gst_droidvideotexturesink_get_droid_media_buffer_memory (sink,
+ sink->last_buffer);
+
+ if (!mem) {
+ ret = FALSE;
+ GST_WARNING_OBJECT (sink, "no droidmedia buffer available");
+ goto unlock_and_out;
+ }
+
+ sink->acquired_buffer = gst_buffer_ref (sink->last_buffer);
+
+ if (!sink->acquired_buffer) {
+ ret = FALSE;
+ GST_INFO_OBJECT (sink, "failed to acquire a buffer");
+ }
+
+unlock_and_out:
+ g_mutex_unlock (&sink->lock);
+ return ret;
+}
+
+static gboolean
+gst_droidvideotexturesink_bind_frame (NemoGstVideoTexture * iface,
+ EGLImageKHR * image)
+{
+ GstDroidVideoTextureSink *sink;
+ gboolean ret = FALSE;
+ GstMemory *mem;
+
+ sink = GST_DROIDVIDEOTEXTURESINK (iface);
+
+ GST_DEBUG_OBJECT (sink, "bind frame");
+
+ g_mutex_lock (&sink->lock);
+
+ if (sink->dpy == EGL_NO_DISPLAY) {
+ GST_WARNING_OBJECT (sink, "can not bind a frame without an EGLDisplay");
+ ret = FALSE;
+ goto unlock_and_out;
+ }
+
+ if (!gst_droidvideotexturesink_populate_egl_proc (sink)) {
+ GST_WARNING_OBJECT (sink, "failed to get needed EGL function pointers");
+ ret = FALSE;
+ goto unlock_and_out;
+ }
+
+ if (!sink->acquired_buffer) {
+ GST_WARNING_OBJECT (sink, "no frames have been acquired");
+ ret = FALSE;
+ goto unlock_and_out;
+ }
+
+ /* Now we are ready */
+
+ /* We can safely use peek here because we have an extra ref to the buffer */
+ mem =
+ gst_droidvideotexturesink_get_droid_media_buffer_memory (sink,
+ sink->acquired_buffer);
+ g_assert (mem);
+
+ sink->image =
+ nemo_gst_egl_image_memory_create_image (mem, sink->dpy, EGL_NO_CONTEXT);
+
+ /* Buffer will not go anywhere so we should be safe to unlock. */
+ g_mutex_unlock (&sink->lock);
+
+ *image = sink->image;
+
+ ret = TRUE;
+ goto out;
+
+unlock_and_out:
+ g_mutex_unlock (&sink->lock);
+
+out:
+ return ret;
+}
+
+static void
+gst_droidvideotexturesink_unbind_frame (NemoGstVideoTexture * iface)
+{
+ GstDroidVideoTextureSink *sink;
+
+ sink = GST_DROIDVIDEOTEXTURESINK (iface);
+
+ GST_DEBUG_OBJECT (sink, "unbind frame");
+
+ g_mutex_lock (&sink->lock);
+
+ if (sink->image == EGL_NO_IMAGE_KHR) {
+ GST_WARNING_OBJECT (sink, "Cannot unbind without a valid EGLImageKHR");
+ goto out;
+ }
+
+ if (sink->eglDestroyImageKHR (sink->dpy, sink->image) != EGL_TRUE) {
+ GST_WARNING_OBJECT (sink, "failed to destroy EGLImageKHR %p", sink->image);
+ }
+
+ sink->image = EGL_NO_IMAGE_KHR;
+
+out:
+ g_mutex_unlock (&sink->lock);
+}
+
+static void
+gst_droidvideotexturesink_release_frame (NemoGstVideoTexture * iface,
+ EGLSyncKHR sync)
+{
+ GstDroidVideoTextureSink *sink;
+
+ sink = GST_DROIDVIDEOTEXTURESINK (iface);
+
+ GST_DEBUG_OBJECT (sink, "release frame");
+
+ g_mutex_lock (&sink->lock);
+
+ if (sink->acquired_buffer) {
+ gst_buffer_unref (sink->acquired_buffer);
+ sink->acquired_buffer = NULL;
+ }
+
+ g_mutex_unlock (&sink->lock);
+
+ /* Destroy any previous fence */
+ gst_droidvideotexturesink_wait_sync (sink);
+
+ /* move on */
+ sink->sync = sync;
+}
+
+static gboolean
+gst_droidvideotexturesink_get_frame_info (NemoGstVideoTexture * iface,
+ NemoGstVideoTextureFrameInfo * info)
+{
+ GstDroidVideoTextureSink *sink;
+ gboolean ret;
+
+ sink = GST_DROIDVIDEOTEXTURESINK (iface);
+
+ GST_DEBUG_OBJECT (sink, "get frame info");
+
+ g_mutex_lock (&sink->lock);
+
+ if (!sink->acquired_buffer->pts) {
+ GST_INFO_OBJECT (sink, "no buffer has been acquired");
+
+ ret = FALSE;
+ goto unlock_and_out;
+ }
+
+ info->pts = sink->acquired_buffer->pts;
+ info->dts = sink->acquired_buffer->dts;
+ info->duration = sink->acquired_buffer->duration;
+ info->offset = sink->acquired_buffer->offset;
+ info->offset_end = sink->acquired_buffer->offset_end;
+
+ ret = TRUE;
+
+unlock_and_out:
+ g_mutex_unlock (&sink->lock);
+
+ return ret;
+}
+
+static GstMeta *
+gst_droidvideotexturesink_get_frame_meta (NemoGstVideoTexture * iface,
+ GType api)
+{
+ GstDroidVideoTextureSink *sink;
+ GstMeta *meta = NULL;
+
+ sink = GST_DROIDVIDEOTEXTURESINK (iface);
+
+ GST_DEBUG_OBJECT (sink, "get frame meta");
+
+ g_mutex_lock (&sink->lock);
+
+ if (sink->acquired_buffer) {
+ meta = gst_buffer_get_meta (sink->acquired_buffer, api);
+ }
+
+ g_mutex_unlock (&sink->lock);
+
+ return meta;
+}
+
+static void
+gst_droidvideotexturesink_video_texture_init (NemoGstVideoTextureClass * iface)
+{
+ iface->acquire_frame = gst_droidvideotexturesink_acquire_frame;
+ iface->bind_frame = gst_droidvideotexturesink_bind_frame;
+ iface->unbind_frame = gst_droidvideotexturesink_unbind_frame;
+ iface->release_frame = gst_droidvideotexturesink_release_frame;
+ iface->get_frame_info = gst_droidvideotexturesink_get_frame_info;
+ iface->get_frame_meta = gst_droidvideotexturesink_get_frame_meta;
+}
|
[-]
[+]
|
Added |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/droideglsink/gstdroidvideotexturesink.h
^
|
@@ -0,0 +1,71 @@
+/*
+ * gst-droid
+ *
+ * Copyright (C) 2014 Mohammed Sameer <msameer@foolab.org>
+ * Copyright (C) 2015 Jolla LTD.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __GST_DROID_VIDEO_TEXTURE_SINK_H__
+#define __GST_DROID_VIDEO_TEXTURE_SINK_H__
+
+#include "gstdroideglsink.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_DROIDVIDEOTEXTURESINK \
+ (gst_droidvideotexturesink_get_type())
+#define GST_DROIDVIDEOTEXTURESINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_DROIDVIDEOTEXTURESINK, GstDroidVideoTextureSink))
+#define GST_DROIDVIDEOTEXTURESINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_DROIDVIDEOTEXTURESINK, GstDroidVideoTextureSinkClass))
+#define GST_IS_DROIDVIDEOTEXTURESINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_DROIDVIDEOTEXTURESINK))
+#define GST_IS_DROIDVIDEOTEXTURESINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_DROIDVIDEOTEXTURESINK))
+
+typedef struct _GstDroidVideoTextureSink GstDroidVideoTextureSink;
+typedef struct _GstDroidVideoTextureSinkClass GstDroidVideoTextureSinkClass;
+
+struct _GstDroidVideoTextureSink
+{
+ GstDroidEglSink parent;
+
+ gint fps_n;
+ gint fps_d;
+
+ GstBuffer *acquired_buffer;
+ GstBuffer *last_buffer;
+ EGLDisplay dpy;
+ EGLImageKHR image;
+ EGLSyncKHR sync;
+ GMutex lock;
+
+ PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
+ PFNEGLCLIENTWAITSYNCKHRPROC eglClientWaitSyncKHR;
+ PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR;
+};
+
+struct _GstDroidVideoTextureSinkClass
+{
+ GstDroidEglSinkClass parent_class;
+};
+
+GType gst_droidvideotexturesink_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_DROID_EGL_SINK_H__ */
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gst/plugin.c
^
|
@@ -26,6 +26,7 @@
#include "plugin.h"
#include "gstdroidcamsrc.h"
#include "gstdroideglsink.h"
+#include "gstdroidvideotexturesink.h"
#include "gstdroidvdec.h"
#include "gstdroidvenc.h"
#include "gstdroidadec.h"
@@ -39,6 +40,7 @@
GST_DEBUG_CATEGORY (gst_droid_venc_debug);
GST_DEBUG_CATEGORY (gst_droid_codec_debug);
GST_DEBUG_CATEGORY (gst_droid_eglsink_debug);
+GST_DEBUG_CATEGORY (gst_droid_videotexturesink_debug);
static gboolean
plugin_init (GstPlugin * plugin)
@@ -51,6 +53,9 @@
GST_DEBUG_CATEGORY_INIT (gst_droid_eglsink_debug, "droideglsink",
0, "Android EGL sink");
+ GST_DEBUG_CATEGORY_INIT (gst_droid_videotexturesink_debug,
+ "droidvideotexturesink", 0, "Android EGL sink");
+
GST_DEBUG_CATEGORY_INIT (gst_droid_adec_debug, "droidadec",
0, "Android HAL audio decoder");
@@ -70,6 +75,8 @@
GST_TYPE_DROIDCAMSRC);
ok &= gst_element_register (plugin, "droideglsink", GST_RANK_PRIMARY,
GST_TYPE_DROIDEGLSINK);
+ ok &= gst_element_register (plugin, "droidvideotexturesink", GST_RANK_PRIMARY,
+ GST_TYPE_DROIDVIDEOTEXTURESINK);
ok &= gst_element_register (plugin, "droidvdec", GST_RANK_PRIMARY + 1,
GST_TYPE_DROIDVDEC);
|
[-]
[+]
|
Added |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/gstreamer-droid-1.0.pc.in
^
|
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/gstreamer-1.0
+
+Name: GstDroid library
+Description: GstDroid library
+Requires: gstreamer-1.0 gstreamer-base-1.0 android-headers
+Version: @VERSION@
+Libs: -L${libdir} -lgstdroid-1.0
+Cflags: -I${includedir}
|
[-]
[+]
|
Changed |
_service:tar_git:gstreamer1.0-droid-0.20200605.0.tar.gz/tools/gstdroidcamsrcconf.c
^
|
@@ -56,6 +56,7 @@
ADD_ENTRY (GST_PHOTOGRAPHY_FLASH_MODE_AUTO, "auto"),
ADD_ENTRY (GST_PHOTOGRAPHY_FLASH_MODE_OFF, "off"),
ADD_ENTRY (GST_PHOTOGRAPHY_FLASH_MODE_ON, "on"),
+ ADD_ENTRY (GST_PHOTOGRAPHY_FLASH_MODE_RED_EYE, "red-eye"),
{NULL, -1}
}},
{"focus-mode-values", "focus-mode", {
@@ -67,29 +68,29 @@
ADD_ENTRY (GST_PHOTOGRAPHY_FOCUS_MODE_EXTENDED, "edof"),
ADD_ENTRY (GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_NORMAL, "continuous"),
ADD_ENTRY (GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_EXTENDED, "continuous"),
- ADD_ENTRY (GST_PHOTOGRAPHY_FOCUS_MODE_MANUAL, NULL),
+ ADD_ENTRY (GST_PHOTOGRAPHY_FOCUS_MODE_MANUAL, "manual"),
{NULL, -1}
}},
{"whitebalance-values", "white-balance-mode", {
ADD_ENTRY (GST_PHOTOGRAPHY_WB_MODE_AUTO, "auto"),
ADD_ENTRY (GST_PHOTOGRAPHY_WB_MODE_DAYLIGHT, "daylight"),
ADD_ENTRY (GST_PHOTOGRAPHY_WB_MODE_CLOUDY, "cloudy-daylight"),
- ADD_ENTRY (GST_PHOTOGRAPHY_WB_MODE_SUNSET, NULL),
+ ADD_ENTRY (GST_PHOTOGRAPHY_WB_MODE_SUNSET, "twilight"),
ADD_ENTRY (GST_PHOTOGRAPHY_WB_MODE_TUNGSTEN, "incandescent"),
ADD_ENTRY (GST_PHOTOGRAPHY_WB_MODE_FLUORESCENT, "fluorescent"),
ADD_ENTRY (GST_PHOTOGRAPHY_WB_MODE_MANUAL, NULL),
- ADD_ENTRY (GST_PHOTOGRAPHY_WB_MODE_WARM_FLUORESCENT, NULL),
- ADD_ENTRY (GST_PHOTOGRAPHY_WB_MODE_SHADE, NULL),
+ ADD_ENTRY (GST_PHOTOGRAPHY_WB_MODE_WARM_FLUORESCENT, "warm-fluorescent"),
+ ADD_ENTRY (GST_PHOTOGRAPHY_WB_MODE_SHADE, "shade"),
{NULL, -1}
}},
{"scene-mode-values", "scene-mode", {
- ADD_ENTRY (GST_PHOTOGRAPHY_SCENE_MODE_MANUAL, NULL),
+ ADD_ENTRY (GST_PHOTOGRAPHY_SCENE_MODE_MANUAL, "auto"),
ADD_ENTRY (GST_PHOTOGRAPHY_SCENE_MODE_CLOSEUP, NULL),
ADD_ENTRY (GST_PHOTOGRAPHY_SCENE_MODE_PORTRAIT, "portrait"),
ADD_ENTRY (GST_PHOTOGRAPHY_SCENE_MODE_LANDSCAPE, "landscape"),
ADD_ENTRY (GST_PHOTOGRAPHY_SCENE_MODE_SPORT, "sports"),
ADD_ENTRY (GST_PHOTOGRAPHY_SCENE_MODE_NIGHT, "night"),
- ADD_ENTRY (GST_PHOTOGRAPHY_SCENE_MODE_AUTO, "auto"),
+ ADD_ENTRY (GST_PHOTOGRAPHY_SCENE_MODE_AUTO, "asd"),
ADD_ENTRY (GST_PHOTOGRAPHY_SCENE_MODE_ACTION, "action"),
ADD_ENTRY (GST_PHOTOGRAPHY_SCENE_MODE_NIGHT_PORTRAIT, "night-portrait"),
ADD_ENTRY (GST_PHOTOGRAPHY_SCENE_MODE_THEATRE, "theatre"),
@@ -101,6 +102,10 @@
ADD_ENTRY (GST_PHOTOGRAPHY_SCENE_MODE_PARTY, "party"),
ADD_ENTRY (GST_PHOTOGRAPHY_SCENE_MODE_CANDLELIGHT, "candlelight"),
ADD_ENTRY (GST_PHOTOGRAPHY_SCENE_MODE_BARCODE, "barcode"),
+ ADD_ENTRY (GST_PHOTOGRAPHY_SCENE_MODE_BACKLIGHT, "backlight"),
+ ADD_ENTRY (GST_PHOTOGRAPHY_SCENE_MODE_FLOWERS, "flowers"),
+ ADD_ENTRY (GST_PHOTOGRAPHY_SCENE_MODE_AR, "AR"),
+ ADD_ENTRY (GST_PHOTOGRAPHY_SCENE_MODE_HDR, "hdr"),
{NULL, -1}
}},
{"effect-values", "color-tone-mode", {
@@ -120,11 +125,16 @@
ADD_ENTRY (GST_PHOTOGRAPHY_COLOR_TONE_MODE_WHITEBOARD, "whiteboard"),
ADD_ENTRY (GST_PHOTOGRAPHY_COLOR_TONE_MODE_BLACKBOARD, "blackboard"),
ADD_ENTRY (GST_PHOTOGRAPHY_COLOR_TONE_MODE_AQUA, "aqua"),
+ ADD_ENTRY (GST_PHOTOGRAPHY_COLOR_TONE_MODE_EMBOSS, "emboss"),
+ ADD_ENTRY (GST_PHOTOGRAPHY_COLOR_TONE_MODE_SKETCH, "sketch"),
+ ADD_ENTRY (GST_PHOTOGRAPHY_COLOR_TONE_MODE_NEON, "neon"),
{NULL, -1}
}},
+ // Qualcomm ISO values (e.g. ISO100) and Intel (iso-100)
{"iso-values", "iso-speed", {
ADD_ENTRY (0, "auto"),
ADD_ENTRY (0, "iso-auto"),
+ ADD_ENTRY (1, "ISO_HJR"),
ADD_ENTRY (100, "ISO100"),
ADD_ENTRY (100, "iso-100"),
ADD_ENTRY (200, "ISO200"),
@@ -135,8 +145,23 @@
ADD_ENTRY (800, "iso-800"),
ADD_ENTRY (1600, "ISO1600"),
ADD_ENTRY (3200, "ISO3200"),
+ ADD_ENTRY (6400, "ISO6400"),
+ ADD_ENTRY (12800, "ISO12800"),
{NULL, -1}
}},
+ // Mediatek ISO values
+ {"iso-speed-values", "iso-speed", {
+ ADD_ENTRY (0, "auto"),
+ ADD_ENTRY (100, "100"),
+ ADD_ENTRY (200, "200"),
+ ADD_ENTRY (400, "400"),
+ ADD_ENTRY (800, "800"),
+ ADD_ENTRY (1600, "1600"),
+ ADD_ENTRY (3200, "3200"),
+ ADD_ENTRY (6400, "6400"),
+ ADD_ENTRY (12800, "12800"),
+ {NULL, -1}
+ }},
{"antibanding-values", "flicker-mode", {
ADD_ENTRY (GST_PHOTOGRAPHY_FLICKER_REDUCTION_OFF, "off"),
ADD_ENTRY (GST_PHOTOGRAPHY_FLICKER_REDUCTION_50HZ, "50hz"),
|