| /* |
| * Copyright (c) 2013-2015, Freescale Semiconductor, Inc. All rights reserved. |
| * Copyright 2017 NXP |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 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 |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public |
| * License along with this library; if not, write to the |
| * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| * Boston, MA 02111-1307, USA. |
| */ |
| |
| /** |
| * SECTION:element-vpudec |
| * |
| * VPU based video decoder. |
| * |
| * <refsect2> |
| * <title>Example launch line</title> |
| * |[ |
| * gst-launch-1.0 -v filesrc location=test.avi ! avidemux ! queue ! vpudec ! videoconvert ! videoscale ! autovideosink |
| * ]| The above pipeline decode the test.avi and renders it to the screen. |
| * </refsect2> |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include "config.h" |
| #endif |
| #include <string.h> |
| |
| #include <gst/video/video.h> |
| #include <gst/video/gstvideometa.h> |
| #include <gst/video/gstvideopool.h> |
| #include <gst/allocators/gstphysmemory.h> |
| #include <gst/allocators/gstdmabufmeta.h> |
| #ifdef USE_ION |
| #include <gst/allocators/gstionmemory.h> |
| #endif |
| #include <drm_fourcc_imx.h> |
| #include "gstimxcommon.h" |
| #include "gstvpuallocator.h" |
| #include "gstvpudec.h" |
| |
| enum |
| { |
| PROP_0, |
| PROP_OUTPUT_FORMAT, |
| PROP_ADAPTIVE_FRAME_DROP, |
| PROP_FRAMES_PLUS, |
| PROP_USE_VPU_MEMORY |
| }; |
| |
| #define DEFAULT_LOW_LATENCY FALSE |
| #define DEFAULT_OUTPUT_FORMAT 0 |
| #define DEFAULT_ADAPTIVE_FRAME_DROP TRUE |
| #define DEFAULT_FRAMES_PLUS 3 |
| /* Default to use VPU memory for video frame buffer as all video frame buffer |
| * must registe to VPU. Change video frame buffer will cause close VPU which |
| * will cause video stream lost. |
| */ |
| #define DEFAULT_USE_VPU_MEMORY TRUE |
| |
| GST_DEBUG_CATEGORY_STATIC (vpu_dec_debug); |
| #define GST_CAT_DEFAULT vpu_dec_debug |
| GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE); |
| |
| static void gst_vpu_dec_get_property (GObject * object, guint prop_id, |
| GValue * value, GParamSpec * pspec); |
| static void gst_vpu_dec_set_property (GObject * object, guint prop_id, |
| const GValue * value, GParamSpec * pspec); |
| static gboolean gst_vpu_dec_open (GstVideoDecoder * bdec); |
| static gboolean gst_vpu_dec_close (GstVideoDecoder * bdec); |
| static gboolean gst_vpu_dec_start (GstVideoDecoder * bdec); |
| static gboolean gst_vpu_dec_stop (GstVideoDecoder * bdec); |
| static gboolean gst_vpu_dec_set_format (GstVideoDecoder * bdec, |
| GstVideoCodecState * state); |
| static GstFlowReturn gst_vpu_dec_handle_frame (GstVideoDecoder * bdec, |
| GstVideoCodecFrame * frame); |
| static GstFlowReturn gst_vpu_dec_finish (GstVideoDecoder * bdec); |
| static gboolean gst_vpu_dec_decide_allocation (GstVideoDecoder * bdec, |
| GstQuery * query); |
| static gboolean gst_vpu_dec_reset (GstVideoDecoder * bdec, gboolean hard); |
| |
| #define gst_vpu_dec_parent_class parent_class |
| G_DEFINE_TYPE (GstVpuDec, gst_vpu_dec, GST_TYPE_VIDEO_DECODER); |
| |
| static void |
| gst_vpu_dec_finalize (GObject * object) |
| { |
| GstVpuDec *dec; |
| GST_DEBUG ("finalizing"); |
| |
| g_return_if_fail (GST_IS_VPU_DEC (object)); |
| |
| dec = GST_VPU_DEC (object); |
| |
| gst_vpu_dec_object_destroy (dec->vpu_dec_object); |
| |
| G_OBJECT_CLASS (parent_class)->finalize (object); |
| } |
| |
| static void |
| gst_vpu_dec_class_init (GstVpuDecClass * klass) |
| { |
| GObjectClass *gobject_class; |
| GstElementClass *element_class; |
| GstVideoDecoderClass *vdec_class; |
| |
| gobject_class = (GObjectClass *) klass; |
| element_class = (GstElementClass *) klass; |
| vdec_class = (GstVideoDecoderClass *) klass; |
| |
| parent_class = g_type_class_peek_parent (klass); |
| |
| gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_vpu_dec_finalize); |
| gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_vpu_dec_set_property); |
| gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_vpu_dec_get_property); |
| |
| g_object_class_install_property (gobject_class, PROP_OUTPUT_FORMAT, |
| g_param_spec_enum ("output-format", "output format", |
| "set raw video format for output (Y42B NV16 Y444 NV24 only for MJPEG)", \ |
| GST_TYPE_VPU_DEC_OUTPUT_FORMAT, \ |
| DEFAULT_OUTPUT_FORMAT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
| g_object_class_install_property (gobject_class, PROP_ADAPTIVE_FRAME_DROP, |
| g_param_spec_boolean ("frame-drop", "frame drop", |
| "enable adaptive frame drop for smoothly playback", |
| DEFAULT_ADAPTIVE_FRAME_DROP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
| g_object_class_install_property (gobject_class, PROP_FRAMES_PLUS, |
| g_param_spec_uint ("frame-plus", "addtionlal frames", |
| "set number of addtional frames for smoothly playback", |
| 0, 16, DEFAULT_FRAMES_PLUS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
| g_object_class_install_property (gobject_class, PROP_USE_VPU_MEMORY, |
| g_param_spec_boolean ("use-vpu-memory", "use vpu memory", |
| "use vpu allocate video frame buffer", |
| DEFAULT_USE_VPU_MEMORY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
| |
| gst_element_class_add_pad_template (element_class, |
| gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, |
| gst_vpu_dec_object_get_sink_caps ())); |
| gst_element_class_add_pad_template (element_class, |
| gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, |
| gst_vpu_dec_object_get_src_caps ())); |
| gst_element_class_set_static_metadata (element_class, |
| "VPU-based video decoder", "Codec/Decoder/Video", |
| "Decode compressed video to raw data", |
| IMX_GST_PLUGIN_AUTHOR); |
| |
| vdec_class->open = GST_DEBUG_FUNCPTR (gst_vpu_dec_open); |
| vdec_class->close = GST_DEBUG_FUNCPTR (gst_vpu_dec_close); |
| vdec_class->start = GST_DEBUG_FUNCPTR (gst_vpu_dec_start); |
| vdec_class->stop = GST_DEBUG_FUNCPTR (gst_vpu_dec_stop); |
| vdec_class->set_format = GST_DEBUG_FUNCPTR (gst_vpu_dec_set_format); |
| vdec_class->handle_frame = GST_DEBUG_FUNCPTR (gst_vpu_dec_handle_frame); |
| vdec_class->finish = GST_DEBUG_FUNCPTR (gst_vpu_dec_finish); |
| vdec_class->decide_allocation = GST_DEBUG_FUNCPTR (gst_vpu_dec_decide_allocation); |
| vdec_class->reset = GST_DEBUG_FUNCPTR (gst_vpu_dec_reset); |
| |
| GST_DEBUG_CATEGORY_INIT (vpu_dec_debug, "vpudec", 0, "VPU decoder"); |
| GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE"); |
| } |
| |
| static void |
| gst_vpu_dec_init (GstVpuDec * dec) |
| { |
| GST_DEBUG ("initializing"); |
| |
| dec->vpu_dec_object = gst_vpu_dec_object_new (); |
| |
| GST_VPU_DEC_LOW_LATENCY (dec->vpu_dec_object) = DEFAULT_LOW_LATENCY; |
| GST_VPU_DEC_OUTPUT_FORMAT (dec->vpu_dec_object) = DEFAULT_OUTPUT_FORMAT; |
| GST_VPU_DEC_FRAME_DROP (dec->vpu_dec_object) = DEFAULT_ADAPTIVE_FRAME_DROP; |
| GST_VPU_DEC_FRAMES_PLUS (dec->vpu_dec_object) = DEFAULT_FRAMES_PLUS; |
| GST_VPU_DEC_USE_VPU_MEMORY (dec->vpu_dec_object) = DEFAULT_USE_VPU_MEMORY; |
| GST_VPU_DEC_MIN_BUF_CNT (dec->vpu_dec_object) = 0; |
| |
| /* As VPU can support stream mode. need call parser before decode */ |
| gst_video_decoder_set_packetized (GST_VIDEO_DECODER (dec), TRUE); |
| } |
| |
| static void |
| gst_vpu_dec_get_property (GObject * object, guint prop_id, GValue * value, |
| GParamSpec * pspec) |
| { |
| GstVpuDec *dec; |
| |
| g_return_if_fail (GST_IS_VPU_DEC (object)); |
| dec = GST_VPU_DEC (object); |
| |
| switch (prop_id) { |
| case PROP_OUTPUT_FORMAT: |
| g_value_set_enum (value, GST_VPU_DEC_OUTPUT_FORMAT (dec->vpu_dec_object)); |
| break; |
| case PROP_ADAPTIVE_FRAME_DROP: |
| g_value_set_boolean (value, GST_VPU_DEC_FRAME_DROP (dec->vpu_dec_object)); |
| break; |
| case PROP_FRAMES_PLUS: |
| g_value_set_uint (value, GST_VPU_DEC_FRAMES_PLUS (dec->vpu_dec_object)); |
| break; |
| case PROP_USE_VPU_MEMORY: |
| g_value_set_boolean (value, GST_VPU_DEC_USE_VPU_MEMORY (dec->vpu_dec_object)); |
| break; |
| default: |
| G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
| break; |
| } |
| } |
| |
| static void |
| gst_vpu_dec_set_property (GObject * object, guint prop_id, |
| const GValue * value, GParamSpec * pspec) |
| { |
| GstVpuDec *dec; |
| |
| g_return_if_fail (GST_IS_VPU_DEC (object)); |
| dec = GST_VPU_DEC (object); |
| |
| switch (prop_id) { |
| case PROP_OUTPUT_FORMAT: |
| GST_VPU_DEC_OUTPUT_FORMAT (dec->vpu_dec_object) = g_value_get_enum (value); |
| break; |
| case PROP_ADAPTIVE_FRAME_DROP: |
| GST_VPU_DEC_FRAME_DROP (dec->vpu_dec_object) = g_value_get_boolean (value); |
| break; |
| case PROP_FRAMES_PLUS: |
| GST_VPU_DEC_FRAMES_PLUS (dec->vpu_dec_object) = g_value_get_uint (value); |
| break; |
| case PROP_USE_VPU_MEMORY: |
| GST_VPU_DEC_USE_VPU_MEMORY (dec->vpu_dec_object) = g_value_get_boolean (value); |
| break; |
| default: |
| G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
| break; |
| } |
| } |
| |
| static gboolean |
| gst_vpu_dec_open (GstVideoDecoder * bdec) |
| { |
| GstVpuDec *dec = (GstVpuDec *) bdec; |
| |
| dec->vpu_dec_object->use_my_pool = FALSE; |
| dec->vpu_dec_object->use_my_allocator = FALSE; |
| dec->vpu_dec_object->drm_modifier = 0; |
| dec->vpu_dec_object->drm_modifier_pre = 0; |
| |
| return gst_vpu_dec_object_open (dec->vpu_dec_object); |
| } |
| |
| static gboolean |
| gst_vpu_dec_close (GstVideoDecoder * bdec) |
| { |
| GstVpuDec *dec = (GstVpuDec *) bdec; |
| |
| return gst_vpu_dec_object_close (dec->vpu_dec_object); |
| } |
| |
| static gboolean |
| gst_vpu_dec_start (GstVideoDecoder * bdec) |
| { |
| GstVpuDec *dec = (GstVpuDec *) bdec; |
| |
| return gst_vpu_dec_object_start (dec->vpu_dec_object); |
| } |
| |
| static gboolean |
| gst_vpu_dec_stop (GstVideoDecoder * bdec) |
| { |
| GstVpuDec *dec = (GstVpuDec *) bdec; |
| |
| return gst_vpu_dec_object_stop (dec->vpu_dec_object); |
| } |
| |
| static gboolean |
| gst_vpu_dec_set_format (GstVideoDecoder * bdec, GstVideoCodecState * state) |
| { |
| GstVpuDec *dec = (GstVpuDec *) bdec; |
| GstQuery *query; |
| gboolean is_live; |
| |
| query = gst_query_new_latency (); |
| is_live = FALSE; |
| if (gst_pad_peer_query (GST_VIDEO_DECODER_SINK_PAD (bdec), query)) { |
| gst_query_parse_latency (query, &is_live, NULL, NULL); |
| } |
| gst_query_unref (query); |
| |
| // Hantro VPU can get best performance with low lantency. |
| if (is_live || IS_HANTRO()) { |
| GST_INFO_OBJECT (dec, "Pipeline is live, set VPU to low latency mode.\n"); |
| GST_VPU_DEC_LOW_LATENCY (dec->vpu_dec_object) = TRUE; |
| } else { |
| GST_INFO_OBJECT (dec, "Pipeline isn't live, set VPU to non-latency mode.\n"); |
| GST_VPU_DEC_LOW_LATENCY (dec->vpu_dec_object) = FALSE; |
| } |
| |
| return gst_vpu_dec_object_config (dec->vpu_dec_object, bdec, state); |
| } |
| |
| static GstFlowReturn |
| gst_vpu_dec_handle_frame (GstVideoDecoder * bdec, GstVideoCodecFrame * frame) |
| { |
| GstVpuDec *dec = (GstVpuDec *) bdec; |
| |
| return gst_vpu_dec_object_decode (dec->vpu_dec_object, bdec, frame); |
| } |
| |
| static GstFlowReturn |
| gst_vpu_dec_finish (GstVideoDecoder * bdec) |
| { |
| GstVpuDec *dec = (GstVpuDec *) bdec; |
| |
| return gst_vpu_dec_object_decode (dec->vpu_dec_object, bdec, NULL); |
| } |
| |
| static gboolean |
| gst_vpu_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query) |
| { |
| GstVpuDec *dec = (GstVpuDec *) bdec; |
| GstCaps *outcaps; |
| GstBufferPool *pool = NULL; |
| guint size, min, max; |
| GstAllocator *allocator = NULL; |
| GstAllocationParams params; |
| GstStructure *config; |
| gboolean update_pool, update_allocator; |
| GstVideoInfo vinfo; |
| gboolean alloc_has_meta = FALSE; |
| guint alloc_index; |
| |
| gst_query_parse_allocation (query, &outcaps, NULL); |
| gst_video_info_init (&vinfo); |
| gst_video_info_from_caps (&vinfo, outcaps); |
| |
| GST_DEBUG_OBJECT (dec, "gst_vpu_dec_decide_allocation"); |
| |
| /* we got configuration from our peer or the decide_allocation method, |
| * parse them */ |
| if (gst_query_get_n_allocation_params (query) > 0) { |
| /* try the allocator */ |
| gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms); |
| update_allocator = TRUE; |
| } else { |
| allocator = NULL; |
| gst_allocation_params_init (¶ms); |
| update_allocator = FALSE; |
| } |
| |
| if (gst_query_get_n_allocation_pools (query) > 0) { |
| gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); |
| size = MAX (size, vinfo.size); |
| if (min < 3) min = 3; |
| update_pool = TRUE; |
| } else { |
| pool = NULL; |
| size = vinfo.size; |
| /* Allocate 3 more buffer as video sink will hold buffer after reuse the |
| * buffer pool */ |
| max = 0; |
| min = 3; |
| |
| update_pool = FALSE; |
| } |
| |
| alloc_has_meta = gst_query_find_allocation_meta (query, |
| GST_DMABUF_META_API_TYPE, &alloc_index); |
| |
| GST_DEBUG_OBJECT (dec, "vpudec query has dmabuf meta %d", alloc_has_meta); |
| |
| if (IS_HANTRO() || IS_AMPHION()) { |
| if (alloc_has_meta) { |
| const GstStructure *params; |
| gchar *meta; |
| gint j, len; |
| |
| gst_query_parse_nth_allocation_meta (query, alloc_index, ¶ms); |
| GST_DEBUG_OBJECT (dec, "Expected field 'GstDmabufMeta' in structure: %" GST_PTR_FORMAT, |
| params); |
| if (params) { |
| const GValue *vdrm_modifier = gst_structure_get_value (params, "dmabuf.drm_modifier"); |
| if (GST_VALUE_HOLDS_LIST (vdrm_modifier)) { |
| len = gst_value_list_get_size (vdrm_modifier); |
| for (j = 0; j < len; j++) { |
| const GValue *val; |
| val = gst_value_list_get_value (vdrm_modifier, j); |
| guint64 drm_modifier = g_value_get_uint64 (val); |
| GST_DEBUG_OBJECT (dec, "dmabuf meta has modifier: %lld", drm_modifier); |
| if (IS_AMPHION() && drm_modifier == DRM_FORMAT_MOD_AMPHION_TILED) |
| dec->vpu_dec_object->drm_modifier = drm_modifier; |
| else if (IS_HANTRO() && drm_modifier == DRM_FORMAT_MOD_VSI_G2_TILED_COMPRESSED |
| && dec->vpu_dec_object->is_g2 == TRUE) |
| dec->vpu_dec_object->drm_modifier = drm_modifier; |
| else if (IS_HANTRO() && drm_modifier == DRM_FORMAT_MOD_VSI_G1_TILED |
| && dec->vpu_dec_object->is_g2 == FALSE) |
| dec->vpu_dec_object->drm_modifier = drm_modifier; |
| else { |
| GST_WARNING_OBJECT (dec, "video sink can't support modifier: %lld", |
| DRM_FORMAT_MOD_AMPHION_TILED); |
| } |
| } |
| } else if (meta = gst_structure_to_string (params)) { |
| guint64 drm_modifier; |
| GST_DEBUG_OBJECT (dec, "dmabuf meta has modifier: %s", meta); |
| sscanf (meta, "GstDmabufMeta, dmabuf.drm_modifier=(guint64){ %lld };", &drm_modifier); |
| GST_DEBUG_OBJECT (dec, "dmabuf meta has modifier: %lld", drm_modifier); |
| if (drm_modifier == DRM_FORMAT_MOD_AMPHION_TILED) { |
| GST_DEBUG_OBJECT (dec, "video sink support modifier: %lld", drm_modifier); |
| dec->vpu_dec_object->drm_modifier = drm_modifier; |
| } else { |
| GST_WARNING_OBJECT (dec, "video sink can't support modifier: %lld", |
| DRM_FORMAT_MOD_AMPHION_TILED); |
| } |
| } |
| } |
| } |
| } |
| |
| if (IS_HANTRO() && (!dec->vpu_dec_object->implement_config |
| || dec->vpu_dec_object->force_linear)) |
| dec->vpu_dec_object->drm_modifier = 0; |
| //FIXME: handle video track selection. |
| if (IS_HANTRO() && dec->vpu_dec_object->drm_modifier_pre != dec->vpu_dec_object->drm_modifier) { |
| int config_param = 0; |
| GstVpuDecObject * vpu_dec_object = dec->vpu_dec_object; |
| gint height_align; |
| gint width_align; |
| guint i; |
| |
| VPU_DecConfig(dec->vpu_dec_object->handle, VPU_DEC_CONF_ENABLE_TILED, &config_param); |
| |
| VPU_DecGetInitialInfo(dec->vpu_dec_object->handle, &(dec->vpu_dec_object->init_info)); |
| dec->vpu_dec_object->frame_size = dec->vpu_dec_object->init_info.nFrameSize; |
| |
| width_align = DEFAULT_FRAME_BUFFER_ALIGNMENT_H; |
| if (vpu_dec_object->init_info.nPicWidth % width_align) |
| vpu_dec_object->video_align.padding_right = width_align \ |
| - vpu_dec_object->init_info.nPicWidth % width_align; |
| |
| for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) |
| vpu_dec_object->video_align.stride_align[i] = width_align - 1; |
| |
| vpu_dec_object->width_paded = vpu_dec_object->init_info.nPicWidth \ |
| + vpu_dec_object->video_align.padding_right; |
| |
| GST_DEBUG_OBJECT (dec, "width: %d height: %d paded width: %d paded height: %d\n", \ |
| vpu_dec_object->init_info.nPicWidth, vpu_dec_object->init_info.nPicHeight, \ |
| vpu_dec_object->width_paded, vpu_dec_object->height_paded); |
| |
| dec->vpu_dec_object->drm_modifier_pre = dec->vpu_dec_object->drm_modifier; |
| } |
| GST_DEBUG_OBJECT (dec, "used modifier: %lld", dec->vpu_dec_object->drm_modifier); |
| |
| if (dec->vpu_dec_object->vpu_need_reconfig == FALSE |
| && dec->vpu_dec_object->use_my_pool |
| && dec->vpu_dec_object->use_my_allocator) { |
| /* video track selection case. don't change pool for smoothly video track |
| * selection */ |
| GstStructure *config; |
| GstCaps *caps; |
| guint size_pre, min_buffers, max_buffers; |
| GstBufferPool *pool_pre = gst_video_decoder_get_buffer_pool (bdec); |
| |
| config = gst_buffer_pool_get_config (pool_pre); |
| gst_buffer_pool_config_get_params (config, &caps, &size_pre, &min_buffers, |
| &max_buffers); |
| |
| GST_DEBUG_OBJECT (dec, "outcaps caps %" GST_PTR_FORMAT, outcaps); |
| GST_DEBUG_OBJECT (dec, "VPU output caps %" GST_PTR_FORMAT, caps); |
| if (gst_caps_is_equal (outcaps, caps)) { |
| GST_DEBUG_OBJECT (dec, "using previous buffer pool.\n"); |
| |
| if (update_pool) |
| gst_query_set_nth_allocation_pool (query, 0, pool_pre, size_pre, \ |
| min_buffers, max_buffers); |
| else |
| gst_query_add_allocation_pool (query, pool_pre, size_pre, min_buffers, \ |
| max_buffers); |
| |
| gst_structure_free (config); |
| gst_object_unref (pool_pre); |
| if (allocator) |
| gst_object_unref (allocator); |
| if (pool) |
| gst_object_unref (pool); |
| |
| return TRUE; |
| } |
| |
| gst_structure_free (config); |
| gst_object_unref (pool_pre); |
| } |
| |
| if (GST_VPU_DEC_USE_VPU_MEMORY (dec->vpu_dec_object)) { |
| if (allocator) |
| gst_object_unref (allocator); |
| allocator = NULL; |
| if (pool) |
| gst_object_unref (pool); |
| pool = NULL; |
| } |
| |
| if (allocator == NULL |
| || !(GST_IS_ALLOCATOR_PHYMEM (allocator) |
| || GST_IS_PHYS_MEMORY_ALLOCATOR (allocator))) { |
| /* no allocator or isn't physical memory allocator. VPU need continus |
| * physical memory. use VPU memory allocator. */ |
| if (allocator) { |
| gst_object_unref (allocator); |
| } |
| GST_DEBUG_OBJECT (dec, "using vpu allocator.\n"); |
| #ifdef USE_ION |
| allocator = gst_ion_allocator_obtain (); |
| #endif |
| if (!allocator) { |
| allocator = gst_vpu_allocator_obtain(); |
| } |
| dec->vpu_dec_object->use_my_allocator = TRUE; |
| } else { |
| dec->vpu_dec_object->use_my_allocator = FALSE; |
| } |
| |
| if (pool) { |
| /* need set video alignment. */ |
| if (!gst_buffer_pool_has_option (pool, \ |
| GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT)) { |
| GST_DEBUG_OBJECT (dec, "buffer pool hasn't video alignment option, unref it.\n"); |
| gst_object_unref (pool); |
| pool = NULL; |
| } |
| } |
| |
| dec->vpu_dec_object->pool_alignment_checked = FALSE; |
| if (pool == NULL) { |
| /* no pool, we can make our own */ |
| GST_DEBUG_OBJECT (dec, "no pool, making new pool"); |
| pool = gst_video_buffer_pool_new (); |
| dec->vpu_dec_object->use_my_pool = TRUE; |
| } else { |
| dec->vpu_dec_object->use_my_pool = FALSE; |
| } |
| |
| max = min += GST_VPU_DEC_MIN_BUF_CNT (dec->vpu_dec_object) \ |
| + GST_VPU_DEC_FRAMES_PLUS (dec->vpu_dec_object); |
| GST_VPU_DEC_ACTUAL_BUF_CNT (dec->vpu_dec_object) = min; |
| params.align = GST_VPU_DEC_BUF_ALIGNMENT (dec->vpu_dec_object); |
| params.flags |= GST_MEMORY_FLAG_READONLY; |
| GST_INFO_OBJECT (dec, "vpudec frame buffer count: %d.\n", \ |
| GST_VPU_DEC_ACTUAL_BUF_CNT (dec->vpu_dec_object)); |
| |
| size = MAX (size, dec->vpu_dec_object->frame_size); |
| GST_DEBUG_OBJECT (dec, "video frame size %d", size); |
| |
| /* now configure */ |
| config = gst_buffer_pool_get_config (pool); |
| |
| if (!gst_buffer_pool_config_has_option (config, \ |
| GST_BUFFER_POOL_OPTION_VIDEO_META)) { |
| gst_buffer_pool_config_add_option (config, |
| GST_BUFFER_POOL_OPTION_VIDEO_META); |
| } |
| if (!gst_buffer_pool_config_has_option (config, \ |
| GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT)) { |
| gst_buffer_pool_config_add_option (config, \ |
| GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT); |
| } |
| |
| gst_buffer_pool_config_set_video_alignment (config, \ |
| &GST_VPU_DEC_VIDEO_ALIGNMENT (dec->vpu_dec_object)); |
| gst_buffer_pool_config_set_params (config, outcaps, size, min, max); |
| gst_buffer_pool_config_set_allocator (config, allocator, ¶ms); |
| gst_buffer_pool_set_config (pool, config); |
| |
| if (update_allocator) |
| gst_query_set_nth_allocation_param (query, 0, allocator, ¶ms); |
| else |
| gst_query_add_allocation_param (query, allocator, ¶ms); |
| if (allocator) |
| gst_object_unref (allocator); |
| |
| if (update_pool) |
| gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max); |
| else |
| gst_query_add_allocation_pool (query, pool, size, min, max); |
| |
| if (pool) |
| gst_object_unref (pool); |
| |
| if (!gst_vpu_dec_object_config (dec->vpu_dec_object, bdec, NULL)) { |
| GST_DEBUG ("gst_vpu_dec_object_reopen fail."); |
| return FALSE; |
| } |
| |
| return TRUE; |
| } |
| |
| static gboolean |
| gst_vpu_dec_reset (GstVideoDecoder * bdec, gboolean hard) |
| { |
| GstVpuDec *dec = (GstVpuDec *) bdec; |
| |
| if (hard) { |
| return gst_vpu_dec_object_flush (bdec, dec->vpu_dec_object); |
| } else { |
| return TRUE; |
| } |
| } |
| |