X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=sys%2Fv4l2%2Fgstv4l2allocator.c;h=5f6f554d97b0a9aced6531000ca87b86a134aa31;hb=a9ea40efb522a2f013d853e08dbaf703610c8027;hp=24bdc0f9c9aa2ad1be8e1e21f2732ce18c4315da;hpb=4b1f43ebe331c16b3f840e391cd8195b24e78bc0;p=platform%2Fupstream%2Fgst-plugins-good.git diff --git a/sys/v4l2/gstv4l2allocator.c b/sys/v4l2/gstv4l2allocator.c index 24bdc0f..5f6f554 100644 --- a/sys/v4l2/gstv4l2allocator.c +++ b/sys/v4l2/gstv4l2allocator.c @@ -38,6 +38,10 @@ #include #include #include +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER +#include +#include +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ #define GST_V4L2_MEMORY_TYPE "V4l2Memory" @@ -235,6 +239,13 @@ gst_v4l2_memory_group_free (GstV4l2MemoryGroup * group) if (mem) gst_memory_unref (mem); } +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + if (group->surface) { + GST_INFO ("unref surface[%p]", group->surface); + tbm_surface_destroy (group->surface); + group->surface = NULL; + } +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ g_slice_free (GstV4l2MemoryGroup, group); } @@ -295,6 +306,7 @@ gst_v4l2_memory_group_new (GstV4l2Allocator * allocator, guint32 index) if (!V4L2_TYPE_IS_MULTIPLANAR (format->type)) { group->planes[0].bytesused = group->buffer.bytesused; group->planes[0].length = group->buffer.length; + group->planes[0].data_offset = 0; g_assert (sizeof (group->planes[0].m) == sizeof (group->buffer.m)); memcpy (&group->planes[0].m, &group->buffer.m, sizeof (group->buffer.m)); } @@ -311,8 +323,10 @@ gst_v4l2_memory_group_new (GstV4l2Allocator * allocator, guint32 index) if (memory == V4L2_MEMORY_MMAP) { gint i; for (i = 0; i < group->n_mem; i++) { - GST_LOG_OBJECT (allocator, " [%u] bytesused: %u, length: %u", i, - group->planes[i].bytesused, group->planes[i].length); + GST_LOG_OBJECT (allocator, + " [%u] bytesused: %u, length: %u, offset: %u", i, + group->planes[i].bytesused, group->planes[i].length, + group->planes[i].data_offset); GST_LOG_OBJECT (allocator, " [%u] MMAP offset: %u", i, group->planes[i].m.mem_offset); } @@ -425,6 +439,13 @@ gst_v4l2_allocator_finalize (GObject * obj) GstV4l2Allocator *allocator = (GstV4l2Allocator *) obj; GST_LOG_OBJECT (obj, "called"); +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + if (allocator->bufmgr) { + GST_INFO_OBJECT (obj, "deinit tbm bufmgr %p", allocator->bufmgr); + tbm_bufmgr_deinit (allocator->bufmgr); + allocator->bufmgr = NULL; + } +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ gst_atomic_queue_unref (allocator->free_queue); gst_object_unref (allocator->obj->element); @@ -500,6 +521,9 @@ gst_v4l2_allocator_probe (GstV4l2Allocator * allocator, guint32 memory, flags |= bcreate_flag; } + if (breq.capabilities & V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS) + flags |= GST_V4L2_ALLOCATOR_FLAG_SUPPORTS_ORPHANED_BUFS; + return flags; } @@ -515,6 +539,9 @@ gst_v4l2_allocator_create_buf (GstV4l2Allocator * allocator) if (!g_atomic_int_get (&allocator->active)) goto done; + if (GST_V4L2_ALLOCATOR_IS_ORPHANED (allocator)) + goto orphaned_bug; + bcreate.memory = allocator->memory; bcreate.format = obj->format; bcreate.count = 1; @@ -539,6 +566,12 @@ done: GST_OBJECT_UNLOCK (allocator); return group; +orphaned_bug: + { + GST_ERROR_OBJECT (allocator, "allocator was orphaned, " + "not creating new buffers"); + goto done; + } create_bufs_failed: { GST_WARNING_OBJECT (allocator, "error creating a new buffer: %s", @@ -581,36 +614,11 @@ static void gst_v4l2_allocator_reset_size (GstV4l2Allocator * allocator, GstV4l2MemoryGroup * group) { - GstV4l2Object *obj = allocator->obj; - gsize size; - gboolean imported = FALSE; - - switch (allocator->memory) { - case V4L2_MEMORY_USERPTR: - case V4L2_MEMORY_DMABUF: - imported = TRUE; - break; - } - - if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) { - gint i; - - for (i = 0; i < group->n_mem; i++) { - size = obj->format.fmt.pix_mp.plane_fmt[i].sizeimage; - - if (imported) - group->mem[i]->maxsize = size; - - gst_memory_resize (group->mem[i], 0, size); - } - - } else { - size = obj->format.fmt.pix.sizeimage; - - if (imported) - group->mem[0]->maxsize = size; - - gst_memory_resize (group->mem[0], 0, size); + gint i; + for (i = 0; i < group->n_mem; i++) { + group->mem[i]->maxsize = group->planes[i].length; + group->mem[i]->offset = 0; + group->mem[i]->size = group->planes[i].length; } } @@ -630,7 +638,20 @@ _cleanup_failed_alloc (GstV4l2Allocator * allocator, GstV4l2MemoryGroup * group) } } - +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER +static tbm_format __get_tbm_format (GstVideoFormat gst_format) +{ + switch (gst_format) { + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_SN12: + return TBM_FORMAT_NV12; + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_S420: + default: + return TBM_FORMAT_YUV420; + } +} +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ GstV4l2Allocator * gst_v4l2_allocator_new (GstObject * parent, GstV4l2Object * v4l2object) @@ -670,6 +691,32 @@ gst_v4l2_allocator_new (GstObject * parent, GstV4l2Object * v4l2object) GST_OBJECT_FLAG_SET (allocator, flags); +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + if (!V4L2_TYPE_IS_OUTPUT (v4l2object->type) && + v4l2object->mode == GST_V4L2_IO_DMABUF) { + tbm_surface_h tmp_surface = NULL; + int width = GST_VIDEO_INFO_WIDTH (&v4l2object->info); + int height = GST_VIDEO_INFO_HEIGHT (&v4l2object->info); + + tmp_surface = tbm_surface_create (width, height, + __get_tbm_format (GST_VIDEO_INFO_FORMAT (&v4l2object->info))); + if (tmp_surface) { + tbm_surface_get_info (tmp_surface, &allocator->s_info); + GST_INFO_OBJECT (allocator, "[%dx%d] -> tbm surface info[%dx%d]", + width, height, allocator->s_info.width, allocator->s_info.height); + tbm_surface_destroy (tmp_surface); + } else { + GST_ERROR_OBJECT (allocator, "[%dx%d] surface failed", width, height); + } + + allocator->bufmgr = tbm_bufmgr_init (-1); + if (!allocator->bufmgr) { + GST_ERROR_OBJECT (allocator, "tbm bufmgr failed"); + gst_object_unref (allocator); + return NULL; + } + } +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ return allocator; } @@ -689,6 +736,9 @@ gst_v4l2_allocator_start (GstV4l2Allocator * allocator, guint32 count, if (g_atomic_int_get (&allocator->active)) goto already_active; + if (GST_V4L2_ALLOCATOR_IS_ORPHANED (allocator)) + goto orphaned; + if (obj->ioctl (obj->video_fd, VIDIOC_REQBUFS, &breq) < 0) goto reqbufs_failed; @@ -737,6 +787,11 @@ already_active: GST_ERROR_OBJECT (allocator, "allocator already active"); goto error; } +orphaned: + { + GST_ERROR_OBJECT (allocator, "allocator was orphaned"); + goto error; + } reqbufs_failed: { GST_ERROR_OBJECT (allocator, @@ -787,10 +842,12 @@ gst_v4l2_allocator_stop (GstV4l2Allocator * allocator) gst_v4l2_memory_group_free (group); } - /* Not all drivers support rebufs(0), so warn only */ - if (obj->ioctl (obj->video_fd, VIDIOC_REQBUFS, &breq) < 0) - GST_WARNING_OBJECT (allocator, - "error releasing buffers buffers: %s", g_strerror (errno)); + if (!GST_V4L2_ALLOCATOR_IS_ORPHANED (allocator)) { + /* Not all drivers support rebufs(0), so warn only */ + if (obj->ioctl (obj->video_fd, VIDIOC_REQBUFS, &breq) < 0) + GST_WARNING_OBJECT (allocator, + "error releasing buffers buffers: %s", g_strerror (errno)); + } allocator->count = 0; @@ -801,6 +858,26 @@ done: return ret; } +gboolean +gst_v4l2_allocator_orphan (GstV4l2Allocator * allocator) +{ + GstV4l2Object *obj = allocator->obj; + struct v4l2_requestbuffers breq = { 0, obj->type, allocator->memory }; + + if (!GST_V4L2_ALLOCATOR_CAN_ORPHAN_BUFS (allocator)) + return FALSE; + + GST_OBJECT_FLAG_SET (allocator, GST_V4L2_ALLOCATOR_FLAG_ORPHANED); + + if (obj->ioctl (obj->video_fd, VIDIOC_REQBUFS, &breq) < 0) { + GST_ERROR_OBJECT (allocator, + "error orphaning buffers buffers: %s", g_strerror (errno)); + return FALSE; + } + + return TRUE; +} + GstV4l2MemoryGroup * gst_v4l2_allocator_alloc_mmap (GstV4l2Allocator * allocator) { @@ -829,8 +906,8 @@ gst_v4l2_allocator_alloc_mmap (GstV4l2Allocator * allocator) group->planes[i].length, group->planes[i].data_offset, i); group->mem[i] = (GstMemory *) _v4l2mem_new (0, GST_ALLOCATOR (allocator), - NULL, group->planes[i].length, 0, 0, group->planes[i].length, i, - data, -1, group); + NULL, group->planes[i].length, 0, 0, group->planes[i].length, i, data, + -1, group); } else { /* Take back the allocator reference */ gst_object_ref (allocator); @@ -863,6 +940,9 @@ gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator, GstV4l2Object *obj = allocator->obj; GstV4l2MemoryGroup *group; gint i; +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + tbm_bo bos[VIDEO_MAX_PLANES] = {NULL, }; +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ g_return_val_if_fail (allocator->memory == V4L2_MEMORY_MMAP, NULL); @@ -874,7 +954,6 @@ gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator, for (i = 0; i < group->n_mem; i++) { GstV4l2Memory *mem; GstMemory *dma_mem; - gint dmafd; if (group->mem[i] == NULL) { struct v4l2_exportbuffer expbuf = { 0 }; @@ -891,8 +970,14 @@ gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator, expbuf.fd, i); group->mem[i] = (GstMemory *) _v4l2mem_new (0, GST_ALLOCATOR (allocator), - NULL, group->planes[i].length, 0, 0, group->planes[i].length, i, - NULL, expbuf.fd, group); + NULL, group->planes[i].length, 0, group->planes[i].data_offset, + group->planes[i].length - group->planes[i].data_offset, i, NULL, + expbuf.fd, group); +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + bos[i] = tbm_bo_import_fd (allocator->bufmgr, expbuf.fd); + GST_INFO_OBJECT (allocator, "obj[%p,i:%d]: fd[%d] -> bo[%p]", + obj, expbuf.index, expbuf.fd, bos[i]); +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ } else { /* Take back the allocator reference */ gst_object_ref (allocator); @@ -903,11 +988,10 @@ gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator, g_assert (gst_is_v4l2_memory (group->mem[i])); mem = (GstV4l2Memory *) group->mem[i]; - if ((dmafd = dup (mem->dmafd)) < 0) - goto dup_failed; - - dma_mem = gst_dmabuf_allocator_alloc (dmabuf_allocator, dmafd, - mem->mem.maxsize); + dma_mem = gst_fd_allocator_alloc (dmabuf_allocator, mem->dmafd, + group->planes[i].length, GST_FD_MEMORY_FLAG_DONT_CLOSE); + gst_memory_resize (dma_mem, group->planes[i].data_offset, + group->planes[i].length - group->planes[i].data_offset); gst_mini_object_set_qdata (GST_MINI_OBJECT (dma_mem), GST_V4L2_MEMORY_QUARK, mem, (GDestroyNotify) gst_memory_unref); @@ -915,6 +999,16 @@ gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator, group->mem[i] = dma_mem; } +#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER + if (!group->surface) { + group->surface = tbm_surface_internal_create_with_bos (&allocator->s_info, bos, group->n_mem); + GST_INFO_OBJECT (allocator, "new surface[%p] in memory group[%p]", group->surface, group); + } + /* release bos - they will be kept in surface. */ + for (i = 0 ; i < VIDEO_MAX_PLANES && bos[i] ; i++) + tbm_bo_unref (bos[i]); +#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */ + gst_v4l2_allocator_reset_size (allocator, group); return group; @@ -925,12 +1019,6 @@ expbuf_failed: g_strerror (errno)); goto cleanup; } -dup_failed: - { - GST_ERROR_OBJECT (allocator, "Failed to dup DMABUF descriptor: %s", - g_strerror (errno)); - goto cleanup; - } cleanup: { _cleanup_failed_alloc (allocator, group); @@ -952,11 +1040,8 @@ gst_v4l2_allocator_clear_dmabufin (GstV4l2Allocator * allocator, mem = (GstV4l2Memory *) group->mem[i]; - GST_LOG_OBJECT (allocator, "clearing DMABUF import, fd %i plane %d", - mem->dmafd, i); - - if (mem->dmafd >= 0) - close (mem->dmafd); + GST_LOG_OBJECT (allocator, "[%i] clearing DMABUF import, fd %i plane %d", + group->buffer.index, mem->dmafd, i); /* Update memory */ mem->mem.maxsize = 0; @@ -1023,8 +1108,8 @@ gst_v4l2_allocator_clear_userptr (GstV4l2Allocator * allocator, for (i = 0; i < group->n_mem; i++) { mem = (GstV4l2Memory *) group->mem[i]; - GST_LOG_OBJECT (allocator, "clearing USERPTR %p plane %d size %" - G_GSIZE_FORMAT, mem->data, i, mem->mem.size); + GST_LOG_OBJECT (allocator, "[%i] clearing USERPTR %p plane %d size %" + G_GSIZE_FORMAT, group->buffer.index, mem->data, i, mem->mem.size); mem->mem.maxsize = 0; mem->mem.size = 0; @@ -1097,10 +1182,10 @@ gst_v4l2_allocator_import_dmabuf (GstV4l2Allocator * allocator, size = gst_memory_get_sizes (dma_mem[i], &offset, &maxsize); - if ((dmafd = dup (gst_dmabuf_memory_get_fd (dma_mem[i]))) < 0) - goto dup_failed; + dmafd = gst_dmabuf_memory_get_fd (dma_mem[i]); - GST_LOG_OBJECT (allocator, "imported DMABUF as fd %i plane %d", dmafd, i); + GST_LOG_OBJECT (allocator, "[%i] imported DMABUF as fd %i plane %d", + group->buffer.index, dmafd, i); mem = (GstV4l2Memory *) group->mem[i]; @@ -1112,7 +1197,7 @@ gst_v4l2_allocator_import_dmabuf (GstV4l2Allocator * allocator, /* Update v4l2 structure */ group->planes[i].length = maxsize; - group->planes[i].bytesused = size; + group->planes[i].bytesused = size + offset; group->planes[i].m.fd = dmafd; group->planes[i].data_offset = offset; } @@ -1122,6 +1207,9 @@ gst_v4l2_allocator_import_dmabuf (GstV4l2Allocator * allocator, group->buffer.bytesused = group->planes[0].bytesused; group->buffer.length = group->planes[0].length; group->buffer.m.fd = group->planes[0].m.userptr; + + /* FIXME Check if data_offset > 0 and fail for non-multi-planar */ + g_assert (group->planes[0].data_offset == 0); } else { group->buffer.length = group->n_mem; } @@ -1139,12 +1227,6 @@ not_dmabuf: GST_ERROR_OBJECT (allocator, "Memory %i is not of DMABUF", i); return FALSE; } -dup_failed: - { - GST_ERROR_OBJECT (allocator, "Failed to dup DMABUF descriptor: %s", - g_strerror (errno)); - return FALSE; - } } gboolean @@ -1165,19 +1247,16 @@ gst_v4l2_allocator_import_userptr (GstV4l2Allocator * allocator, for (i = 0; i < group->n_mem; i++) { gsize maxsize, psize; - if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) { - struct v4l2_pix_format_mplane *pix = &obj->format.fmt.pix_mp; - maxsize = pix->plane_fmt[i].sizeimage; - psize = size[i]; - } else { - maxsize = obj->format.fmt.pix.sizeimage; - psize = img_size; - } + /* TODO request used size and maxsize seperatly */ + if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) + maxsize = psize = size[i]; + else + maxsize = psize = img_size; g_assert (psize <= img_size); - GST_LOG_OBJECT (allocator, "imported USERPTR %p plane %d size %" - G_GSIZE_FORMAT, data[i], i, psize); + GST_LOG_OBJECT (allocator, "[%i] imported USERPTR %p plane %d size %" + G_GSIZE_FORMAT, group->buffer.index, data[i], i, psize); mem = (GstV4l2Memory *) group->mem[i]; @@ -1350,14 +1429,33 @@ gst_v4l2_allocator_dqbuf (GstV4l2Allocator * allocator, } else { /* for capture, simply read the size */ for (i = 0; i < group->n_mem; i++) { - if (G_LIKELY (group->planes[i].bytesused <= group->mem[i]->maxsize)) - gst_memory_resize (group->mem[i], 0, group->planes[i].bytesused); + gsize size, offset; + + GST_LOG_OBJECT (allocator, + "Dequeued capture buffer, length: %u bytesused: %u data_offset: %u", + group->planes[i].length, group->planes[i].bytesused, + group->planes[i].data_offset); + + offset = group->planes[i].data_offset; + + if (group->planes[i].bytesused > group->planes[i].data_offset) { + size = group->planes[i].bytesused - group->planes[i].data_offset; + } else { + GST_WARNING_OBJECT (allocator, "V4L2 provided buffer has bytesused %" + G_GUINT32_FORMAT " which is too small to include data_offset %" + G_GUINT32_FORMAT, group->planes[i].bytesused, + group->planes[i].data_offset); + size = group->planes[i].bytesused; + } + + if (G_LIKELY (size + offset <= group->mem[i]->maxsize)) + gst_memory_resize (group->mem[i], offset, size); else { GST_WARNING_OBJECT (allocator, "v4l2 provided buffer that is too big for the memory it was " - "writing into. v4l2 claims %" G_GUINT32_FORMAT " bytes used but " + "writing into. v4l2 claims %" G_GSIZE_FORMAT " bytes used but " "memory is only %" G_GSIZE_FORMAT "B. This is probably a driver " - "bug.", group->planes[i].bytesused, group->mem[i]->maxsize); + "bug.", size, group->mem[i]->maxsize); gst_memory_resize (group->mem[i], 0, group->mem[i]->maxsize); } }