blob: 26827d14846f3814a48e020983348a17b43935cb [file] [log] [blame]
xuesong.jiangae1548e2022-05-06 16:38:46 +08001/* GStreamer
2 * Copyright (C) 2022 <xuesong.jiang@amlogic.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
17 * Boston, MA 02110-1335, USA.
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24#include <fcntl.h>
25
26#include <sys/mman.h>
27#include <string.h>
28#include <unistd.h>
29#include <stdio.h>
30
31#include "gst/video/video.h"
32#include "gst/video/gstvideometa.h"
33#include "gst/video/gstvideopool.h"
34#include "gst/allocators/gstdmabuf.h"
35
36#include <gstamlv4l2bufferpool.h>
37
38#include "gstamlv4l2object.h"
39#include "gst/gst-i18n-plugin.h"
40#include <gst/glib-compat-private.h>
41
42#define GST_DUMP_CAPTURE_BP_STAT_FILENAME "amlv4l2dec_capture_bp_buf_stat"
43#define GST_DUMP_OUTPUT_BP_STAT_FILENAME "amlv4l2dec_output_bp_buf_stat"
44
45GST_DEBUG_CATEGORY_STATIC(amlv4l2bufferpool_debug);
bo.xiao857b8682024-09-12 16:40:32 +080046GST_DEBUG_CATEGORY_STATIC (CAT_PERFORMANCE);
xuesong.jiangae1548e2022-05-06 16:38:46 +080047#define GST_CAT_DEFAULT amlv4l2bufferpool_debug
48
49#define GST_AML_V4L2_IMPORT_QUARK gst_aml_v4l2_buffer_pool_import_quark()
50
51/*
52 * GstAmlV4l2BufferPool:
53 */
54#define gst_aml_v4l2_buffer_pool_parent_class parent_class
55G_DEFINE_TYPE(GstAmlV4l2BufferPool, gst_aml_v4l2_buffer_pool, GST_TYPE_BUFFER_POOL);
56
57enum _GstAmlV4l2BufferPoolAcquireFlags
58{
bo.xiao857b8682024-09-12 16:40:32 +080059 GST_V4L2_BUFFER_POOL_ACQUIRE_FLAG_RESURRECT =
60 GST_BUFFER_POOL_ACQUIRE_FLAG_LAST,
61 GST_V4L2_BUFFER_POOL_ACQUIRE_FLAG_LAST
xuesong.jiangae1548e2022-05-06 16:38:46 +080062};
63
64static void gst_aml_v4l2_buffer_pool_release_buffer(GstBufferPool *bpool,
65 GstBuffer *buffer);
66
67#ifdef GST_AML_SPEC_FLOW_FOR_VBP
68static gboolean gst_aml_v4l2_buffer_pool_release_buffer_aml_patch(GstBufferPool *bpool);
69#endif
70
zengliang.lidcd41462024-06-19 16:05:12 +080071#define MAX_CC_LEN 72
72#ifndef V4L2_CID_USER_AMLOGIC_BASE
73#define V4L2_CID_USER_AMLOGIC_BASE (V4L2_CID_USER_BASE + 0x1100)
74#define AML_V4L2_GET_DECINFO_SET (V4L2_CID_USER_AMLOGIC_BASE + 13)
75#endif
76
77enum E_DECINFO_CMD_GET {
78AML_DECINFO_GET_STREAM_TYPE = 0,
79AML_DECINFO_GET_STATISTIC_TYPE,
80AML_DECINFO_GET_AFD_TYPE,
81AML_DECINFO_GET_CC_TYPE,
82AML_DECINFO_GET_HDR10_TYPE,
83AML_DECINFO_GET_HDR10P_TYPE,
84AML_DECINFO_GET_CUVA_TYPE,
85AML_DECINFO_GET_DV_TYPE,
86AML_DECINFO_GET_FRAME_TYPE,
87AML_DECINFO_GET_COMPOSITE_TYPE = 30,
88AML_DECINFO_GET_CMD_BOTTOM = 31,
89};
90
91struct v4l_userdata_meta_data_t {
92__u32 poc_number;
93__u16 flags;
94__u16 video_format;
95__u16 extension_data;
96__u16 frame_type;
97__u32 vpts;
98__u32 vpts_valid;
99__u64 timestamp;
100__u32 records_in_que;
101unsigned long long priv_data;
102__u32 padding_data[64];
103};
104
105struct sei_usd_param_s {
106__u32 info_type; /* CC or AFD or aux data*/
107__u32 data_size; /* size of the data domain */
108__u64 data; /* pointer to data domain */
109__u64 v_addr; /* used for kernelspace data */
110struct v4l_userdata_meta_data_t meta_data; /* meta_data */
111};
112
113enum E_ASPECT_RATIO {
114ASPECT_RATIO_4_3,
115ASPECT_RATIO_16_9,
116ASPECT_UNDEFINED = 255
117};
118
119struct aspect_ratio_size {
120__s32 sar_width;
121__s32 sar_height;
122__s32 dar_width;
123__s32 dar_height;
124};
125
126struct dec_stream_info_s {
127__u32 info_type;
128char vdec_name[32];
129__u32 vdec_type;
130__u32 dual_core_flag;
131__u32 is_secure;
132__u32 profile_idc;
133__u32 level_idc;
134__u32 filed_flag;
135__u32 frame_width;
136__u32 frame_height;
137__u32 crop_top;
138__u32 crop_bottom;
139__u32 crop_left;
140__u32 crop_right;
141__u32 frame_rate;
142__u32 fence_enable;
143__u32 fast_output_enable;
144__u32 trick_mode;
145__u32 bit_depth;
146__u32 double_write_mode;
147__u32 error_handle_policy;
148enum E_ASPECT_RATIO eu_aspect_ratio;
149struct aspect_ratio_size ratio_size;
150char reserved[64];
151};
152
153struct dec_statistics_info_s {
154__u32 info_ype;
155__u32 total_decoded_frames;
156__u32 error_frames;
157__u32 drop_frames;
158__u32 i_decoded_frames;
159__u32 i_drop_frames;
160__u32 i_error_frames;
161__u32 p_decoded_frames;
162__u32 p_drop_frames;
163__u32 p_error_frames;
164__u32 b_decoded_frames;
165__u32 b_drop_frames;
166__u32 b_error_frames;
167__u32 av_resynch_counter;
168__u64 total_decoded_datasize;
169char reserved[64];
170};
171
172struct vframe_qos_s {
173__u32 num;
174__u32 type;
175__u32 size;
176__u32 pts;
177int max_qp;
178int avg_qp;
179int min_qp;
180int max_skip;
181int avg_skip;
182int min_skip;
183int max_mv;
184int min_mv;
185int avg_mv;
186int decode_buffer;
187} /*vframe_qos */;
188
189struct dec_frame_info_s {
190__u32 info_type;
191struct vframe_qos_s qos; /* qos */
192__u32 num;
193__u32 type;
194__s32 frame_poc;
195__u32 decode_time_cost;
196__u32 pic_width;
197__u32 pic_height;
198__u32 error_flag;
199__u32 status;
200__u32 bitrate;
201__u32 field_output_order;
202__u32 offset;
203__u32 ratio_control;
204__u32 vf_type;
205__u32 signal_type;
206__u32 ext_signal_type;
207__u32 pts;
208__u64 pts_us64;
209__u64 timestamp;
210__u32 frame_size;
211char reserved[64];
212};
213
214struct aux_data_static_t {
215__u32 info_type; /* HDR10 HLG FMM or IMAX */
216struct aml_vdec_hdr_infos hdr_info;
217};
218
219struct v4l_dec_data_extension {
220ulong ptr; /* for future extension */
221__u32 data_size;
222};
223
224/**
225* struct vdec_common_s - Structure used to receive infos from decoder
226*/
227struct vdec_common_s {
228 __u32 version_magic;
229 __u32 vdec_id;
230 __u32 type;
231 union {
232 struct dec_stream_info_s stream_info;
233 struct dec_frame_info_s frame_info;
234 struct dec_statistics_info_s decoder_statistics;
235 struct sei_usd_param_s usd_param;
236 struct aux_data_static_t aux_data;
237 struct v4l_dec_data_extension data_ext;
238 char raw_data[512];
239 } u;
240 __u32 size;
241};
242
xuesong.jiangae1548e2022-05-06 16:38:46 +0800243static gboolean
244gst_aml_v4l2_is_buffer_valid(GstBuffer *buffer, GstAmlV4l2MemoryGroup **out_group)
245{
bo.xiao857b8682024-09-12 16:40:32 +0800246 GstMemory *mem = gst_buffer_peek_memory (buffer, 0);
247 gboolean valid = FALSE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800248
bo.xiao857b8682024-09-12 16:40:32 +0800249 if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY))
250 goto done;
251
252 if (gst_is_dmabuf_memory (mem))
253 mem = gst_mini_object_get_qdata (GST_MINI_OBJECT (mem),
254 GST_AML_V4L2_MEMORY_QUARK);
255
256 if (mem && gst_aml_is_v4l2_memory(mem))
257 {
258 GstAmlV4l2Memory *vmem = (GstAmlV4l2Memory *)mem;
259 GstAmlV4l2MemoryGroup *group = vmem->group;
260 gint i;
261
262 if (group->n_mem != gst_buffer_n_memory (buffer))
263 goto done;
264
265 for (i = 0; i < group->n_mem; i++)
266 {
267 if (group->mem[i] != gst_buffer_peek_memory (buffer, i))
xuesong.jiangae1548e2022-05-06 16:38:46 +0800268 goto done;
269
bo.xiao857b8682024-09-12 16:40:32 +0800270 if (!gst_memory_is_writable (group->mem[i]))
271 goto done;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800272 }
273
bo.xiao857b8682024-09-12 16:40:32 +0800274 valid = TRUE;
275 if (out_group)
276 *out_group = group;
277 }
278
xuesong.jiangae1548e2022-05-06 16:38:46 +0800279done:
bo.xiao857b8682024-09-12 16:40:32 +0800280 return valid;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800281}
282
283static GstFlowReturn
284gst_aml_v4l2_buffer_pool_copy_buffer(GstAmlV4l2BufferPool *pool, GstBuffer *dest,
285 GstBuffer *src)
286{
bo.xiao857b8682024-09-12 16:40:32 +0800287 const GstVideoFormatInfo *finfo = pool->caps_info.finfo;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800288
bo.xiao857b8682024-09-12 16:40:32 +0800289 GST_LOG_OBJECT(pool, "copying buffer");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800290
bo.xiao857b8682024-09-12 16:40:32 +0800291 if (finfo && (finfo->format != GST_VIDEO_FORMAT_UNKNOWN &&
292 finfo->format != GST_VIDEO_FORMAT_ENCODED))
293 {
294 GstVideoFrame src_frame, dest_frame;
295
296 GST_DEBUG_OBJECT (pool, "copy video frame");
297
298 /* we have raw video, use videoframe copy to get strides right */
299 if (!gst_video_frame_map (&src_frame, &pool->caps_info, src, GST_MAP_READ))
300 goto invalid_buffer;
301
302 if (!gst_video_frame_map (&dest_frame, &pool->caps_info, dest,
303 GST_MAP_WRITE))
xuesong.jiangae1548e2022-05-06 16:38:46 +0800304 {
bo.xiao857b8682024-09-12 16:40:32 +0800305 gst_video_frame_unmap (&src_frame);
306 goto invalid_buffer;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800307 }
308
bo.xiao857b8682024-09-12 16:40:32 +0800309 gst_video_frame_copy (&dest_frame, &src_frame);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800310
bo.xiao857b8682024-09-12 16:40:32 +0800311 gst_video_frame_unmap (&src_frame);
312 gst_video_frame_unmap (&dest_frame);
313 }
314 else
315 {
316 GstMapInfo map;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800317
bo.xiao857b8682024-09-12 16:40:32 +0800318 GST_DEBUG_OBJECT(pool, "copy raw bytes size:%d", gst_buffer_get_size(src));
319
320 if (!gst_buffer_map (src, &map, GST_MAP_READ))
321 goto invalid_buffer;
322
323 gst_buffer_fill (dest, 0, map.data, gst_buffer_get_size (src));
324
325 gst_buffer_unmap (src, &map);
326 gst_buffer_resize (dest, 0, gst_buffer_get_size (src));
327 }
328
329 gst_buffer_copy_into (dest, src,
330 GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
331
332 GST_CAT_LOG_OBJECT (CAT_PERFORMANCE, pool, "slow copy into buffer %p", dest);
333
334 return GST_FLOW_OK;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800335
336invalid_buffer:
bo.xiao857b8682024-09-12 16:40:32 +0800337 {
338 GST_ERROR_OBJECT (pool, "could not map buffer");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800339 return GST_FLOW_ERROR;
bo.xiao857b8682024-09-12 16:40:32 +0800340 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800341}
342
343struct UserPtrData
344{
bo.xiao857b8682024-09-12 16:40:32 +0800345 GstBuffer *buffer;
346 gboolean is_frame;
347 GstVideoFrame frame;
348 GstMapInfo map;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800349};
350
351static GQuark
352gst_aml_v4l2_buffer_pool_import_quark(void)
353{
bo.xiao857b8682024-09-12 16:40:32 +0800354 static GQuark quark = 0;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800355
bo.xiao857b8682024-09-12 16:40:32 +0800356 if (quark == 0)
357 quark = g_quark_from_string("GstAmlV4l2BufferPoolUsePtrData");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800358
bo.xiao857b8682024-09-12 16:40:32 +0800359 return quark;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800360}
361
362static void
bo.xiao857b8682024-09-12 16:40:32 +0800363_unmap_userptr_frame (struct UserPtrData *data)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800364{
bo.xiao857b8682024-09-12 16:40:32 +0800365 if (data->is_frame)
366 gst_video_frame_unmap (&data->frame);
367 else
368 gst_buffer_unmap (data->buffer, &data->map);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800369
bo.xiao857b8682024-09-12 16:40:32 +0800370 if (data->buffer)
371 gst_buffer_unref (data->buffer);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800372
bo.xiao857b8682024-09-12 16:40:32 +0800373 g_slice_free (struct UserPtrData, data);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800374}
375
376static GstFlowReturn
377gst_aml_v4l2_buffer_pool_import_userptr(GstAmlV4l2BufferPool *pool,
378 GstBuffer *dest, GstBuffer *src)
379{
bo.xiao857b8682024-09-12 16:40:32 +0800380 GstFlowReturn ret = GST_FLOW_OK;
381 GstAmlV4l2MemoryGroup *group = NULL;
382 GstMapFlags flags;
383 const GstVideoFormatInfo *finfo = pool->caps_info.finfo;
384 struct UserPtrData *data = NULL;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800385
bo.xiao857b8682024-09-12 16:40:32 +0800386 GST_LOG_OBJECT (pool, "importing userptr");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800387
bo.xiao857b8682024-09-12 16:40:32 +0800388 /* get the group */
389 if (!gst_aml_v4l2_is_buffer_valid(dest, &group))
390 goto not_our_buffer;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800391
bo.xiao857b8682024-09-12 16:40:32 +0800392 if (V4L2_TYPE_IS_OUTPUT (pool->obj->type))
393 flags = GST_MAP_READ;
394 else
395 flags = GST_MAP_WRITE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800396
bo.xiao857b8682024-09-12 16:40:32 +0800397 data = g_slice_new0 (struct UserPtrData);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800398
bo.xiao857b8682024-09-12 16:40:32 +0800399 if (finfo && (finfo->format != GST_VIDEO_FORMAT_UNKNOWN &&
400 finfo->format != GST_VIDEO_FORMAT_ENCODED))
401 {
402 gsize size[GST_VIDEO_MAX_PLANES] = { 0, };
403 gint i;
404
405 data->is_frame = TRUE;
406
407 if (!gst_video_frame_map (&data->frame, &pool->caps_info, src, flags))
408 goto invalid_buffer;
409
410 for (i = 0; i < GST_VIDEO_FORMAT_INFO_N_PLANES(finfo); i++)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800411 {
bo.xiao857b8682024-09-12 16:40:32 +0800412 if (GST_VIDEO_FORMAT_INFO_IS_TILED(finfo))
413 {
414 gint tinfo = GST_VIDEO_FRAME_PLANE_STRIDE (&data->frame, i);
415 gint pstride;
416 guint pheight;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800417
bo.xiao857b8682024-09-12 16:40:32 +0800418 pstride = GST_VIDEO_TILE_X_TILES (tinfo) <<
419 GST_VIDEO_FORMAT_INFO_TILE_WS (finfo);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800420
bo.xiao857b8682024-09-12 16:40:32 +0800421 pheight = GST_VIDEO_TILE_Y_TILES (tinfo) <<
422 GST_VIDEO_FORMAT_INFO_TILE_HS (finfo);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800423
bo.xiao857b8682024-09-12 16:40:32 +0800424 size[i] = pstride * pheight;
425 }
426 else
427 {
428 size[i] = GST_VIDEO_FRAME_PLANE_STRIDE (&data->frame, i) *
429 GST_VIDEO_FRAME_COMP_HEIGHT (&data->frame, i);
430 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800431 }
432
bo.xiao857b8682024-09-12 16:40:32 +0800433 /* In the single planar API, planes must be contiguous in memory and
434 * therefore they must have expected size. ie: no padding.
435 * To check these conditions, we check that plane 'i' start address
436 * + plane 'i' size equals to plane 'i+1' start address */
437 if (!V4L2_TYPE_IS_MULTIPLANAR(pool->obj->type))
438 {
439 for (i = 0; i < (GST_VIDEO_FORMAT_INFO_N_PLANES(finfo) - 1); i++)
440 {
441 const struct v4l2_pix_format *pix_fmt = &pool->obj->format.fmt.pix;
442 gpointer tmp;
443 gint estride = gst_aml_v4l2_object_extrapolate_stride(finfo, i,
444 pix_fmt->bytesperline);
445 guint eheight = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (finfo, i,
446 pix_fmt->height);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800447
bo.xiao857b8682024-09-12 16:40:32 +0800448 tmp = ((guint8 *) data->frame.data[i]) + estride * eheight;
449 if (tmp != data->frame.data[i + 1])
450 goto non_contiguous_mem;
451 }
452 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800453
bo.xiao857b8682024-09-12 16:40:32 +0800454 if (!gst_aml_v4l2_allocator_import_userptr(pool->vallocator, group,
455 data->frame.info.size, finfo->n_planes, data->frame.data, size))
456 goto import_failed;
457 }
458 else
459 {
460 gpointer ptr[1];
461 gsize size[1];
xuesong.jiangae1548e2022-05-06 16:38:46 +0800462
bo.xiao857b8682024-09-12 16:40:32 +0800463 data->is_frame = FALSE;
464
465 if (!gst_buffer_map (src, &data->map, flags))
466 goto invalid_buffer;
467
468 ptr[0] = data->map.data;
469 size[0] = data->map.size;
470
471 if (!gst_aml_v4l2_allocator_import_userptr(pool->vallocator, group,
472 data->map.size, 1, ptr, size))
473 goto import_failed;
474 }
475
476 data->buffer = gst_buffer_ref (src);
477
478 gst_mini_object_set_qdata(GST_MINI_OBJECT(dest), GST_AML_V4L2_IMPORT_QUARK,
479 data, (GDestroyNotify) _unmap_userptr_frame);
480
481 gst_buffer_copy_into (dest, src,
482 GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
483
484 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800485
486not_our_buffer:
bo.xiao857b8682024-09-12 16:40:32 +0800487 {
488 GST_ERROR_OBJECT (pool, "destination buffer invalid or not from our pool");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800489 return GST_FLOW_ERROR;
bo.xiao857b8682024-09-12 16:40:32 +0800490 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800491invalid_buffer:
bo.xiao857b8682024-09-12 16:40:32 +0800492 {
493 GST_ERROR_OBJECT (pool, "could not map buffer");
494 g_slice_free (struct UserPtrData, data);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800495 return GST_FLOW_ERROR;
bo.xiao857b8682024-09-12 16:40:32 +0800496 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800497non_contiguous_mem:
bo.xiao857b8682024-09-12 16:40:32 +0800498 {
499 GST_ERROR_OBJECT (pool, "memory is not contiguous or plane size mismatch");
500 _unmap_userptr_frame (data);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800501 return GST_FLOW_ERROR;
bo.xiao857b8682024-09-12 16:40:32 +0800502 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800503import_failed:
bo.xiao857b8682024-09-12 16:40:32 +0800504 {
505 GST_ERROR_OBJECT (pool, "failed to import data");
506 _unmap_userptr_frame (data);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800507 return GST_FLOW_ERROR;
bo.xiao857b8682024-09-12 16:40:32 +0800508 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800509}
510
511static GstFlowReturn
512gst_aml_v4l2_buffer_pool_import_dmabuf(GstAmlV4l2BufferPool *pool,
513 GstBuffer *dest, GstBuffer *src)
514{
bo.xiao857b8682024-09-12 16:40:32 +0800515 GstAmlV4l2MemoryGroup *group = NULL;
516 GstMemory *dma_mem[GST_VIDEO_MAX_PLANES] = { 0 };
517 guint n_mem = gst_buffer_n_memory (src);
518 gint i;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800519
bo.xiao857b8682024-09-12 16:40:32 +0800520 GST_LOG_OBJECT (pool, "importing dmabuf");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800521
bo.xiao857b8682024-09-12 16:40:32 +0800522 if (!gst_aml_v4l2_is_buffer_valid(dest, &group))
523 goto not_our_buffer;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800524
bo.xiao857b8682024-09-12 16:40:32 +0800525 if (n_mem > GST_VIDEO_MAX_PLANES)
526 goto too_many_mems;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800527
bo.xiao857b8682024-09-12 16:40:32 +0800528 for (i = 0; i < n_mem; i++)
529 dma_mem[i] = gst_buffer_peek_memory (src, i);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800530
bo.xiao857b8682024-09-12 16:40:32 +0800531 if (!gst_aml_v4l2_allocator_import_dmabuf(pool->vallocator, group, n_mem,
532 dma_mem))
533 goto import_failed;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800534
bo.xiao857b8682024-09-12 16:40:32 +0800535 // Output buf is secure memory, Need to unref by itselt
536 // Capture buf is secure memory, Need to unref by downstreaming element gstvideosink
537 if (V4L2_TYPE_IS_OUTPUT (pool->obj->type))
538 gst_mini_object_set_qdata(GST_MINI_OBJECT(dest), GST_AML_V4L2_IMPORT_QUARK,
539 gst_buffer_ref(src), (GDestroyNotify) gst_buffer_unref);
540 else
541 gst_mini_object_set_qdata(GST_MINI_OBJECT(dest), GST_AML_V4L2_IMPORT_QUARK, gst_buffer_ref(src), NULL);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800542
bo.xiao857b8682024-09-12 16:40:32 +0800543 gst_buffer_copy_into (dest, src,
544 GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800545
bo.xiao857b8682024-09-12 16:40:32 +0800546 GST_DEBUG_OBJECT(pool, "v4l2 buf:%p, import buf:%p as qdata", dest, src);
547
548 return GST_FLOW_OK;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800549
550not_our_buffer:
bo.xiao857b8682024-09-12 16:40:32 +0800551 {
552 GST_ERROR_OBJECT (pool, "destination buffer invalid or not from our pool");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800553 return GST_FLOW_ERROR;
bo.xiao857b8682024-09-12 16:40:32 +0800554 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800555too_many_mems:
bo.xiao857b8682024-09-12 16:40:32 +0800556 {
557 GST_ERROR_OBJECT (pool, "could not map buffer");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800558 return GST_FLOW_ERROR;
bo.xiao857b8682024-09-12 16:40:32 +0800559 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800560import_failed:
bo.xiao857b8682024-09-12 16:40:32 +0800561 {
562 GST_ERROR_OBJECT (pool, "failed to import dmabuf");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800563 return GST_FLOW_ERROR;
bo.xiao857b8682024-09-12 16:40:32 +0800564 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800565}
566
567static GstFlowReturn
568gst_aml_v4l2_buffer_pool_prepare_buffer(GstAmlV4l2BufferPool *pool,
569 GstBuffer *dest, GstBuffer *src)
570{
bo.xiao857b8682024-09-12 16:40:32 +0800571 GstFlowReturn ret = GST_FLOW_OK;
572 gboolean own_src = FALSE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800573
bo.xiao857b8682024-09-12 16:40:32 +0800574 if (src == NULL)
575 {
576 if (pool->other_pool == NULL)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800577 {
bo.xiao857b8682024-09-12 16:40:32 +0800578 GST_ERROR_OBJECT (pool, "can't prepare buffer, source buffer missing");
579 return GST_FLOW_ERROR;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800580 }
581
bo.xiao857b8682024-09-12 16:40:32 +0800582 ret = gst_buffer_pool_acquire_buffer(pool->other_pool, &src, NULL);
583 if (ret != GST_FLOW_OK)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800584 {
bo.xiao857b8682024-09-12 16:40:32 +0800585 GST_ERROR_OBJECT (pool, "failed to acquire buffer from downstream pool");
586 goto done;
587 }
588
589 own_src = TRUE;
590 }
591
592 switch (pool->obj->mode)
593 {
xuesong.jiangae1548e2022-05-06 16:38:46 +0800594 case GST_V4L2_IO_MMAP:
595 case GST_V4L2_IO_DMABUF:
bo.xiao857b8682024-09-12 16:40:32 +0800596 ret = gst_aml_v4l2_buffer_pool_copy_buffer(pool, dest, src);
597 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800598 case GST_V4L2_IO_USERPTR:
bo.xiao857b8682024-09-12 16:40:32 +0800599 ret = gst_aml_v4l2_buffer_pool_import_userptr(pool, dest, src);
600 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800601 case GST_V4L2_IO_DMABUF_IMPORT:
bo.xiao857b8682024-09-12 16:40:32 +0800602 ret = gst_aml_v4l2_buffer_pool_import_dmabuf(pool, dest, src);
603 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800604 default:
bo.xiao857b8682024-09-12 16:40:32 +0800605 break;
606 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800607
bo.xiao857b8682024-09-12 16:40:32 +0800608 if (own_src)
609 gst_buffer_unref (src);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800610
611done:
bo.xiao857b8682024-09-12 16:40:32 +0800612 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800613}
614
615static GstFlowReturn
616gst_aml_v4l2_buffer_pool_alloc_buffer(GstBufferPool *bpool, GstBuffer **buffer,
617 GstBufferPoolAcquireParams *params)
618{
bo.xiao857b8682024-09-12 16:40:32 +0800619 GstAmlV4l2BufferPool *pool = GST_AML_V4L2_BUFFER_POOL(bpool);
620 GstAmlV4l2MemoryGroup *group = NULL;
621 GstBuffer *newbuf = NULL;
622 GstAmlV4l2Object *obj;
623 GstVideoInfo *info;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800624
bo.xiao857b8682024-09-12 16:40:32 +0800625 obj = pool->obj;
626 info = &obj->info;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800627
bo.xiao857b8682024-09-12 16:40:32 +0800628 switch (obj->mode)
629 {
xuesong.jiangae1548e2022-05-06 16:38:46 +0800630 case GST_V4L2_IO_RW:
bo.xiao857b8682024-09-12 16:40:32 +0800631 newbuf =
632 gst_buffer_new_allocate (pool->allocator, pool->size, &pool->params);
633 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800634 case GST_V4L2_IO_MMAP:
bo.xiao857b8682024-09-12 16:40:32 +0800635 group = gst_aml_v4l2_allocator_alloc_mmap(pool->vallocator);
636 break;
637 case GST_V4L2_IO_DMABUF:
638 group = gst_aml_v4l2_allocator_alloc_dmabuf(pool->vallocator,
639 pool->allocator);
640 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800641 case GST_V4L2_IO_USERPTR:
bo.xiao857b8682024-09-12 16:40:32 +0800642 group = gst_aml_v4l2_allocator_alloc_userptr(pool->vallocator);
643 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800644 case GST_V4L2_IO_DMABUF_IMPORT:
bo.xiao857b8682024-09-12 16:40:32 +0800645 group = gst_aml_v4l2_allocator_alloc_dmabufin(pool->vallocator);
646 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800647 default:
bo.xiao857b8682024-09-12 16:40:32 +0800648 newbuf = NULL;
649 g_assert_not_reached ();
650 break;
651 }
652
653 if (group != NULL)
654 {
655 gint i;
656 newbuf = gst_buffer_new ();
657
658 for (i = 0; i < group->n_mem; i++)
659 gst_buffer_append_memory (newbuf, group->mem[i]);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800660 }
bo.xiao857b8682024-09-12 16:40:32 +0800661 else if (newbuf == NULL)
662 {
663 goto allocation_failed;
664 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800665
bo.xiao857b8682024-09-12 16:40:32 +0800666 /* add metadata to raw video buffers */
667 if (pool->add_videometa)
668 gst_buffer_add_video_meta_full(newbuf, GST_VIDEO_FRAME_FLAG_NONE,
669 GST_VIDEO_INFO_FORMAT(info), GST_VIDEO_INFO_WIDTH(info),
670 GST_VIDEO_INFO_HEIGHT(info), GST_VIDEO_INFO_N_PLANES(info),
671 info->offset, info->stride);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800672
bo.xiao857b8682024-09-12 16:40:32 +0800673 *buffer = newbuf;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800674
bo.xiao857b8682024-09-12 16:40:32 +0800675 return GST_FLOW_OK;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800676
bo.xiao857b8682024-09-12 16:40:32 +0800677 /* ERRORS */
xuesong.jiangae1548e2022-05-06 16:38:46 +0800678allocation_failed:
bo.xiao857b8682024-09-12 16:40:32 +0800679 {
680 GST_ERROR_OBJECT (pool, "failed to allocate buffer");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800681 return GST_FLOW_ERROR;
bo.xiao857b8682024-09-12 16:40:32 +0800682 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800683}
684
685static gboolean
686gst_aml_v4l2_buffer_pool_set_config(GstBufferPool *bpool, GstStructure *config)
687{
bo.xiao857b8682024-09-12 16:40:32 +0800688 GstAmlV4l2BufferPool *pool = GST_AML_V4L2_BUFFER_POOL(bpool);
689 GstAmlV4l2Object *obj = pool->obj;
690 GstCaps *caps;
691 guint size, min_buffers, max_buffers;
692 GstAllocator *allocator;
693 GstAllocationParams params;
694 gboolean can_allocate = FALSE;
695 gboolean updated = FALSE;
696 gboolean ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800697
bo.xiao857b8682024-09-12 16:40:32 +0800698 pool->add_videometa =
699 gst_buffer_pool_config_has_option (config,
700 GST_BUFFER_POOL_OPTION_VIDEO_META);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800701
bo.xiao857b8682024-09-12 16:40:32 +0800702 /* parse the config and keep around */
703 if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers,
704 &max_buffers))
705 goto wrong_config;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800706
bo.xiao857b8682024-09-12 16:40:32 +0800707 if (!gst_buffer_pool_config_get_allocator (config, &allocator, &params))
708 goto wrong_config;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800709
bo.xiao857b8682024-09-12 16:40:32 +0800710 GST_DEBUG_OBJECT (pool, "config %" GST_PTR_FORMAT, config);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800711
bo.xiao857b8682024-09-12 16:40:32 +0800712 if (pool->allocator)
713 gst_object_unref (pool->allocator);
714 pool->allocator = NULL;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800715
bo.xiao857b8682024-09-12 16:40:32 +0800716 switch (obj->mode)
717 {
xuesong.jiangae1548e2022-05-06 16:38:46 +0800718 case GST_V4L2_IO_DMABUF:
bo.xiao857b8682024-09-12 16:40:32 +0800719 pool->allocator = gst_dmabuf_allocator_new ();
720 can_allocate = GST_AML_V4L2_ALLOCATOR_CAN_ALLOCATE(pool->vallocator, MMAP);
721 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800722 case GST_V4L2_IO_MMAP:
bo.xiao857b8682024-09-12 16:40:32 +0800723 can_allocate = GST_AML_V4L2_ALLOCATOR_CAN_ALLOCATE(pool->vallocator, MMAP);
724 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800725 case GST_V4L2_IO_USERPTR:
bo.xiao857b8682024-09-12 16:40:32 +0800726 can_allocate =
727 GST_AML_V4L2_ALLOCATOR_CAN_ALLOCATE(pool->vallocator, USERPTR);
728 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800729 case GST_V4L2_IO_DMABUF_IMPORT:
bo.xiao857b8682024-09-12 16:40:32 +0800730 can_allocate = GST_AML_V4L2_ALLOCATOR_CAN_ALLOCATE(pool->vallocator, DMABUF);
731 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800732 case GST_V4L2_IO_RW:
bo.xiao857b8682024-09-12 16:40:32 +0800733 if (allocator)
734 pool->allocator = g_object_ref (allocator);
735 pool->params = params;
736 /* No need to change the configuration */
737 goto done;
738 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800739 default:
bo.xiao857b8682024-09-12 16:40:32 +0800740 g_assert_not_reached ();
741 break;
742 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800743
bo.xiao857b8682024-09-12 16:40:32 +0800744 /* libv4l2 conversion code does not handle CREATE_BUFS, and may lead to
745 * instability and crash, disable it for now */
746 if (can_allocate && obj->fmtdesc->flags & V4L2_FMT_FLAG_EMULATED)
747 {
748 GST_WARNING_OBJECT (pool,
749 "libv4l2 converter detected, disabling CREATE_BUFS");
750 can_allocate = FALSE;
751 GST_OBJECT_FLAG_UNSET (pool->vallocator,
752 GST_V4L2_ALLOCATOR_FLAG_MMAP_CREATE_BUFS
753 | GST_V4L2_ALLOCATOR_FLAG_USERPTR_CREATE_BUFS
754 | GST_V4L2_ALLOCATOR_FLAG_DMABUF_CREATE_BUFS);
755 }
756
757 if (min_buffers < GST_AML_V4L2_MIN_BUFFERS)
758 {
759 updated = TRUE;
760 min_buffers = GST_AML_V4L2_MIN_BUFFERS;
761 GST_INFO_OBJECT (pool, "increasing minimum buffers to %u", min_buffers);
762 }
763
764 /* respect driver requirements */
765 if (min_buffers < obj->min_buffers)
766 {
767 updated = TRUE;
768 min_buffers = obj->min_buffers;
769 GST_INFO_OBJECT (pool, "increasing minimum buffers to %u", min_buffers);
770 }
771
772 if (max_buffers > VIDEO_MAX_FRAME || max_buffers == 0)
773 {
774 updated = TRUE;
775 max_buffers = VIDEO_MAX_FRAME;
776 GST_INFO_OBJECT (pool, "reducing maximum buffers to %u", max_buffers);
777 }
778
779 if (min_buffers > max_buffers)
780 {
781 updated = TRUE;
782 min_buffers = max_buffers;
783 GST_INFO_OBJECT (pool, "reducing minimum buffers to %u", min_buffers);
784 }
785 else if (min_buffers != max_buffers)
786 {
787 if (!can_allocate)
xuesong.jiangae1548e2022-05-06 16:38:46 +0800788 {
bo.xiao857b8682024-09-12 16:40:32 +0800789 updated = TRUE;
790 max_buffers = min_buffers;
791 GST_INFO_OBJECT (pool, "can't allocate, setting maximum to minimum");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800792 }
bo.xiao857b8682024-09-12 16:40:32 +0800793 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800794
bo.xiao857b8682024-09-12 16:40:32 +0800795 if (!pool->add_videometa && obj->need_video_meta)
796 {
797 GST_INFO_OBJECT (pool, "adding needed video meta");
798 updated = TRUE;
799 gst_buffer_pool_config_add_option (config,
800 GST_BUFFER_POOL_OPTION_VIDEO_META);
801 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800802
bo.xiao857b8682024-09-12 16:40:32 +0800803 /* Always update the config to ensure the configured size matches */
804 gst_buffer_pool_config_set_params (config, caps, obj->info.size, min_buffers,
805 max_buffers);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800806
bo.xiao857b8682024-09-12 16:40:32 +0800807 /* keep a GstVideoInfo with defaults for the when we need to copy */
808 gst_video_info_from_caps (&pool->caps_info, caps);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800809
810done:
bo.xiao857b8682024-09-12 16:40:32 +0800811 ret = GST_BUFFER_POOL_CLASS (parent_class)->set_config (bpool, config);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800812
bo.xiao857b8682024-09-12 16:40:32 +0800813 /* If anything was changed documentation recommend to return FALSE */
814 return !updated && ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800815
bo.xiao857b8682024-09-12 16:40:32 +0800816 /* ERRORS */
xuesong.jiangae1548e2022-05-06 16:38:46 +0800817wrong_config:
bo.xiao857b8682024-09-12 16:40:32 +0800818 {
819 GST_ERROR_OBJECT (pool, "invalid config %" GST_PTR_FORMAT, config);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800820 return FALSE;
bo.xiao857b8682024-09-12 16:40:32 +0800821 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800822}
823
824static GstFlowReturn
825gst_aml_v4l2_buffer_pool_resurrect_buffer(GstAmlV4l2BufferPool *pool)
826{
bo.xiao857b8682024-09-12 16:40:32 +0800827 GstBufferPoolAcquireParams params = { 0 };
828 GstBuffer *buffer = NULL;
829 GstFlowReturn ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800830
bo.xiao857b8682024-09-12 16:40:32 +0800831 GST_DEBUG_OBJECT (pool, "A buffer was lost, reallocating it");
xuesong.jiangae1548e2022-05-06 16:38:46 +0800832
bo.xiao857b8682024-09-12 16:40:32 +0800833 /* block recursive calls to this function */
834 g_signal_handler_block (pool->vallocator, pool->group_released_handler);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800835
bo.xiao857b8682024-09-12 16:40:32 +0800836 params.flags =
837 (GstBufferPoolAcquireFlags) GST_V4L2_BUFFER_POOL_ACQUIRE_FLAG_RESURRECT |
838 GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT;
839 ret =
840 gst_buffer_pool_acquire_buffer (GST_BUFFER_POOL (pool), &buffer, &params);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800841
bo.xiao857b8682024-09-12 16:40:32 +0800842 if (ret == GST_FLOW_OK)
843 gst_buffer_unref (buffer);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800844
bo.xiao857b8682024-09-12 16:40:32 +0800845 g_signal_handler_unblock (pool->vallocator, pool->group_released_handler);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800846
bo.xiao857b8682024-09-12 16:40:32 +0800847 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800848}
849
850static gboolean
851gst_aml_v4l2_buffer_pool_streamon(GstAmlV4l2BufferPool *pool)
852{
bo.xiao857b8682024-09-12 16:40:32 +0800853 GstAmlV4l2Object *obj = pool->obj;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800854
bo.xiao857b8682024-09-12 16:40:32 +0800855 if (pool->streaming)
856 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800857
bo.xiao857b8682024-09-12 16:40:32 +0800858 switch (obj->mode)
859 {
xuesong.jiangae1548e2022-05-06 16:38:46 +0800860 case GST_V4L2_IO_MMAP:
861 case GST_V4L2_IO_USERPTR:
862 case GST_V4L2_IO_DMABUF:
863 case GST_V4L2_IO_DMABUF_IMPORT:
bo.xiao857b8682024-09-12 16:40:32 +0800864 if (!V4L2_TYPE_IS_OUTPUT(pool->obj->type))
865 {
866 guint i;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800867
bo.xiao857b8682024-09-12 16:40:32 +0800868 /* For captures, we need to enqueue buffers before we start streaming,
869 * so the driver don't underflow immediately. As we have put then back
870 * into the base class queue, resurrect them, then releasing will queue
871 * them back. */
872 for (i = 0; i < pool->num_allocated; i++)
873 gst_aml_v4l2_buffer_pool_resurrect_buffer(pool);
874 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800875
bo.xiao857b8682024-09-12 16:40:32 +0800876 if (obj->ioctl (pool->video_fd, VIDIOC_STREAMON, &obj->type) < 0)
877 goto streamon_failed;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800878
bo.xiao857b8682024-09-12 16:40:32 +0800879 pool->streaming = TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800880
bo.xiao857b8682024-09-12 16:40:32 +0800881 GST_DEBUG_OBJECT (pool, "Started streaming");
882 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800883 default:
bo.xiao857b8682024-09-12 16:40:32 +0800884 break;
885 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800886
bo.xiao857b8682024-09-12 16:40:32 +0800887 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800888
889streamon_failed:
bo.xiao857b8682024-09-12 16:40:32 +0800890 {
891 GST_ERROR_OBJECT (pool, "error with STREAMON %d (%s)", errno,
892 g_strerror (errno));
xuesong.jiangae1548e2022-05-06 16:38:46 +0800893 return FALSE;
bo.xiao857b8682024-09-12 16:40:32 +0800894 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800895}
896
897/* Call with streamlock held, or when streaming threads are down */
898static void
899gst_aml_v4l2_buffer_pool_streamoff(GstAmlV4l2BufferPool *pool)
900{
bo.xiao857b8682024-09-12 16:40:32 +0800901 GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
902 GstAmlV4l2Object *obj = pool->obj;
903 gint i;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800904
bo.xiao857b8682024-09-12 16:40:32 +0800905 if (!pool->streaming)
906 return;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800907
bo.xiao857b8682024-09-12 16:40:32 +0800908 switch (obj->mode)
909 {
xuesong.jiangae1548e2022-05-06 16:38:46 +0800910 case GST_V4L2_IO_MMAP:
911 case GST_V4L2_IO_USERPTR:
912 case GST_V4L2_IO_DMABUF:
913 case GST_V4L2_IO_DMABUF_IMPORT:
914
bo.xiao857b8682024-09-12 16:40:32 +0800915 if (obj->ioctl (pool->video_fd, VIDIOC_STREAMOFF, &obj->type) < 0)
916 GST_WARNING_OBJECT (pool, "STREAMOFF failed with errno %d (%s)",
917 errno, g_strerror (errno));
xuesong.jiangae1548e2022-05-06 16:38:46 +0800918
xuesong.jiangae1548e2022-05-06 16:38:46 +0800919
bo.xiao857b8682024-09-12 16:40:32 +0800920 GST_DEBUG_OBJECT (pool, "Stopped streaming");
921
922 if (pool->vallocator)
923 gst_aml_v4l2_allocator_flush(pool->vallocator);
924 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800925 default:
bo.xiao857b8682024-09-12 16:40:32 +0800926 break;
927 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800928
bo.xiao857b8682024-09-12 16:40:32 +0800929 GstBufferPool *bpool = GST_BUFFER_POOL(pool);
930 if (V4L2_TYPE_IS_OUTPUT(pool->obj->type))
931 {
932 for (i = 0; i < VIDEO_MAX_FRAME; i++)
933 {
934 GST_INFO_OBJECT(pool, "deal with output buf index:%d, buf:%p", i, pool->buffers[i]);
935 if (pool->buffers[i])
936 {
937 GstBuffer *buffer = pool->buffers[i];
938 pool->buffers[i] = NULL;
939 gst_aml_v4l2_buffer_pool_release_buffer(bpool, buffer);
940 g_atomic_int_add(&pool->num_queued, -1);
941 }
942 }
943 }
944 else
945 {
xuesong.jiangae1548e2022-05-06 16:38:46 +0800946#ifdef GST_AML_SPEC_FLOW_FOR_VBP
bo.xiao857b8682024-09-12 16:40:32 +0800947 if (GST_V4L2_IO_DMABUF_IMPORT == obj->mode)
948 {
949 GST_DEBUG_OBJECT(pool, "have %d ready to free capture buffer", pool->ready_to_free_buf_num);
950 for (i = 0; i < VIDEO_MAX_FRAME; i++)
951 {
952 GST_DEBUG_OBJECT(pool, "buffers[%d]:%p, read_to_free_bufs[%d]:%p", i, pool->buffers[i], i, pool->read_to_free_bufs[i]);
953 if (pool->buffers[i])
954 {
955 if (pool->other_pool)
956 {
957 GstBuffer *other_pool_buf = gst_mini_object_get_qdata(GST_MINI_OBJECT(pool->buffers[i]), GST_AML_V4L2_IMPORT_QUARK);
958 GST_DEBUG_OBJECT(pool, "release v4l2 capture buf[%d]:%p other pool buf:%p", i, pool->buffers[i], other_pool_buf);
959 gst_buffer_unref(other_pool_buf);
960 }
961 }
962 else if (pool->read_to_free_bufs[i])
963 {
964 pool->buffers[i] = pool->read_to_free_bufs[i];
965 pool->read_to_free_bufs[i] = NULL;
966 pool->ready_to_free_buf_num--;
967 }
968 }
969 GST_DEBUG_OBJECT(pool, "%d ready to free capture buffer left", pool->ready_to_free_buf_num);
970 pool->num_queued = 0;
971 }
xuesong.jiangae1548e2022-05-06 16:38:46 +0800972#endif
bo.xiao857b8682024-09-12 16:40:32 +0800973 for (i = 0; i < VIDEO_MAX_FRAME; i++)
974 {
975 GST_INFO_OBJECT(pool, "deal with caputre buf index:%d, buf:%p", i, pool->buffers[i]);
976 if (pool->buffers[i])
977 {
978 GstBuffer *buffer = pool->buffers[i];
979 pool->buffers[i] = NULL;
980 pclass->release_buffer(bpool, buffer);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800981#ifndef GST_AML_SPEC_FLOW_FOR_VBP
bo.xiao857b8682024-09-12 16:40:32 +0800982 g_atomic_int_add(&pool->num_queued, -1);
xuesong.jiangae1548e2022-05-06 16:38:46 +0800983#endif
bo.xiao857b8682024-09-12 16:40:32 +0800984 }
985 }
986 }
987 pool->streaming = FALSE;
xuesong.jiangae1548e2022-05-06 16:38:46 +0800988}
989
990static gboolean
991gst_aml_v4l2_buffer_pool_start(GstBufferPool *bpool)
992{
bo.xiao857b8682024-09-12 16:40:32 +0800993 GstAmlV4l2BufferPool *pool = GST_AML_V4L2_BUFFER_POOL(bpool);
994 GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
995 GstAmlV4l2Object *obj = pool->obj;
996 GstStructure *config;
997 GstCaps *caps;
998 guint size, min_buffers, max_buffers;
999 guint max_latency, min_latency, copy_threshold = 0;
1000 gboolean can_allocate = FALSE, ret = TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001001
bo.xiao857b8682024-09-12 16:40:32 +08001002 GST_DEBUG_OBJECT (pool, "activating pool");
xuesong.jiangae1548e2022-05-06 16:38:46 +08001003
bo.xiao857b8682024-09-12 16:40:32 +08001004 if (pool->other_pool)
1005 {
1006 GstBuffer *buffer;
1007
1008 if (!gst_buffer_pool_set_active (pool->other_pool, TRUE))
1009 goto other_pool_failed;
1010
1011 if (gst_buffer_pool_acquire_buffer (pool->other_pool, &buffer, NULL) !=
1012 GST_FLOW_OK)
1013 goto other_pool_failed;
1014
1015 if (!gst_aml_v4l2_object_try_import(obj, buffer))
xuesong.jiangae1548e2022-05-06 16:38:46 +08001016 {
bo.xiao857b8682024-09-12 16:40:32 +08001017 gst_buffer_unref (buffer);
1018 goto cannot_import;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001019 }
bo.xiao857b8682024-09-12 16:40:32 +08001020 gst_buffer_unref (buffer);
1021 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001022
bo.xiao857b8682024-09-12 16:40:32 +08001023 config = gst_buffer_pool_get_config (bpool);
1024 if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers,
1025 &max_buffers))
1026 goto wrong_config;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001027
bo.xiao857b8682024-09-12 16:40:32 +08001028 min_latency = MAX(GST_AML_V4L2_MIN_BUFFERS, obj->min_buffers);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001029
bo.xiao857b8682024-09-12 16:40:32 +08001030 switch (obj->mode)
1031 {
xuesong.jiangae1548e2022-05-06 16:38:46 +08001032 case GST_V4L2_IO_RW:
bo.xiao857b8682024-09-12 16:40:32 +08001033 can_allocate = TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001034#ifdef HAVE_LIBV4L2
bo.xiao857b8682024-09-12 16:40:32 +08001035 /* This workaround a unfixable bug in libv4l2 when RW is emulated on top
1036 * of MMAP. In this case, the first read initialize the queues, but the
1037 * poll before that will always fail. Doing an empty read, forces the
1038 * queue to be initialized now. We only do this if we have a streaming
1039 * driver. */
1040 if (obj->device_caps & V4L2_CAP_STREAMING)
1041 obj->read (obj->video_fd, NULL, 0);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001042#endif
bo.xiao857b8682024-09-12 16:40:32 +08001043 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001044 case GST_V4L2_IO_DMABUF:
1045 case GST_V4L2_IO_MMAP:
1046 {
bo.xiao857b8682024-09-12 16:40:32 +08001047 guint count;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001048
bo.xiao857b8682024-09-12 16:40:32 +08001049 can_allocate = GST_AML_V4L2_ALLOCATOR_CAN_ALLOCATE(pool->vallocator, MMAP);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001050
bo.xiao857b8682024-09-12 16:40:32 +08001051 /* first, lets request buffers, and see how many we can get: */
1052 GST_DEBUG_OBJECT (pool, "requesting %d MMAP buffers", min_buffers);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001053
bo.xiao857b8682024-09-12 16:40:32 +08001054 count = gst_aml_v4l2_allocator_start(pool->vallocator, min_buffers,
1055 V4L2_MEMORY_MMAP);
1056 pool->num_allocated = count;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001057
bo.xiao857b8682024-09-12 16:40:32 +08001058 if (count < GST_AML_V4L2_MIN_BUFFERS)
1059 {
1060 min_buffers = count;
1061 goto no_buffers;
1062 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001063
bo.xiao857b8682024-09-12 16:40:32 +08001064 /* V4L2 buffer pool are often very limited in the amount of buffers it
1065 * can offer. The copy_threshold will workaround this limitation by
1066 * falling back to copy if the pipeline needed more buffers. This also
1067 * prevent having to do REQBUFS(N)/REQBUFS(0) every time configure is
1068 * called. */
1069 if (count != min_buffers || pool->enable_copy_threshold)
1070 {
1071 GST_WARNING_OBJECT (pool,
1072 "Uncertain or not enough buffers, enabling copy threshold");
1073 min_buffers = count;
1074 copy_threshold = min_latency;
1075 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001076
bo.xiao857b8682024-09-12 16:40:32 +08001077 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001078 }
1079 case GST_V4L2_IO_USERPTR:
1080 {
bo.xiao857b8682024-09-12 16:40:32 +08001081 guint count;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001082
bo.xiao857b8682024-09-12 16:40:32 +08001083 can_allocate =
1084 GST_AML_V4L2_ALLOCATOR_CAN_ALLOCATE(pool->vallocator, USERPTR);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001085
bo.xiao857b8682024-09-12 16:40:32 +08001086 GST_DEBUG_OBJECT (pool, "requesting %d USERPTR buffers", min_buffers);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001087
bo.xiao857b8682024-09-12 16:40:32 +08001088 count = gst_aml_v4l2_allocator_start(pool->vallocator, min_buffers,
1089 V4L2_MEMORY_USERPTR);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001090
bo.xiao857b8682024-09-12 16:40:32 +08001091 /* There is no rational to not get what we asked */
1092 if (count < min_buffers)
1093 {
xuesong.jiangae1548e2022-05-06 16:38:46 +08001094 min_buffers = count;
bo.xiao857b8682024-09-12 16:40:32 +08001095 goto no_buffers;
1096 }
1097
1098 min_buffers = count;
1099 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001100 }
1101 case GST_V4L2_IO_DMABUF_IMPORT:
1102 {
bo.xiao857b8682024-09-12 16:40:32 +08001103 guint count;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001104
bo.xiao857b8682024-09-12 16:40:32 +08001105 can_allocate = GST_AML_V4L2_ALLOCATOR_CAN_ALLOCATE(pool->vallocator, DMABUF);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001106
bo.xiao857b8682024-09-12 16:40:32 +08001107 GST_DEBUG_OBJECT (pool, "requesting %d DMABUF buffers", min_buffers);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001108
bo.xiao857b8682024-09-12 16:40:32 +08001109 count = gst_aml_v4l2_allocator_start(pool->vallocator, min_buffers,
1110 V4L2_MEMORY_DMABUF);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001111
bo.xiao857b8682024-09-12 16:40:32 +08001112 /* There is no rational to not get what we asked */
1113 if (count < min_buffers)
1114 {
xuesong.jiangae1548e2022-05-06 16:38:46 +08001115 min_buffers = count;
bo.xiao857b8682024-09-12 16:40:32 +08001116 goto no_buffers;
1117 }
1118
1119 min_buffers = count;
1120 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001121 }
1122 default:
bo.xiao857b8682024-09-12 16:40:32 +08001123 min_buffers = 0;
1124 copy_threshold = 0;
1125 g_assert_not_reached ();
1126 break;
1127 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001128
bo.xiao857b8682024-09-12 16:40:32 +08001129 if (can_allocate)
1130 max_latency = max_buffers;
1131 else
1132 max_latency = min_buffers;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001133
bo.xiao857b8682024-09-12 16:40:32 +08001134 pool->size = size;
1135 pool->copy_threshold = copy_threshold;
1136 pool->max_latency = max_latency;
1137 pool->min_latency = min_latency;
1138 pool->num_queued = 0;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001139
bo.xiao857b8682024-09-12 16:40:32 +08001140 if (max_buffers != 0 && max_buffers < min_buffers)
1141 max_buffers = min_buffers;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001142
bo.xiao857b8682024-09-12 16:40:32 +08001143 gst_buffer_pool_config_set_params (config, caps, size, min_buffers,
1144 max_buffers);
1145 pclass->set_config (bpool, config);
1146 gst_structure_free (config);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001147
bo.xiao857b8682024-09-12 16:40:32 +08001148 /* now, allocate the buffers: */
1149 if (!pclass->start (bpool))
1150 goto start_failed;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001151
bo.xiao857b8682024-09-12 16:40:32 +08001152 if (!V4L2_TYPE_IS_OUTPUT(obj->type))
1153 {
1154 if (g_atomic_int_get(&pool->num_queued) < min_buffers)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001155 {
bo.xiao857b8682024-09-12 16:40:32 +08001156 if (obj->old_other_pool || obj->old_old_other_pool)
1157 GST_DEBUG_OBJECT(pool, "resolution switching flow, need to wait other pool recycle");
1158 else
1159 goto queue_failed;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001160 }
1161
bo.xiao857b8682024-09-12 16:40:32 +08001162 pool->group_released_handler =
1163 g_signal_connect_swapped (pool->vallocator, "group-released",
1164 G_CALLBACK(gst_aml_v4l2_buffer_pool_resurrect_buffer), pool);
1165 ret = gst_aml_v4l2_buffer_pool_streamon(pool);
1166 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001167
bo.xiao857b8682024-09-12 16:40:32 +08001168 return ret;
1169
1170 /* ERRORS */
xuesong.jiangae1548e2022-05-06 16:38:46 +08001171wrong_config:
bo.xiao857b8682024-09-12 16:40:32 +08001172 {
1173 GST_ERROR_OBJECT (pool, "invalid config %" GST_PTR_FORMAT, config);
1174 gst_structure_free (config);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001175 return FALSE;
bo.xiao857b8682024-09-12 16:40:32 +08001176 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001177no_buffers:
bo.xiao857b8682024-09-12 16:40:32 +08001178 {
1179 GST_ERROR_OBJECT (pool,
1180 "we received %d buffer from device '%s', we want at least %d",
1181 min_buffers, obj->videodev, GST_AML_V4L2_MIN_BUFFERS);
1182 gst_structure_free (config);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001183 return FALSE;
bo.xiao857b8682024-09-12 16:40:32 +08001184 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001185start_failed:
bo.xiao857b8682024-09-12 16:40:32 +08001186 {
1187 GST_ERROR_OBJECT (pool, "allocate failed");
xuesong.jiangae1548e2022-05-06 16:38:46 +08001188 return FALSE;
bo.xiao857b8682024-09-12 16:40:32 +08001189 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001190other_pool_failed:
bo.xiao857b8682024-09-12 16:40:32 +08001191 {
1192 GST_ERROR_OBJECT (pool, "failed to activate the other pool %"
1193 GST_PTR_FORMAT, pool->other_pool);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001194 return FALSE;
bo.xiao857b8682024-09-12 16:40:32 +08001195 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001196queue_failed:
bo.xiao857b8682024-09-12 16:40:32 +08001197 {
1198 GST_ERROR_OBJECT (pool, "failed to queue buffers into the capture queue");
xuesong.jiangae1548e2022-05-06 16:38:46 +08001199 return FALSE;
bo.xiao857b8682024-09-12 16:40:32 +08001200 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001201cannot_import:
bo.xiao857b8682024-09-12 16:40:32 +08001202 {
1203 GST_ERROR_OBJECT (pool, "cannot import buffers from downstream pool");
xuesong.jiangae1548e2022-05-06 16:38:46 +08001204 return FALSE;
bo.xiao857b8682024-09-12 16:40:32 +08001205 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001206}
1207
1208static gboolean
1209gst_aml_v4l2_buffer_pool_vallocator_stop(GstAmlV4l2BufferPool *pool)
1210{
bo.xiao857b8682024-09-12 16:40:32 +08001211 GstAmlV4l2Return vret;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001212
bo.xiao857b8682024-09-12 16:40:32 +08001213 if (!pool->vallocator)
1214 return TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001215
bo.xiao857b8682024-09-12 16:40:32 +08001216 vret = gst_aml_v4l2_allocator_stop(pool->vallocator);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001217
bo.xiao857b8682024-09-12 16:40:32 +08001218 if (vret == GST_AML_V4L2_BUSY)
1219 GST_WARNING_OBJECT (pool, "some buffers are still outstanding");
xuesong.jiangae1548e2022-05-06 16:38:46 +08001220
bo.xiao857b8682024-09-12 16:40:32 +08001221 return (vret == GST_AML_V4L2_OK);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001222}
1223
1224static gboolean
1225gst_aml_v4l2_buffer_pool_stop(GstBufferPool *bpool)
1226{
bo.xiao857b8682024-09-12 16:40:32 +08001227 GstAmlV4l2BufferPool *pool = GST_AML_V4L2_BUFFER_POOL(bpool);
1228 gboolean ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001229
bo.xiao857b8682024-09-12 16:40:32 +08001230 if (pool->orphaned)
1231 return gst_aml_v4l2_buffer_pool_vallocator_stop(pool);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001232
bo.xiao857b8682024-09-12 16:40:32 +08001233 GST_DEBUG_OBJECT (pool, "stopping pool");
xuesong.jiangae1548e2022-05-06 16:38:46 +08001234
bo.xiao857b8682024-09-12 16:40:32 +08001235 if (pool->group_released_handler > 0)
1236 {
1237 g_signal_handler_disconnect (pool->vallocator,
1238 pool->group_released_handler);
1239 pool->group_released_handler = 0;
1240 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001241
bo.xiao857b8682024-09-12 16:40:32 +08001242 gst_aml_v4l2_buffer_pool_streamoff(pool);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001243
bo.xiao857b8682024-09-12 16:40:32 +08001244 ret = GST_BUFFER_POOL_CLASS (parent_class)->stop (bpool);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001245
bo.xiao857b8682024-09-12 16:40:32 +08001246 if (ret)
1247 ret = gst_aml_v4l2_buffer_pool_vallocator_stop(pool);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001248
bo.xiao857b8682024-09-12 16:40:32 +08001249 GST_DEBUG_OBJECT (pool, "stopping other_pool");
1250 if (pool->other_pool)
1251 {
1252 gst_buffer_pool_set_active (pool->other_pool, FALSE);
1253 gst_object_unref (pool->other_pool);
1254 pool->other_pool = NULL;
1255 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001256
bo.xiao857b8682024-09-12 16:40:32 +08001257 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001258}
1259
1260gboolean
1261gst_aml_v4l2_buffer_pool_orphan(GstBufferPool **bpool)
1262{
bo.xiao857b8682024-09-12 16:40:32 +08001263 GstAmlV4l2BufferPool *pool = GST_AML_V4L2_BUFFER_POOL(*bpool);
1264 gboolean ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001265
bo.xiao857b8682024-09-12 16:40:32 +08001266 if (!GST_AML_V4L2_ALLOCATOR_CAN_ORPHAN_BUFS(pool->vallocator))
1267 return FALSE;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001268
bo.xiao857b8682024-09-12 16:40:32 +08001269 if (g_getenv("GST_V4L2_FORCE_DRAIN"))
1270 return FALSE;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001271
bo.xiao857b8682024-09-12 16:40:32 +08001272 GST_DEBUG_OBJECT (pool, "orphaning pool");
xuesong.jiangae1548e2022-05-06 16:38:46 +08001273
bo.xiao857b8682024-09-12 16:40:32 +08001274 gst_buffer_pool_set_active (*bpool, FALSE);
1275 /*
1276 * If the buffer pool has outstanding buffers, it will not be stopped
1277 * by the base class when set inactive. Stop it manually and mark it
1278 * as orphaned
1279 */
1280 ret = gst_aml_v4l2_buffer_pool_stop(*bpool);
1281 if (!ret)
1282 {
1283 GST_DEBUG_OBJECT(pool, "stop poll fail, try to orphaning allocator");
1284 ret = gst_aml_v4l2_allocator_orphan (pool->vallocator);
1285 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001286
bo.xiao857b8682024-09-12 16:40:32 +08001287 if (!ret)
1288 goto orphan_failed;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001289
bo.xiao857b8682024-09-12 16:40:32 +08001290 pool->orphaned = TRUE;
1291 gst_object_unref(*bpool);
1292 *bpool = NULL;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001293
1294orphan_failed:
bo.xiao857b8682024-09-12 16:40:32 +08001295 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001296}
1297
1298static void
bo.xiao857b8682024-09-12 16:40:32 +08001299gst_aml_v4l2_buffer_pool_flush_start (GstBufferPool * bpool)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001300{
bo.xiao857b8682024-09-12 16:40:32 +08001301 GstAmlV4l2BufferPool *pool = GST_AML_V4L2_BUFFER_POOL (bpool);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001302
bo.xiao857b8682024-09-12 16:40:32 +08001303 GST_DEBUG_OBJECT (pool, "start flushing");
xuesong.jiangae1548e2022-05-06 16:38:46 +08001304
bo.xiao857b8682024-09-12 16:40:32 +08001305 gst_poll_set_flushing (pool->poll, TRUE);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001306
bo.xiao857b8682024-09-12 16:40:32 +08001307 GST_OBJECT_LOCK (pool);
1308 pool->empty = FALSE;
1309 g_cond_broadcast (&pool->empty_cond);
1310 GST_OBJECT_UNLOCK (pool);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001311
bo.xiao857b8682024-09-12 16:40:32 +08001312 if (pool->other_pool)
1313 gst_buffer_pool_set_flushing(pool->other_pool, TRUE);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001314}
1315
1316static void
bo.xiao857b8682024-09-12 16:40:32 +08001317gst_aml_v4l2_buffer_pool_flush_stop (GstBufferPool * bpool)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001318{
bo.xiao857b8682024-09-12 16:40:32 +08001319 GstAmlV4l2BufferPool *pool = GST_AML_V4L2_BUFFER_POOL (bpool);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001320
bo.xiao857b8682024-09-12 16:40:32 +08001321 GST_DEBUG_OBJECT (pool, "stop flushing");
xuesong.jiangae1548e2022-05-06 16:38:46 +08001322
bo.xiao857b8682024-09-12 16:40:32 +08001323 if (pool->other_pool)
1324 gst_buffer_pool_set_flushing (pool->other_pool, FALSE);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001325
bo.xiao857b8682024-09-12 16:40:32 +08001326 gst_poll_set_flushing (pool->poll, FALSE);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001327}
1328
1329static GstFlowReturn
bo.xiao857b8682024-09-12 16:40:32 +08001330gst_aml_v4l2_buffer_pool_poll (GstAmlV4l2BufferPool * pool, gboolean wait)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001331{
bo.xiao857b8682024-09-12 16:40:32 +08001332 gint ret;
1333 GstClockTime timeout;
1334 gint try_num = 0;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001335
bo.xiao857b8682024-09-12 16:40:32 +08001336 if (wait)
1337 timeout = GST_CLOCK_TIME_NONE;
1338 else
1339 timeout = 0;
1340
1341 /* In RW mode there is no queue, hence no need to wait while the queue is
1342 * empty */
1343
1344 if ((pool->obj->type == V4L2_BUF_TYPE_VIDEO_CAPTURE || pool->obj->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
1345 pool->obj->mode == GST_V4L2_IO_DMABUF_IMPORT)
1346 {
1347 GST_TRACE_OBJECT(pool, "CAPTURE DMA don't quit when empty buf");
1348 timeout = 5*1000*1000; //5ms
1349 }
1350 else
1351 {
1352 if (pool->obj->mode != GST_V4L2_IO_RW)
1353 {
1354 GST_OBJECT_LOCK(pool);
1355
1356 if (!wait && pool->empty)
1357 {
1358 GST_OBJECT_UNLOCK(pool);
1359 goto no_buffers;
1360 }
1361
1362 while (pool->empty)
1363 g_cond_wait(&pool->empty_cond, GST_OBJECT_GET_LOCK(pool));
1364
1365 GST_OBJECT_UNLOCK(pool);
1366 }
1367 }
1368
1369 if (!pool->can_poll_device)
1370 {
xuesong.jiangae1548e2022-05-06 16:38:46 +08001371 if (wait)
bo.xiao857b8682024-09-12 16:40:32 +08001372 goto done;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001373 else
bo.xiao857b8682024-09-12 16:40:32 +08001374 goto no_buffers;
1375 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001376
bo.xiao857b8682024-09-12 16:40:32 +08001377 GST_TRACE_OBJECT(pool, "polling device");
xuesong.jiang93f2dcb2022-07-15 14:24:55 +08001378
bo.xiao857b8682024-09-12 16:40:32 +08001379again:
1380 ret = gst_poll_wait (pool->poll, timeout);
1381#ifdef GST_AML_SPEC_FLOW_FOR_VBP
1382 GST_TRACE_OBJECT(pool, "amlmodbuf poll timeout:%lld, ret:%d, errno:%d", timeout, ret, errno);
1383#endif
1384 if (G_UNLIKELY(ret < 0))
1385 {
1386 switch (errno)
1387 {
1388 case EBUSY:
1389 goto stopped;
1390 case EAGAIN:
1391 case EINTR:
1392 goto again;
1393 case ENXIO:
1394 GST_WARNING_OBJECT (pool,
1395 "v4l2 device doesn't support polling. Disabling"
1396 " using libv4l2 in this case may cause deadlocks");
1397 pool->can_poll_device = FALSE;
1398 goto done;
1399 default:
1400 goto select_error;
1401 }
1402 }
1403
1404 if (gst_poll_fd_has_error (pool->poll, &pool->pollfd))
1405 {
1406 //if v4l2 don't have capture buffer, we will poll a error,it cause v4l2dec loop thread exit
1407 //so we should wait capture buffer release and queue it to v4l2,after this,we try poll again
xuesong.jiang93f2dcb2022-07-15 14:24:55 +08001408 if ((pool->obj->type == V4L2_BUF_TYPE_VIDEO_CAPTURE || pool->obj->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
1409 pool->obj->mode == GST_V4L2_IO_DMABUF_IMPORT)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001410 {
bo.xiao857b8682024-09-12 16:40:32 +08001411 if (pool->num_queued == 0)
1412 {
1413 ret = 0;
1414 GST_TRACE_OBJECT(pool,"ignore error when no capture buffer on v4l2");
1415 g_usleep(4000);
1416 goto wait_buffer_queue;
1417 }
xuesong.jiang93f2dcb2022-07-15 14:24:55 +08001418 }
bo.xiao857b8682024-09-12 16:40:32 +08001419 goto select_error;
1420 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001421
fei.deng08cb2dc2023-11-08 04:21:41 +00001422wait_buffer_queue:
bo.xiao857b8682024-09-12 16:40:32 +08001423 if (ret == 0)
1424 {
xuesong.jiangae1548e2022-05-06 16:38:46 +08001425#ifdef GST_AML_SPEC_FLOW_FOR_VBP
bo.xiao857b8682024-09-12 16:40:32 +08001426 if ((pool->obj->type == V4L2_BUF_TYPE_VIDEO_CAPTURE || pool->obj->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
1427 pool->obj->mode == GST_V4L2_IO_DMABUF_IMPORT)
1428 {
1429 GST_TRACE_OBJECT(pool, "amlmodbuf can't get buffer in capture obj dmaimport mode, try release buf from other pool");
1430 gst_aml_v4l2_buffer_pool_dump_stat(pool, GST_DUMP_CAPTURE_BP_STAT_FILENAME, try_num++);
1431 gst_aml_v4l2_buffer_pool_release_buffer_aml_patch((GstBufferPool *)pool);
1432 goto again;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001433 }
bo.xiao857b8682024-09-12 16:40:32 +08001434 else
1435#endif
1436 goto no_buffers;
1437 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001438
1439done:
bo.xiao857b8682024-09-12 16:40:32 +08001440 return GST_FLOW_OK;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001441
bo.xiao857b8682024-09-12 16:40:32 +08001442 /* ERRORS */
xuesong.jiangae1548e2022-05-06 16:38:46 +08001443stopped:
bo.xiao857b8682024-09-12 16:40:32 +08001444 {
1445 GST_DEBUG_OBJECT (pool, "stop called");
xuesong.jiangae1548e2022-05-06 16:38:46 +08001446 return GST_FLOW_FLUSHING;
bo.xiao857b8682024-09-12 16:40:32 +08001447 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001448select_error:
bo.xiao857b8682024-09-12 16:40:32 +08001449 {
1450 GST_ELEMENT_ERROR (pool->obj->element, RESOURCE, READ, (NULL),
1451 ("poll error %d: %s (%d)", ret, g_strerror (errno), errno));
xuesong.jiangae1548e2022-05-06 16:38:46 +08001452 return GST_FLOW_ERROR;
bo.xiao857b8682024-09-12 16:40:32 +08001453 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001454no_buffers:
1455 return GST_FLOW_CUSTOM_SUCCESS;
1456}
1457
1458static GstFlowReturn
bo.xiao857b8682024-09-12 16:40:32 +08001459gst_aml_v4l2_buffer_pool_qbuf (GstAmlV4l2BufferPool * pool, GstBuffer * buf,
xuesong.jiangae1548e2022-05-06 16:38:46 +08001460 GstAmlV4l2MemoryGroup *group)
1461{
bo.xiao857b8682024-09-12 16:40:32 +08001462 const GstAmlV4l2Object *obj = pool->obj;
1463 GstClockTime timestamp;
1464 gint index;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001465
bo.xiao857b8682024-09-12 16:40:32 +08001466 index = group->buffer.index;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001467
bo.xiao857b8682024-09-12 16:40:32 +08001468 if (pool->buffers[index] != NULL)
1469 goto already_queued;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001470
bo.xiao857b8682024-09-12 16:40:32 +08001471 if (V4L2_TYPE_IS_OUTPUT (obj->type))
1472 {
1473 enum v4l2_field field;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001474
bo.xiao857b8682024-09-12 16:40:32 +08001475 /* Except when field is set to alternate, buffer field is the same as
1476 * the one defined in format */
1477 if (V4L2_TYPE_IS_MULTIPLANAR (obj->type))
1478 field = obj->format.fmt.pix_mp.field;
zengliang.li32cb11e2022-11-24 12:10:26 +08001479 else
bo.xiao857b8682024-09-12 16:40:32 +08001480 field = obj->format.fmt.pix.field;
1481
1482
1483 /* NB: At this moment, we can't have alternate mode because it not handled
1484 * yet */
1485 if (field == V4L2_FIELD_ALTERNATE)
zengliang.li32cb11e2022-11-24 12:10:26 +08001486 {
bo.xiao857b8682024-09-12 16:40:32 +08001487 if (GST_BUFFER_FLAG_IS_SET(buf, GST_VIDEO_FRAME_FLAG_TFF))
1488 field = V4L2_FIELD_TOP;
1489 else
1490 field = V4L2_FIELD_BOTTOM;
zengliang.li32cb11e2022-11-24 12:10:26 +08001491 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001492
bo.xiao857b8682024-09-12 16:40:32 +08001493 group->buffer.field = field;
1494 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001495
bo.xiao857b8682024-09-12 16:40:32 +08001496 if (GST_BUFFER_TIMESTAMP_IS_VALID (buf))
1497 {
1498 timestamp = GST_BUFFER_TIMESTAMP(buf);
1499 GST_TIME_TO_TIMEVAL (timestamp, group->buffer.timestamp);
1500 }
1501 else
1502 {
1503 group->buffer.timestamp.tv_sec = -1;
1504 group->buffer.timestamp.tv_usec = 0;
1505 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001506
bo.xiao857b8682024-09-12 16:40:32 +08001507 GST_OBJECT_LOCK (pool);
1508 g_atomic_int_inc (&pool->num_queued);
1509 pool->buffers[index] = buf;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001510
bo.xiao857b8682024-09-12 16:40:32 +08001511 if (!gst_aml_v4l2_allocator_qbuf (pool->vallocator, group))
1512 goto queue_failed;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001513
bo.xiao857b8682024-09-12 16:40:32 +08001514 if (!V4L2_TYPE_IS_OUTPUT(obj->type))
1515 {
1516 gst_aml_v4l2_buffer_pool_dump_stat(pool, GST_DUMP_CAPTURE_BP_STAT_FILENAME, 0);
1517 }
1518
fei.denge8c66042024-09-26 14:12:39 +08001519 GST_DEBUG_OBJECT (pool, "queued idx:%d num:%d",index, pool->num_queued);
1520
bo.xiao857b8682024-09-12 16:40:32 +08001521 pool->empty = FALSE;
1522 g_cond_signal (&pool->empty_cond);
1523 GST_OBJECT_UNLOCK (pool);
1524
1525 return GST_FLOW_OK;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001526
1527already_queued:
bo.xiao857b8682024-09-12 16:40:32 +08001528 {
1529 GST_ERROR_OBJECT (pool, "the buffer %i was already queued", index);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001530 return GST_FLOW_ERROR;
bo.xiao857b8682024-09-12 16:40:32 +08001531 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001532queue_failed:
bo.xiao857b8682024-09-12 16:40:32 +08001533 {
1534 GST_ERROR_OBJECT (pool, "could not queue a buffer %i", index);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001535 /* Mark broken buffer to the allocator */
bo.xiao857b8682024-09-12 16:40:32 +08001536 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_TAG_MEMORY);
1537 g_atomic_int_add (&pool->num_queued, -1);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001538 pool->buffers[index] = NULL;
bo.xiao857b8682024-09-12 16:40:32 +08001539 GST_OBJECT_UNLOCK (pool);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001540 return GST_FLOW_ERROR;
bo.xiao857b8682024-09-12 16:40:32 +08001541 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001542}
1543
1544static GstFlowReturn
bo.xiao857b8682024-09-12 16:40:32 +08001545gst_aml_v4l2_buffer_pool_dqevent (GstAmlV4l2BufferPool * pool)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001546{
bo.xiao857b8682024-09-12 16:40:32 +08001547 GstAmlV4l2Object *v4l2object = pool->obj;
1548 struct v4l2_event evt;
1549 GstFlowReturn ret = GST_AML_V4L2_FLOW_UNKNOWN_EVENT;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001550
bo.xiao857b8682024-09-12 16:40:32 +08001551 memset (&evt, 0x00, sizeof (struct v4l2_event));
1552 if (v4l2object->ioctl (pool->video_fd, VIDIOC_DQEVENT, &evt) < 0)
1553 goto dqevent_failed;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001554
bo.xiao857b8682024-09-12 16:40:32 +08001555 switch (evt.type)
1556 {
xuesong.jiangae1548e2022-05-06 16:38:46 +08001557 case V4L2_EVENT_SOURCE_CHANGE:
bo.xiao857b8682024-09-12 16:40:32 +08001558 if (evt.u.src_change.changes & V4L2_EVENT_SRC_CH_RESOLUTION)
1559 ret = GST_AML_V4L2_FLOW_SOURCE_CHANGE;
1560 else
1561 {
1562 GST_WARNING_OBJECT (pool, "Unknown source change 0x%x - skipped", evt.u.src_change.changes);
bo.xiaob6afda52024-08-02 16:08:30 +08001563 ret = GST_AML_V4L2_FLOW_UNKNOWN_EVENT;
bo.xiao857b8682024-09-12 16:40:32 +08001564 }
1565 break;
1566 case V4L2_EVENT_EOS:
1567 ret = GST_AML_V4L2_FLOW_LAST_BUFFER;
1568 break;
1569 case V4L2_EVENT_PRIVATE_EXT_REPORT_DECINFO:
1570 if (evt.id == AML_DECINFO_EVENT_CC)
1571 {
1572 struct v4l2_ext_control control;
1573 struct v4l2_ext_controls ctrls;
1574 struct vdec_common_s vdec_comm;
1575 char cc_data[MAX_CC_LEN] = {0};
xuesong.jiangae1548e2022-05-06 16:38:46 +08001576
bo.xiao857b8682024-09-12 16:40:32 +08001577 memset(&ctrls, 0, sizeof(ctrls));
1578 memset(&control, 0, sizeof(control));
1579 memset(&vdec_comm, 0, sizeof(vdec_comm));
xuesong.jiangae1548e2022-05-06 16:38:46 +08001580
bo.xiao857b8682024-09-12 16:40:32 +08001581 vdec_comm.type = AML_DECINFO_GET_CC_TYPE;
1582 vdec_comm.u.usd_param.data = (void *)cc_data;
1583 vdec_comm.u.usd_param.data_size = MAX_CC_LEN;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001584
bo.xiao857b8682024-09-12 16:40:32 +08001585 control.ptr = &vdec_comm;
1586 control.id = AML_V4L2_GET_DECINFO_SET;
1587 control.size = sizeof(struct vdec_common_s);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001588
bo.xiao857b8682024-09-12 16:40:32 +08001589 ctrls.count = 1;
1590 ctrls.controls = &control;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001591
bo.xiao857b8682024-09-12 16:40:32 +08001592 if (v4l2object->ioctl (pool->video_fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
1593 {
1594 GST_DEBUG("VIDIOC_S_EXT_CTRLS fail");
1595 }
1596 else
1597 {
1598 if (v4l2object->ioctl (pool->video_fd, VIDIOC_G_EXT_CTRLS, &ctrls) == 0)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001599 {
bo.xiao857b8682024-09-12 16:40:32 +08001600 GstBuffer *cc_buffer = gst_buffer_new ();
1601 GstMemory *mem = gst_allocator_alloc (NULL, MAX_CC_LEN, NULL);
1602 gst_buffer_insert_memory (cc_buffer, -1, mem);
1603 gsize cc_size = gst_buffer_fill (cc_buffer, 0, vdec_comm.u.usd_param.data, vdec_comm.u.usd_param.data_size);
1604 GST_DEBUG("copy cc data size:%d",cc_size);
1605 cc_buffer->pts = vdec_comm.u.usd_param.meta_data.timestamp;
1606 pool->cc_buffer_list = g_list_append (pool->cc_buffer_list,cc_buffer);
1607 GST_DEBUG("cc_buffer_list size:%d",g_list_length(pool->cc_buffer_list));
1608 #if 0
1609 //dump decoder metadata
1610 GST_DEBUG("cc pack pts:%lld",vdec_comm.u.usd_param.meta_data.timestamp);
1611 int fd=open("/data/test/cc0.data",O_RDWR |O_CREAT|O_APPEND,0777);
1612 write(fd,vdec_comm.u.usd_param.data,vdec_comm.u.usd_param.data_size);
1613 close(fd);
1614 #endif
hanghang.luob216ac42023-05-12 02:56:54 +00001615 }
1616 else
bo.xiao857b8682024-09-12 16:40:32 +08001617 {
1618 GST_DEBUG("VIDIOC_G_EXT_CTRLS fail");
1619 }
1620 }
1621 ret = GST_AML_V4L2_FLOW_CC_DATA;
1622 }
1623 else
1624 {
1625 GST_WARNING_OBJECT (pool, "Unknown DECINFO 0x%x - skipped", evt.id);
1626 ret = GST_AML_V4L2_FLOW_UNKNOWN_EVENT;
1627 }
1628 break;
1629 case V4L2_EVENT_PRIVATE_EXT_REPORT_ERROR_FRAME:
xuesong.jiangae1548e2022-05-06 16:38:46 +08001630 {
bo.xiao857b8682024-09-12 16:40:32 +08001631 guint64 pts = 0;
1632 memcpy(&pts, &(evt.u.data[0]), sizeof(guint64));
1633 v4l2object->num_error_frames += 1;
1634 v4l2object->error_frame_pts = pts;
1635 GST_WARNING_OBJECT (pool, "decoding video frame error,pts:%" GST_TIME_FORMAT ",total %d",
1636 GST_TIME_ARGS(pts),v4l2object->num_error_frames);
1637 ret = GST_AML_V4L2_FLOW_DECODING_ERROR;
1638 } break;
1639 default:
1640 GST_WARNING_OBJECT (pool, "Unknown evt.type 0x%x - skipped", evt.type);
1641 ret = GST_AML_V4L2_FLOW_UNKNOWN_EVENT;
1642 break;
1643 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001644
bo.xiao857b8682024-09-12 16:40:32 +08001645 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001646
bo.xiao857b8682024-09-12 16:40:32 +08001647 /* ERRORS */
1648dqevent_failed:
1649 {
1650 return GST_FLOW_ERROR;
1651 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001652}
1653
1654static GstFlowReturn
bo.xiao857b8682024-09-12 16:40:32 +08001655gst_aml_v4l2_buffer_pool_dqbuf (GstAmlV4l2BufferPool * pool, GstBuffer ** buffer,
1656 gboolean wait)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001657{
bo.xiao857b8682024-09-12 16:40:32 +08001658 GstFlowReturn res;
1659 GstBuffer *outbuf = NULL;
1660 GstAmlV4l2Object *obj = pool->obj;
1661 GstClockTime timestamp;
1662 GstAmlV4l2MemoryGroup *group;
1663 GstVideoMeta *vmeta;
1664 gsize size;
1665 gint i;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001666
bo.xiao857b8682024-09-12 16:40:32 +08001667 res = gst_aml_v4l2_allocator_dqbuf (pool->vallocator, &group);
1668 if (res == GST_FLOW_EOS)
1669 goto eos;
1670 if (res != GST_FLOW_OK)
1671 goto dqbuf_failed;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001672
bo.xiao857b8682024-09-12 16:40:32 +08001673 /* get our GstBuffer with that index from the pool, if the buffer was
1674 * outstanding we have a serious problem.
1675 */
1676 outbuf = pool->buffers[group->buffer.index];
1677 if (outbuf == NULL)
1678 goto no_buffer;
1679
1680 /* mark the buffer outstanding */
1681 pool->buffers[group->buffer.index] = NULL;
1682 if (g_atomic_int_dec_and_test (&pool->num_queued))
1683 {
1684 GST_OBJECT_LOCK (pool);
1685 pool->empty = TRUE;
1686 GST_OBJECT_UNLOCK (pool);
1687 }
1688
1689 if (-1 == group->buffer.timestamp.tv_sec)
1690 timestamp = GST_CLOCK_TIME_NONE;
1691 else
1692 timestamp = GST_TIMEVAL_TO_TIME (group->buffer.timestamp);
1693
1694 size = 0;
1695 vmeta = gst_buffer_get_video_meta (outbuf);
1696 for (i = 0; i < group->n_mem; i++)
1697 {
1698 GST_LOG_OBJECT(pool,
1699 "dequeued buffer %p seq:%d (ix=%d), mem %p used %d, plane=%d, flags %08x, ts %" GST_TIME_FORMAT ", pool-queued=%d, buffer=%p", outbuf,
1700 group->buffer.sequence, group->buffer.index, group->mem[i],
1701 group->planes[i].bytesused, i, group->buffer.flags,
1702 GST_TIME_ARGS(timestamp), pool->num_queued, outbuf);
1703
1704 if (vmeta)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001705 {
bo.xiao857b8682024-09-12 16:40:32 +08001706 vmeta->offset[i] = size;
1707 size += gst_memory_get_sizes (group->mem[i], NULL, NULL);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001708 }
bo.xiao857b8682024-09-12 16:40:32 +08001709 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001710
bo.xiao857b8682024-09-12 16:40:32 +08001711 /* Ignore timestamp and field for OUTPUT device */
1712 if (V4L2_TYPE_IS_OUTPUT (obj->type))
1713 goto done;
1714
1715 /* Check for driver bug in reporting feild */
1716 if (group->buffer.field == V4L2_FIELD_ANY)
1717 {
1718 /* Only warn once to avoid the spamming */
1719#ifndef GST_DISABLE_GST_DEBUG
1720 if (!pool->has_warned_on_buggy_field)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001721 {
bo.xiao857b8682024-09-12 16:40:32 +08001722 pool->has_warned_on_buggy_field = TRUE;
1723 GST_WARNING_OBJECT (pool,
1724 "Driver should never set v4l2_buffer.field to ANY");
1725 }
1726#endif
1727
1728 /* Use the value from the format (works for UVC bug) */
1729 group->buffer.field = obj->format.fmt.pix.field;
1730
1731 /* If driver also has buggy S_FMT, assume progressive */
1732 if (group->buffer.field == V4L2_FIELD_ANY)
1733 {
1734#ifndef GST_DISABLE_GST_DEBUG
1735 if (!pool->has_warned_on_buggy_field)
1736 {
1737 pool->has_warned_on_buggy_field = TRUE;
1738 GST_WARNING_OBJECT (pool,
1739 "Driver should never set v4l2_format.pix.field to ANY");
1740 }
1741#endif
1742
1743 group->buffer.field = V4L2_FIELD_NONE;
1744 }
1745 }
1746
1747 /* set top/bottom field first if v4l2_buffer has the information */
1748 switch (group->buffer.field)
1749 {
1750 case V4L2_FIELD_NONE:
1751 GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1752 GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1753 break;
1754 case V4L2_FIELD_INTERLACED_TB:
1755 GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1756 GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1757 break;
1758 case V4L2_FIELD_INTERLACED_BT:
1759 GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1760 GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1761 break;
1762 case V4L2_FIELD_INTERLACED:
1763 GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1764 if (obj->tv_norm == V4L2_STD_NTSC_M ||
1765 obj->tv_norm == V4L2_STD_NTSC_M_JP ||
1766 obj->tv_norm == V4L2_STD_NTSC_M_KR)
1767 {
1768 GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1769 }
1770 else
1771 {
1772 GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1773 }
1774 break;
1775 default:
1776 GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1777 GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1778 GST_FIXME_OBJECT (pool,
1779 "Unhandled enum v4l2_field %d - treating as progressive",
1780 group->buffer.field);
1781 break;
1782 }
1783
1784 if (GST_VIDEO_INFO_FORMAT (&obj->info) == GST_VIDEO_FORMAT_ENCODED)
1785 {
1786 if ((group->buffer.flags & V4L2_BUF_FLAG_KEYFRAME) ||
1787 GST_AML_V4L2_PIXELFORMAT (obj) == V4L2_PIX_FMT_MJPEG ||
1788 GST_AML_V4L2_PIXELFORMAT (obj) == V4L2_PIX_FMT_JPEG ||
1789 GST_AML_V4L2_PIXELFORMAT (obj) == V4L2_PIX_FMT_PJPG)
1790 GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1791 else
1792 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1793 }
1794
1795 if (group->buffer.flags & V4L2_BUF_FLAG_ERROR)
1796 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_CORRUPTED);
1797
1798 GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
1799 GST_BUFFER_OFFSET (outbuf) = group->buffer.sequence;
1800 GST_BUFFER_OFFSET_END (outbuf) = group->buffer.sequence + 1;
1801
1802done:
1803 *buffer = outbuf;
1804 if ((group->buffer.flags & V4L2_BUF_FLAG_LAST) &&(group->buffer.bytesused == 0))
1805 {
1806 GST_DEBUG_OBJECT (pool,"dequeued empty buffer");
1807 GST_BUFFER_FLAG_SET(*buffer, GST_AML_V4L2_BUFFER_FLAG_LAST_EMPTY);
1808 }
1809
1810 if (!V4L2_TYPE_IS_OUTPUT(obj->type))
1811 {
1812 gst_aml_v4l2_buffer_pool_dump_stat(pool, GST_DUMP_CAPTURE_BP_STAT_FILENAME, 0);
1813 }
1814
1815 return res;
1816
1817 /* ERRORS */
1818eos:
1819 {
1820 return GST_FLOW_EOS;
1821 }
1822dqbuf_failed:
1823 {
1824 return GST_FLOW_ERROR;
1825 }
1826no_buffer:
1827 {
1828 GST_ERROR_OBJECT (pool, "No free buffer found in the pool at index %d.",
1829 group->buffer.index);
1830 return GST_FLOW_ERROR;
1831 }
1832}
1833
1834static GstFlowReturn
1835gst_aml_v4l2_buffer_pool_dequeue (GstAmlV4l2BufferPool * pool, GstBuffer ** buffer,
1836 gboolean wait)
1837{
1838 GstFlowReturn res;
1839 GstAmlV4l2Object *obj = pool->obj;
1840
1841 if ((res = gst_aml_v4l2_buffer_pool_poll (pool, wait)) != GST_FLOW_OK)
1842 goto poll_failed;
1843
1844 if (obj->can_wait_event && gst_poll_fd_can_read_pri (pool->poll, &pool->pollfd))
1845 {
1846 GstFlowReturn res_event = gst_aml_v4l2_buffer_pool_dqevent(pool);
1847 if (res_event != GST_FLOW_OK)
1848 {
1849 /* when drive V4l2 receive cmd_stop, it will finish current decoding frame, then creat
1850 * a EOS event and a empty buff. if gstreamer dq EOS event first ,the last frame will be drop,
1851 * this a question
1852 */
1853 if (res_event == GST_AML_V4L2_FLOW_LAST_BUFFER)
1854 {
1855 GST_DEBUG_OBJECT(pool," reiceive EOS event, drop it");
1856 }
1857 else
1858 return res_event;
1859 }
1860 }
1861 if (res == GST_FLOW_CUSTOM_SUCCESS)
1862 {
1863 GST_LOG_OBJECT (pool, "nothing to dequeue");
1864 *buffer = NULL;
1865 return res;
1866 }
1867
1868 GST_LOG_OBJECT (pool, "dequeueing a buffer");
1869 return gst_aml_v4l2_buffer_pool_dqbuf(pool, buffer, wait);
1870
1871 /* ERRORS */
1872poll_failed:
1873 {
1874 GST_DEBUG_OBJECT (pool, "poll error %s", gst_flow_get_name (res));
1875 return res;
1876 }
1877}
1878
1879static GstFlowReturn
1880gst_aml_v4l2_buffer_pool_acquire_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
1881 GstBufferPoolAcquireParams * params)
1882{
1883 GstFlowReturn ret;
1884 GstAmlV4l2BufferPool *pool = GST_AML_V4L2_BUFFER_POOL (bpool);
1885 GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
1886 GstAmlV4l2Object *obj = pool->obj;
1887
1888 GST_DEBUG_OBJECT (pool, "acquire");
1889
1890 /* If this is being called to resurrect a lost buffer */
1891 if (params && params->flags & GST_V4L2_BUFFER_POOL_ACQUIRE_FLAG_RESURRECT)
1892 {
1893 ret = pclass->acquire_buffer (bpool, buffer, params);
1894 goto done;
1895 }
1896
1897 switch (obj->type)
1898 {
xuesong.jiangae1548e2022-05-06 16:38:46 +08001899 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1900 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
bo.xiao857b8682024-09-12 16:40:32 +08001901 /* capture, This function should return a buffer with new captured data */
1902 switch (obj->mode)
1903 {
xuesong.jiangae1548e2022-05-06 16:38:46 +08001904 case GST_V4L2_IO_RW:
1905 {
bo.xiao857b8682024-09-12 16:40:32 +08001906 /* take empty buffer from the pool */
1907 ret = pclass->acquire_buffer (bpool, buffer, params);
1908 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001909 }
1910 case GST_V4L2_IO_DMABUF:
1911 case GST_V4L2_IO_MMAP:
1912 case GST_V4L2_IO_USERPTR:
xuesong.jiang3df0f7b2022-11-29 14:52:45 +08001913 {
bo.xiao857b8682024-09-12 16:40:32 +08001914 /* just dequeue a buffer, we basically use the queue of v4l2 as the
1915 * storage for our buffers. This function does poll first so we can
1916 * interrupt it fine. */
1917 ret = gst_aml_v4l2_buffer_pool_dequeue(pool, buffer, TRUE);
xuesong.jiang3df0f7b2022-11-29 14:52:45 +08001918
bo.xiao857b8682024-09-12 16:40:32 +08001919 break;
xuesong.jiang3df0f7b2022-11-29 14:52:45 +08001920 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001921 case GST_V4L2_IO_DMABUF_IMPORT:
1922 {
1923#ifdef GST_AML_SPEC_FLOW_FOR_VBP
bo.xiao857b8682024-09-12 16:40:32 +08001924 GST_DEBUG_OBJECT(pool, "amlmodbuf return free buf before acquire buf");
1925 gst_aml_v4l2_buffer_pool_release_buffer_aml_patch(bpool);
1926 ret = gst_aml_v4l2_buffer_pool_dequeue(pool, buffer, FALSE);
1927 GST_DEBUG_OBJECT(pool, "amlmodbuf dequeue return ret:%d", ret);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001928#else
bo.xiao857b8682024-09-12 16:40:32 +08001929 /* just dequeue a buffer, we basically use the queue of v4l2 as the
1930 * storage for our buffers. This function does poll first so we can
1931 * interrupt it fine. */
1932 ret = gst_aml_v4l2_buffer_pool_dequeue(pool, buffer, TRUE);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001933#endif
bo.xiao857b8682024-09-12 16:40:32 +08001934 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001935 }
1936 default:
bo.xiao857b8682024-09-12 16:40:32 +08001937 ret = GST_FLOW_ERROR;
1938 g_assert_not_reached ();
1939 break;
1940 }
1941 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001942
1943 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1944 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
bo.xiao857b8682024-09-12 16:40:32 +08001945 /* playback, This function should return an empty buffer */
1946 switch (obj->mode)
1947 {
xuesong.jiangae1548e2022-05-06 16:38:46 +08001948 case GST_V4L2_IO_RW:
bo.xiao857b8682024-09-12 16:40:32 +08001949 /* get an empty buffer */
1950 ret = pclass->acquire_buffer (bpool, buffer, params);
1951 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001952
1953 case GST_V4L2_IO_MMAP:
1954 case GST_V4L2_IO_DMABUF:
1955 case GST_V4L2_IO_USERPTR:
1956 case GST_V4L2_IO_DMABUF_IMPORT:
bo.xiao857b8682024-09-12 16:40:32 +08001957 /* get a free unqueued buffer */
1958 ret = pclass->acquire_buffer (bpool, buffer, params);
1959 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001960
1961 default:
bo.xiao857b8682024-09-12 16:40:32 +08001962 ret = GST_FLOW_ERROR;
1963 g_assert_not_reached ();
1964 break;
1965 }
1966 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001967
1968 default:
bo.xiao857b8682024-09-12 16:40:32 +08001969 ret = GST_FLOW_ERROR;
1970 g_assert_not_reached ();
1971 break;
1972 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001973done:
bo.xiao857b8682024-09-12 16:40:32 +08001974 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001975}
1976
1977static void
bo.xiao857b8682024-09-12 16:40:32 +08001978gst_aml_v4l2_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
xuesong.jiangae1548e2022-05-06 16:38:46 +08001979{
bo.xiao857b8682024-09-12 16:40:32 +08001980 GstAmlV4l2BufferPool *pool = GST_AML_V4L2_BUFFER_POOL (bpool);
1981 GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS(parent_class);
1982 GstAmlV4l2Object *obj = pool->obj;
xuesong.jiangae1548e2022-05-06 16:38:46 +08001983
bo.xiao857b8682024-09-12 16:40:32 +08001984 GST_DEBUG_OBJECT(pool, "release buffer %p", buffer);
xuesong.jiangae1548e2022-05-06 16:38:46 +08001985
bo.xiao857b8682024-09-12 16:40:32 +08001986 /* If the buffer's pool has been orphaned, dispose of it so that
1987 * the pool resources can be freed */
1988 if (pool->orphaned)
1989 {
1990 GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_FLAG_TAG_MEMORY);
1991 pclass->release_buffer(bpool, buffer);
1992 return;
1993 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08001994
bo.xiao857b8682024-09-12 16:40:32 +08001995 switch (obj->type)
1996 {
1997 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1998 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1999 /* capture, put the buffer back in the queue so that we can refill it
2000 * later. */
2001 switch (obj->mode)
2002 {
2003 case GST_V4L2_IO_RW:
2004 /* release back in the pool */
2005 pclass->release_buffer(bpool, buffer);
2006 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002007
bo.xiao857b8682024-09-12 16:40:32 +08002008 case GST_V4L2_IO_DMABUF:
2009 case GST_V4L2_IO_MMAP:
2010 case GST_V4L2_IO_USERPTR:
2011 case GST_V4L2_IO_DMABUF_IMPORT:
2012 {
2013 GstAmlV4l2MemoryGroup *group;
2014 if (gst_aml_v4l2_is_buffer_valid(buffer, &group))
2015 {
2016 GstFlowReturn ret = GST_FLOW_OK;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002017
bo.xiao857b8682024-09-12 16:40:32 +08002018 gst_aml_v4l2_allocator_reset_group(pool->vallocator, group);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002019
2020#ifdef GST_AML_SPEC_FLOW_FOR_VBP
bo.xiao857b8682024-09-12 16:40:32 +08002021 GST_DEBUG_OBJECT(pool, "amlmodbuf trace in add flow with buf:%p index:%d", buffer, group->buffer.index);
2022 pool->read_to_free_bufs[group->buffer.index] = buffer;
2023 pool->ready_to_free_buf_num++;
2024 if (gst_aml_v4l2_buffer_pool_release_buffer_aml_patch(bpool))
2025 {
2026 GST_DEBUG_OBJECT(pool, "amlmodbuf execute aml code logic, skip the following flow");
2027 return;
2028 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002029#endif
bo.xiao857b8682024-09-12 16:40:32 +08002030 /* queue back in the device */
2031 if (pool->other_pool)
2032 ret = gst_aml_v4l2_buffer_pool_prepare_buffer(pool, buffer, NULL);
2033 if (ret != GST_FLOW_OK ||
2034 gst_aml_v4l2_buffer_pool_qbuf(pool, buffer, group) != GST_FLOW_OK)
2035 pclass->release_buffer(bpool, buffer);
2036 }
2037 else
2038 {
2039 /* Simply release invalide/modified buffer, the allocator will
2040 * give it back later */
2041 GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_FLAG_TAG_MEMORY);
2042 pclass->release_buffer(bpool, buffer);
2043 }
2044 break;
2045 }
2046 default:
2047 g_assert_not_reached();
2048 break;
2049 }
2050 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002051
bo.xiao857b8682024-09-12 16:40:32 +08002052 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
2053 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
2054 switch (obj->mode)
2055 {
xuesong.jiangae1548e2022-05-06 16:38:46 +08002056 case GST_V4L2_IO_RW:
2057 /* release back in the pool */
2058 pclass->release_buffer(bpool, buffer);
2059 break;
2060
2061 case GST_V4L2_IO_MMAP:
2062 case GST_V4L2_IO_DMABUF:
2063 case GST_V4L2_IO_USERPTR:
2064 case GST_V4L2_IO_DMABUF_IMPORT:
2065 {
2066 GstAmlV4l2MemoryGroup *group;
2067 guint index;
2068
2069 if (!gst_aml_v4l2_is_buffer_valid(buffer, &group))
2070 {
2071 /* Simply release invalide/modified buffer, the allocator will
2072 * give it back later */
2073 GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_FLAG_TAG_MEMORY);
2074 pclass->release_buffer(bpool, buffer);
2075 break;
2076 }
2077
2078 index = group->buffer.index;
2079
2080 if (pool->buffers[index] == NULL)
2081 {
2082 GST_LOG_OBJECT(pool, "buffer %u not queued, putting on free list",
2083 index);
2084
2085 /* Remove qdata, this will unmap any map data in userptr */
2086 gst_mini_object_set_qdata(GST_MINI_OBJECT(buffer),
2087 GST_AML_V4L2_IMPORT_QUARK, NULL, NULL);
2088
2089 /* reset to default size */
2090 gst_aml_v4l2_allocator_reset_group(pool->vallocator, group);
2091
2092 /* playback, put the buffer back in the queue to refill later. */
2093 pclass->release_buffer(bpool, buffer);
2094 }
2095 else
2096 {
2097 /* the buffer is queued in the device but maybe not played yet. We just
2098 * leave it there and not make it available for future calls to acquire
2099 * for now. The buffer will be dequeued and reused later. */
2100 GST_LOG_OBJECT(pool, "buffer %u is queued", index);
2101 }
2102 break;
2103 }
2104
2105 default:
bo.xiao857b8682024-09-12 16:40:32 +08002106 g_assert_not_reached ();
2107 break;
2108 }
2109 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002110
2111 default:
bo.xiao857b8682024-09-12 16:40:32 +08002112 g_assert_not_reached ();
2113 break;
2114 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002115}
2116
2117#ifdef GST_AML_SPEC_FLOW_FOR_VBP
2118static gboolean
2119gst_aml_v4l2_buffer_pool_release_buffer_aml_patch(GstBufferPool *bpool)
2120{
bo.xiao857b8682024-09-12 16:40:32 +08002121 GstFlowReturn ret = GST_FLOW_OK;
2122 GstAmlV4l2BufferPool *pool = GST_AML_V4L2_BUFFER_POOL(bpool);
2123 GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS(parent_class);
2124 GstAmlV4l2Object *obj = pool->obj;
2125 GstBuffer *src = NULL;
2126 GstBufferPoolAcquireParams params;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002127
bo.xiao857b8682024-09-12 16:40:32 +08002128 if (!(obj->mode == GST_V4L2_IO_DMABUF_IMPORT && pool->other_pool))
2129 {
2130 GST_WARNING_OBJECT(pool,"please check GstV4l2IOMode!");
2131 return FALSE;
2132 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002133
bo.xiao857b8682024-09-12 16:40:32 +08002134 /*resolution change flow start*/
2135 if (obj->old_other_pool || obj->old_old_other_pool)
2136 {
2137 gint outstanding_buf_num = 0;
hanghang.luodc626902024-08-23 14:59:27 +08002138
bo.xiao857b8682024-09-12 16:40:32 +08002139 outstanding_buf_num = gst_aml_v4l2_object_get_outstanding_capture_buf_num(obj);
2140 GST_DEBUG_OBJECT(pool, "amlmodbuf oop outstanding buf num %d", outstanding_buf_num);
2141 if (outstanding_buf_num != obj->outstanding_buf_num)
2142 {
2143 guint update = 0, need_buf_num = 0;
2144 GstStructure *config = NULL;
2145 guint size, min_buffers = 0, old_max_buffers = 0;
xuesong.jiangc5dac0f2023-02-01 14:42:24 +08002146
bo.xiao857b8682024-09-12 16:40:32 +08002147 if (outstanding_buf_num > obj->outstanding_buf_num)
2148 {
2149 GST_ERROR_OBJECT(pool, "amlmodbuf old other pool recycle buffer error, outstanding from %d to %d", obj->outstanding_buf_num, outstanding_buf_num);
2150 return FALSE;
2151 }
2152 GST_DEBUG_OBJECT(pool, "amlmodbuf oop outstanding buf num from %d reduce to %d", obj->outstanding_buf_num, outstanding_buf_num);
hanghang.luodc626902024-08-23 14:59:27 +08002153
bo.xiao857b8682024-09-12 16:40:32 +08002154 /*get buffer pool config to calculate max buffer count*/
2155 config = gst_buffer_pool_get_config(pool->other_pool);
2156 if (config)
2157 {
2158 if (gst_buffer_pool_config_get_params(config, NULL, &size, &min_buffers, &old_max_buffers) != FALSE)
2159 {
2160 if (G_UNLIKELY(obj->min_buffers < old_max_buffers))
2161 {
2162 GST_ERROR("Too many drm buffers are applied");
2163 }
2164 else if (obj->min_buffers == old_max_buffers)
2165 {
2166 update = 0;
2167 }
2168 else if (obj->min_buffers > old_max_buffers)
2169 {
2170 GST_INFO("display occupy: %d,total num of buffer rotations: %u op have set max buf: %u",
2171 outstanding_buf_num,
2172 obj->min_buffers,
2173 old_max_buffers);
2174 update = obj->outstanding_buf_num - outstanding_buf_num; // available buf num
2175 need_buf_num = obj->min_buffers - old_max_buffers; //need buf num
2176 update = need_buf_num >= update ? update : need_buf_num;
2177 }
2178 }
2179 }
2180 if (update > 0 && !gst_buffer_pool_increase_max_num(pool->other_pool, update))
2181 {
2182 GST_ERROR_OBJECT(pool, "amlmodbuf update other pool max buffer num error");
2183 return FALSE;
2184 }
2185 obj->outstanding_buf_num = outstanding_buf_num;
2186 }
2187 }
2188 /*resolution change flow stop*/
hanghang.luodc626902024-08-23 14:59:27 +08002189
bo.xiao857b8682024-09-12 16:40:32 +08002190 /*buffer match flow*/
2191 memset(&params, 0, sizeof(GstBufferPoolAcquireParams));
2192 params.flags = GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT;
2193 GST_TRACE_OBJECT(pool, "before release ready_to_free_buf_num:%d", pool->ready_to_free_buf_num);
2194 while (pool->ready_to_free_buf_num && gst_buffer_pool_acquire_buffer(pool->other_pool, &src, &params) != GST_FLOW_ERROR && src != NULL)
2195 {
2196 gint i = 0;
hanghang.luodc626902024-08-23 14:59:27 +08002197
bo.xiao857b8682024-09-12 16:40:32 +08002198 for (; i < VIDEO_MAX_FRAME; i++)
2199 {
2200 GST_TRACE_OBJECT(pool, "amlmodbuf check index:%d", i);
2201 if (pool->read_to_free_bufs[i])
2202 {
2203 GstBuffer *bind_drm_buf = gst_mini_object_get_qdata(GST_MINI_OBJECT(pool->read_to_free_bufs[i]), GST_AML_V4L2_IMPORT_QUARK);
2204 if (bind_drm_buf == NULL)
2205 {
2206 GST_DEBUG_OBJECT(pool, "init flow, bind v4l2 capture buf[%d]:%p with drm buf:%p", i, pool->read_to_free_bufs[i], src);
2207 }
2208 else if (src != bind_drm_buf)
2209 {
2210 continue;
2211 }
hanghang.luodc626902024-08-23 14:59:27 +08002212
bo.xiao857b8682024-09-12 16:40:32 +08002213 GST_TRACE_OBJECT(pool, "v4l2 capture buf[%d]:%p found bind drm buf:%p", i, pool->read_to_free_bufs[i], src);
2214 GstFlowReturn isvalid = GST_FLOW_OK;
2215 GstAmlV4l2MemoryGroup *tmp_group = NULL;
hanghang.luodc626902024-08-23 14:59:27 +08002216
bo.xiao857b8682024-09-12 16:40:32 +08002217 // bind_drm_buf= gst_mini_object_steal_qdata(GST_MINI_OBJECT(pool->read_to_free_bufs[i]), GST_AML_V4L2_IMPORT_QUARK);
2218 ret = gst_aml_v4l2_buffer_pool_import_dmabuf(pool, pool->read_to_free_bufs[i], src);
2219 gst_buffer_unref(src);
2220 src = NULL;
2221 isvalid = gst_aml_v4l2_is_buffer_valid(pool->read_to_free_bufs[i], &tmp_group);
2222 if ((ret != GST_FLOW_OK && isvalid) || gst_aml_v4l2_buffer_pool_qbuf(pool, pool->read_to_free_bufs[i], tmp_group) != GST_FLOW_OK)
2223 {
2224 GST_ERROR_OBJECT(pool, "amlmodbuf go into error flow");
2225 pclass->release_buffer(bpool, pool->read_to_free_bufs[i]);
2226 }
2227 pool->read_to_free_bufs[i] = NULL;
2228 pool->ready_to_free_buf_num--;
2229 break;
2230 }
2231 }
2232 if (i == VIDEO_MAX_FRAME)
2233 {
2234 GST_ERROR_OBJECT(pool, "drm buf:%p can't match any v4l2 capture buf, error", src);
2235 gst_buffer_unref(src);
2236 src = NULL;
2237 return FALSE;
2238 }
2239 }
2240 GST_TRACE_OBJECT(pool, "after release ready_to_free_buf_num:%d", pool->ready_to_free_buf_num);
2241 return TRUE;
hanghang.luodc626902024-08-23 14:59:27 +08002242
xuesong.jiangae1548e2022-05-06 16:38:46 +08002243}
2244#endif
2245
2246static void
bo.xiao857b8682024-09-12 16:40:32 +08002247gst_aml_v4l2_buffer_pool_dispose (GObject * object)
xuesong.jiangae1548e2022-05-06 16:38:46 +08002248{
bo.xiao857b8682024-09-12 16:40:32 +08002249 GstAmlV4l2BufferPool *pool = GST_AML_V4L2_BUFFER_POOL (object);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002250
bo.xiao857b8682024-09-12 16:40:32 +08002251 if (pool->vallocator)
2252 gst_object_unref (pool->vallocator);
2253 pool->vallocator = NULL;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002254
bo.xiao857b8682024-09-12 16:40:32 +08002255 if (pool->allocator)
2256 gst_object_unref (pool->allocator);
2257 pool->allocator = NULL;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002258
bo.xiao857b8682024-09-12 16:40:32 +08002259 if (pool->other_pool)
2260 gst_object_unref (pool->other_pool);
2261 pool->other_pool = NULL;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002262
bo.xiao857b8682024-09-12 16:40:32 +08002263 G_OBJECT_CLASS (parent_class)->dispose (object);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002264}
2265
2266static void
bo.xiao857b8682024-09-12 16:40:32 +08002267gst_aml_v4l2_buffer_pool_finalize (GObject * object)
xuesong.jiangae1548e2022-05-06 16:38:46 +08002268{
bo.xiao857b8682024-09-12 16:40:32 +08002269 GstAmlV4l2BufferPool *pool = GST_AML_V4L2_BUFFER_POOL (object);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002270
bo.xiao857b8682024-09-12 16:40:32 +08002271 if (g_list_length (pool->cc_buffer_list) > 0)
2272 {
2273 g_list_free_full (pool->cc_buffer_list, (GDestroyNotify) gst_buffer_unref);
zengliang.lidcd41462024-06-19 16:05:12 +08002274 pool->cc_buffer_list = NULL;
bo.xiao857b8682024-09-12 16:40:32 +08002275 }
2276
2277 if (pool->video_fd >= 0)
2278 pool->obj->close (pool->video_fd);
2279
2280 gst_poll_free (pool->poll);
2281
2282 /* This can't be done in dispose method because we must not set pointer
2283 * to NULL as it is part of the v4l2object and dispose could be called
2284 * multiple times */
2285 gst_object_unref (pool->obj->element);
2286
2287 g_cond_clear (&pool->empty_cond);
2288
2289 /* FIXME have we done enough here ? */
2290
2291 G_OBJECT_CLASS (parent_class)->finalize (object);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002292}
2293
2294static void
bo.xiao857b8682024-09-12 16:40:32 +08002295gst_aml_v4l2_buffer_pool_init (GstAmlV4l2BufferPool * pool)
xuesong.jiangae1548e2022-05-06 16:38:46 +08002296{
bo.xiao857b8682024-09-12 16:40:32 +08002297 pool->poll = gst_poll_new (TRUE);
2298 pool->can_poll_device = TRUE;
2299 g_cond_init (&pool->empty_cond);
2300 GST_OBJECT_LOCK(pool);
2301 pool->empty = TRUE;
2302 GST_OBJECT_UNLOCK(pool);
2303 pool->orphaned = FALSE;
2304 pool->cc_buffer_list = NULL;
2305}
xuesong.jiangae1548e2022-05-06 16:38:46 +08002306
bo.xiao857b8682024-09-12 16:40:32 +08002307static void
2308gst_aml_v4l2_buffer_pool_class_init (GstAmlV4l2BufferPoolClass * klass)
2309{
2310 GObjectClass *object_class = G_OBJECT_CLASS (klass);
2311 GstBufferPoolClass *bufferpool_class = GST_BUFFER_POOL_CLASS (klass);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002312
bo.xiao857b8682024-09-12 16:40:32 +08002313 object_class->dispose = gst_aml_v4l2_buffer_pool_dispose;
2314 object_class->finalize = gst_aml_v4l2_buffer_pool_finalize;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002315
bo.xiao857b8682024-09-12 16:40:32 +08002316 bufferpool_class->start = gst_aml_v4l2_buffer_pool_start;
2317 bufferpool_class->stop = gst_aml_v4l2_buffer_pool_stop;
2318 bufferpool_class->set_config = gst_aml_v4l2_buffer_pool_set_config;
2319 bufferpool_class->alloc_buffer = gst_aml_v4l2_buffer_pool_alloc_buffer;
2320 bufferpool_class->acquire_buffer = gst_aml_v4l2_buffer_pool_acquire_buffer;
2321 bufferpool_class->release_buffer = gst_aml_v4l2_buffer_pool_release_buffer;
2322 bufferpool_class->flush_start = gst_aml_v4l2_buffer_pool_flush_start;
2323 bufferpool_class->flush_stop = gst_aml_v4l2_buffer_pool_flush_stop;
2324
2325 GST_DEBUG_CATEGORY_INIT (amlv4l2bufferpool_debug, "amlv4l2bufferpool", 0,
2326 "V4L2 Buffer Pool");
2327 GST_DEBUG_CATEGORY_GET (CAT_PERFORMANCE, "GST_PERFORMANCE");
xuesong.jiangae1548e2022-05-06 16:38:46 +08002328}
2329
2330/**
2331 * gst_aml_v4l2_buffer_pool_new:
2332 * @obj: the v4l2 object owning the pool
2333 *
2334 * Construct a new buffer pool.
2335 *
2336 * Returns: the new pool, use gst_object_unref() to free resources
2337 */
2338GstBufferPool *
bo.xiao857b8682024-09-12 16:40:32 +08002339gst_aml_v4l2_buffer_pool_new (GstAmlV4l2Object * obj, GstCaps * caps)
xuesong.jiangae1548e2022-05-06 16:38:46 +08002340{
bo.xiao857b8682024-09-12 16:40:32 +08002341 GstAmlV4l2BufferPool *pool;
2342 GstStructure *config;
2343 gchar *name, *parent_name;
2344 gint fd;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002345
bo.xiao857b8682024-09-12 16:40:32 +08002346 fd = obj->dup (obj->video_fd);
2347 if (fd < 0)
2348 goto dup_failed;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002349
bo.xiao857b8682024-09-12 16:40:32 +08002350 /* setting a significant unique name */
2351 parent_name = gst_object_get_name (GST_OBJECT (obj->element));
2352 name = g_strconcat(parent_name, ":", "pool:",
2353 V4L2_TYPE_IS_OUTPUT(obj->type) ? "sink" : "src", NULL);
2354 g_free (parent_name);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002355
bo.xiao857b8682024-09-12 16:40:32 +08002356 pool = (GstAmlV4l2BufferPool *) g_object_new (GST_TYPE_AML_V4L2_BUFFER_POOL,
2357 "name", name, NULL);
2358 g_object_ref_sink (pool);
2359 g_free (name);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002360
bo.xiao857b8682024-09-12 16:40:32 +08002361 gst_poll_fd_init (&pool->pollfd);
2362 pool->pollfd.fd = fd;
2363 gst_poll_add_fd (pool->poll, &pool->pollfd);
2364 if (V4L2_TYPE_IS_OUTPUT (obj->type))
2365 {
2366 gst_poll_fd_ctl_write (pool->poll, &pool->pollfd, TRUE);
2367 }
2368 else
2369 {
2370 gst_poll_fd_ctl_read (pool->poll, &pool->pollfd, TRUE);
2371 gst_poll_fd_ctl_pri (pool->poll, &pool->pollfd, TRUE);
2372 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002373
bo.xiao857b8682024-09-12 16:40:32 +08002374 pool->video_fd = fd;
2375 pool->obj = obj;
2376 pool->can_poll_device = TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002377
bo.xiao857b8682024-09-12 16:40:32 +08002378 pool->vallocator = gst_aml_v4l2_allocator_new (GST_OBJECT (pool), obj);
2379 if (pool->vallocator == NULL)
2380 goto allocator_failed;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002381
bo.xiao857b8682024-09-12 16:40:32 +08002382 gst_object_ref (obj->element);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002383
bo.xiao857b8682024-09-12 16:40:32 +08002384 config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool));
2385 gst_buffer_pool_config_set_params (config, caps, obj->info.size, 0, 0);
2386 /* This will simply set a default config, but will not configure the pool
2387 * because min and max are not valid */
2388 (void)gst_buffer_pool_set_config (GST_BUFFER_POOL_CAST(pool), config);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002389
bo.xiao857b8682024-09-12 16:40:32 +08002390 return GST_BUFFER_POOL (pool);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002391
bo.xiao857b8682024-09-12 16:40:32 +08002392 /* ERRORS */
xuesong.jiangae1548e2022-05-06 16:38:46 +08002393dup_failed:
bo.xiao857b8682024-09-12 16:40:32 +08002394 {
2395 GST_ERROR ("failed to dup fd %d (%s)", errno, g_strerror (errno));
xuesong.jiangae1548e2022-05-06 16:38:46 +08002396 return NULL;
bo.xiao857b8682024-09-12 16:40:32 +08002397 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002398allocator_failed:
bo.xiao857b8682024-09-12 16:40:32 +08002399 {
2400 GST_ERROR_OBJECT (pool, "Failed to create V4L2 allocator");
2401 gst_object_unref (pool);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002402 return NULL;
bo.xiao857b8682024-09-12 16:40:32 +08002403 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002404}
2405
2406static GstFlowReturn
bo.xiao857b8682024-09-12 16:40:32 +08002407gst_aml_v4l2_do_read (GstAmlV4l2BufferPool * pool, GstBuffer * buf)
xuesong.jiangae1548e2022-05-06 16:38:46 +08002408{
bo.xiao857b8682024-09-12 16:40:32 +08002409 GstFlowReturn res;
2410 GstAmlV4l2Object *obj = pool->obj;
2411 gint amount;
2412 GstMapInfo map;
2413 gint toread;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002414
bo.xiao857b8682024-09-12 16:40:32 +08002415 toread = obj->info.size;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002416
bo.xiao857b8682024-09-12 16:40:32 +08002417 GST_LOG_OBJECT (pool, "reading %d bytes into buffer %p", toread, buf);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002418
bo.xiao857b8682024-09-12 16:40:32 +08002419 gst_buffer_map (buf, &map, GST_MAP_WRITE);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002420
bo.xiao857b8682024-09-12 16:40:32 +08002421 do
2422 {
2423 if ((res = gst_aml_v4l2_buffer_pool_poll (pool, TRUE)) != GST_FLOW_OK)
2424 goto poll_error;
2425
2426 amount = obj->read (obj->video_fd, map.data, toread);
2427
2428 if (amount == toread)
xuesong.jiangae1548e2022-05-06 16:38:46 +08002429 {
bo.xiao857b8682024-09-12 16:40:32 +08002430 break;
2431 }
2432 else if (amount == -1)
2433 {
2434 if (errno == EAGAIN || errno == EINTR)
2435 {
2436 continue;
2437 }
2438 else
2439 goto read_error;
2440 }
2441 else
2442 {
2443 /* short reads can happen if a signal interrupts the read */
2444 continue;
2445 }
2446 } while (TRUE);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002447
bo.xiao857b8682024-09-12 16:40:32 +08002448 GST_LOG_OBJECT (pool, "read %d bytes", amount);
2449 gst_buffer_unmap (buf, &map);
2450 gst_buffer_resize (buf, 0, amount);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002451
bo.xiao857b8682024-09-12 16:40:32 +08002452 return GST_FLOW_OK;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002453
bo.xiao857b8682024-09-12 16:40:32 +08002454 /* ERRORS */
xuesong.jiangae1548e2022-05-06 16:38:46 +08002455poll_error:
bo.xiao857b8682024-09-12 16:40:32 +08002456 {
2457 GST_DEBUG ("poll error %s", gst_flow_get_name (res));
xuesong.jiangae1548e2022-05-06 16:38:46 +08002458 goto cleanup;
bo.xiao857b8682024-09-12 16:40:32 +08002459 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002460read_error:
bo.xiao857b8682024-09-12 16:40:32 +08002461 {
2462 GST_ELEMENT_ERROR (obj->element, RESOURCE, READ,
2463 (_("Error reading %d bytes from device '%s'."),
2464 toread, obj->videodev), GST_ERROR_SYSTEM);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002465 res = GST_FLOW_ERROR;
2466 goto cleanup;
bo.xiao857b8682024-09-12 16:40:32 +08002467 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002468cleanup:
bo.xiao857b8682024-09-12 16:40:32 +08002469 {
2470 gst_buffer_unmap (buf, &map);
2471 gst_buffer_resize (buf, 0, 0);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002472 return res;
bo.xiao857b8682024-09-12 16:40:32 +08002473 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002474}
2475
2476/**
2477 * gst_aml_v4l2_buffer_pool_process:
2478 * @bpool: a #GstBufferPool
2479 * @buf: a #GstBuffer, maybe be replaced
2480 *
2481 * Process @buf in @bpool. For capture devices, this functions fills @buf with
2482 * data from the device. For output devices, this functions send the contents of
2483 * @buf to the device for playback.
2484 *
2485 * Returns: %GST_FLOW_OK on success.
2486 */
2487GstFlowReturn
2488gst_aml_v4l2_buffer_pool_process(GstAmlV4l2BufferPool *pool, GstBuffer **buf)
2489{
bo.xiao857b8682024-09-12 16:40:32 +08002490 GstFlowReturn ret = GST_FLOW_OK;
2491 GstBufferPool *bpool = GST_BUFFER_POOL_CAST (pool);
2492 GstAmlV4l2Object *obj = pool->obj;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002493
bo.xiao857b8682024-09-12 16:40:32 +08002494 GST_DEBUG_OBJECT(pool, "process buffer %p, buf_pool:%p, v4l2 output pool:%p", *buf, (*buf)->pool, bpool);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002495
bo.xiao857b8682024-09-12 16:40:32 +08002496 if (GST_BUFFER_POOL_IS_FLUSHING (pool))
2497 return GST_FLOW_FLUSHING;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002498
bo.xiao857b8682024-09-12 16:40:32 +08002499 switch (obj->type)
2500 {
xuesong.jiangae1548e2022-05-06 16:38:46 +08002501 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2502 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
bo.xiao857b8682024-09-12 16:40:32 +08002503 /* capture */
2504 switch (obj->mode)
2505 {
xuesong.jiangae1548e2022-05-06 16:38:46 +08002506 case GST_V4L2_IO_RW:
bo.xiao857b8682024-09-12 16:40:32 +08002507 /* capture into the buffer */
2508 ret = gst_aml_v4l2_do_read (pool, *buf);
2509 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002510
2511 case GST_V4L2_IO_MMAP:
2512 case GST_V4L2_IO_DMABUF:
2513 {
bo.xiao857b8682024-09-12 16:40:32 +08002514 GstBuffer *tmp;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002515
bo.xiao857b8682024-09-12 16:40:32 +08002516 if ((*buf)->pool == bpool)
2517 {
2518 guint num_queued;
2519 gsize size = gst_buffer_get_size (*buf);
2520
2521 /* Legacy M2M devices return empty buffer when drained */
2522 if (size == 0 && GST_AML_V4L2_IS_M2M(obj->device_caps))
2523 goto eos;
2524
2525 if (GST_VIDEO_INFO_FORMAT (&pool->caps_info) !=
2526 GST_VIDEO_FORMAT_ENCODED && size < pool->size)
2527 goto buffer_truncated;
2528
2529 num_queued = g_atomic_int_get (&pool->num_queued);
2530 GST_TRACE_OBJECT (pool, "Only %i buffer left in the capture queue.",
2531 num_queued);
2532
2533 /* If we have no more buffer, and can allocate it time to do so */
2534 if (num_queued == 0)
xuesong.jiangae1548e2022-05-06 16:38:46 +08002535 {
bo.xiao857b8682024-09-12 16:40:32 +08002536 if (GST_AML_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP))
2537 {
2538 ret = gst_aml_v4l2_buffer_pool_resurrect_buffer (pool);
2539 if (ret == GST_FLOW_OK)
2540 goto done;
2541 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002542 }
2543
bo.xiao857b8682024-09-12 16:40:32 +08002544 /* start copying buffers when we are running low on buffers */
2545 if (num_queued < pool->copy_threshold)
xuesong.jiangae1548e2022-05-06 16:38:46 +08002546 {
bo.xiao857b8682024-09-12 16:40:32 +08002547 GstBuffer *copy;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002548
bo.xiao857b8682024-09-12 16:40:32 +08002549 if (GST_AML_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP))
2550 {
2551 ret = gst_aml_v4l2_buffer_pool_resurrect_buffer (pool);
2552 if (ret == GST_FLOW_OK)
2553 goto done;
2554 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002555
bo.xiao857b8682024-09-12 16:40:32 +08002556 /* copy the buffer */
2557 copy = gst_buffer_copy_region (*buf,
2558 GST_BUFFER_COPY_ALL | GST_BUFFER_COPY_DEEP, 0, -1);
2559 GST_LOG_OBJECT (pool, "copy buffer %p->%p", *buf, copy);
2560
2561 /* and requeue so that we can continue capturing */
2562 gst_buffer_unref (*buf);
2563 *buf = copy;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002564 }
2565
bo.xiao857b8682024-09-12 16:40:32 +08002566 ret = GST_FLOW_OK;
2567 /* nothing, data was inside the buffer when we did _acquire() */
2568 goto done;
2569 }
hanghang.luo185a3372023-06-06 02:35:33 +00002570
bo.xiao857b8682024-09-12 16:40:32 +08002571 /* buffer not from our pool, grab a frame and copy it into the target */
2572 if ((ret = gst_aml_v4l2_buffer_pool_dequeue (pool, &tmp, TRUE))
2573 != GST_FLOW_OK)
2574 goto done;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002575
bo.xiao857b8682024-09-12 16:40:32 +08002576 if (obj->dumpframefile)
2577 {
2578 FILE *pFile = fopen(obj->dumpframefile, "ab");
2579 if (pFile)
2580 {
2581 int n = gst_buffer_n_memory(tmp);
2582 int i;
2583 GstMapInfo map_info;
2584 GstMemory *mem;
2585
2586 for (i = 0; i < n; ++i)
2587 {
2588 mem = gst_buffer_peek_memory(tmp, i);
2589 if (gst_memory_map(mem, &map_info, GST_MAP_READ))
2590 {
2591 fwrite(map_info.data, map_info.size, 1, pFile);
2592 gst_memory_unmap(mem, &map_info);
2593 }
2594 }
2595 fclose(pFile);
2596 }
2597 }
2598 /* An empty buffer on capture indicates the end of stream */
2599 if (gst_buffer_get_size(tmp) == 0)
2600 {
xuesong.jiangae1548e2022-05-06 16:38:46 +08002601 gst_aml_v4l2_buffer_pool_release_buffer(bpool, tmp);
2602
bo.xiao857b8682024-09-12 16:40:32 +08002603 /* Legacy M2M devices return empty buffer when drained */
2604 if (GST_AML_V4L2_IS_M2M(obj->device_caps))
2605 goto eos;
2606 }
2607
2608 ret = gst_aml_v4l2_buffer_pool_copy_buffer(pool, *buf, tmp);
2609 if (obj->mode == GST_V4L2_IO_DMABUF && (GST_VIDEO_FORMAT_NV12 == pool->caps_info.finfo->format || GST_VIDEO_FORMAT_NV21 == pool->caps_info.finfo->format) && gst_buffer_get_size (*buf) > (pool->caps_info.width * pool->caps_info.height * 3 / 2))
2610 {
2611 GST_DEBUG_OBJECT (pool, "resizebuf. format:%d [%d, %d] W:%d, H:%d", pool->caps_info.finfo->format, GST_VIDEO_FORMAT_NV12, GST_VIDEO_FORMAT_NV21, pool->caps_info.width, pool->caps_info.height);
2612 gst_buffer_resize (*buf, 0, pool->caps_info.width * pool->caps_info.height * 3 / 2);
2613 }
2614
2615
2616 /* an queue the buffer again after the copy */
2617 gst_aml_v4l2_buffer_pool_release_buffer(bpool, tmp);
2618
2619 if (ret != GST_FLOW_OK)
2620 goto copy_failed;
2621 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002622 }
2623
2624 case GST_V4L2_IO_USERPTR:
2625 {
bo.xiao857b8682024-09-12 16:40:32 +08002626 struct UserPtrData *data;
2627 GstBuffer *tmp;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002628
bo.xiao857b8682024-09-12 16:40:32 +08002629 /* Replace our buffer with downstream allocated buffer */
2630 data = gst_mini_object_steal_qdata (GST_MINI_OBJECT (*buf),
2631 GST_AML_V4L2_IMPORT_QUARK);
2632 tmp = gst_buffer_ref (data->buffer);
2633 _unmap_userptr_frame (data);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002634
bo.xiao857b8682024-09-12 16:40:32 +08002635 /* Now tmp is writable, copy the flags and timestamp */
2636 gst_buffer_copy_into (tmp, *buf,
2637 GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002638
bo.xiao857b8682024-09-12 16:40:32 +08002639 gst_buffer_replace (buf, tmp);
2640 gst_buffer_unref (tmp);
2641 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002642 }
2643
2644 case GST_V4L2_IO_DMABUF_IMPORT:
2645 {
bo.xiao857b8682024-09-12 16:40:32 +08002646 GstBuffer *tmp;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002647
bo.xiao857b8682024-09-12 16:40:32 +08002648 /* Replace our buffer with downstream allocated buffer */
2649 // tmp = gst_mini_object_steal_qdata(GST_MINI_OBJECT(*buf),
2650 // GST_AML_V4L2_IMPORT_QUARK);
2651 tmp = gst_mini_object_get_qdata(GST_MINI_OBJECT(*buf), GST_AML_V4L2_IMPORT_QUARK);
2652 GST_DEBUG("got v4l2 capture buf:%p, with qdata drm buf:%p", *buf, tmp);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002653
bo.xiao857b8682024-09-12 16:40:32 +08002654 gst_buffer_copy_into (tmp, *buf,
2655 GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002656
bo.xiao857b8682024-09-12 16:40:32 +08002657 gst_buffer_replace (buf, tmp);
2658 gst_buffer_unref (tmp);
2659 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002660 }
2661
2662 default:
bo.xiao857b8682024-09-12 16:40:32 +08002663 g_assert_not_reached ();
2664 break;
2665 }
2666 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002667
2668 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
2669 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
bo.xiao857b8682024-09-12 16:40:32 +08002670 /* playback */
2671 switch (obj->mode)
2672 {
xuesong.jiangae1548e2022-05-06 16:38:46 +08002673 case GST_V4L2_IO_RW:
bo.xiao857b8682024-09-12 16:40:32 +08002674 /* FIXME, do write() */
2675 GST_WARNING_OBJECT (pool, "implement write()");
2676 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002677
2678 case GST_V4L2_IO_USERPTR:
2679 case GST_V4L2_IO_DMABUF_IMPORT:
2680 case GST_V4L2_IO_DMABUF:
2681 case GST_V4L2_IO_MMAP:
2682 {
bo.xiao857b8682024-09-12 16:40:32 +08002683 GstBuffer *to_queue = NULL;
2684 GstBuffer *buffer;
2685 GstAmlV4l2MemoryGroup *group;
2686 gint index;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002687
bo.xiao857b8682024-09-12 16:40:32 +08002688 if ((*buf)->pool != bpool)
2689 goto copying;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002690
bo.xiao857b8682024-09-12 16:40:32 +08002691 if (!gst_aml_v4l2_is_buffer_valid (*buf, &group))
2692 goto copying;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002693
bo.xiao857b8682024-09-12 16:40:32 +08002694 index = group->buffer.index;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002695
bo.xiao857b8682024-09-12 16:40:32 +08002696 GST_LOG_OBJECT (pool, "processing buffer %i from our pool", index);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002697
bo.xiao857b8682024-09-12 16:40:32 +08002698 if (pool->buffers[index] != NULL)
2699 {
2700 GST_LOG_OBJECT (pool, "buffer %i already queued, copying", index);
2701 goto copying;
2702 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002703
bo.xiao857b8682024-09-12 16:40:32 +08002704 /* we can queue directly */
2705 to_queue = gst_buffer_ref (*buf);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002706
2707 copying:
bo.xiao857b8682024-09-12 16:40:32 +08002708 if (to_queue == NULL)
2709 {
2710 GstBufferPoolAcquireParams params = { 0 };
2711
2712 GST_LOG_OBJECT (pool, "alloc buffer from our pool");
2713
2714 /* this can return EOS if all buffers are outstanding which would
2715 * be strange because we would expect the upstream element to have
2716 * allocated them and returned to us.. */
2717 params.flags = GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT;
2718 ret = gst_buffer_pool_acquire_buffer (bpool, &to_queue, &params);
2719 if (ret != GST_FLOW_OK)
2720 goto acquire_failed;
2721
2722 ret = gst_aml_v4l2_buffer_pool_prepare_buffer (pool, to_queue, *buf);
2723 if (ret != GST_FLOW_OK)
xuesong.jiangae1548e2022-05-06 16:38:46 +08002724 {
bo.xiao857b8682024-09-12 16:40:32 +08002725 gst_buffer_unref (to_queue);
2726 goto prepare_failed;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002727 }
2728
bo.xiao857b8682024-09-12 16:40:32 +08002729 /* retrieve the group */
2730 gst_aml_v4l2_is_buffer_valid (to_queue, &group);
2731 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002732
bo.xiao857b8682024-09-12 16:40:32 +08002733 if ((ret = gst_aml_v4l2_buffer_pool_qbuf(pool, to_queue, group)) != GST_FLOW_OK)
2734 goto queue_failed;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002735
bo.xiao857b8682024-09-12 16:40:32 +08002736 /* if we are not streaming yet (this is the first buffer, start
2737 * streaming now */
2738 if (!gst_aml_v4l2_buffer_pool_streamon (pool))
2739 {
2740 /* don't check return value because qbuf would have failed */
2741 gst_aml_v4l2_is_buffer_valid (to_queue, &group);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002742
bo.xiao857b8682024-09-12 16:40:32 +08002743 /* qbuf has stored to_queue buffer but we are not in
2744 * streaming state, so the flush logic won't be performed.
2745 * To avoid leaks, flush the allocator and restore the queued
2746 * buffer as non-queued */
2747 gst_aml_v4l2_allocator_flush (pool->vallocator);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002748
bo.xiao857b8682024-09-12 16:40:32 +08002749 pool->buffers[group->buffer.index] = NULL;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002750
bo.xiao857b8682024-09-12 16:40:32 +08002751 gst_mini_object_set_qdata (GST_MINI_OBJECT (to_queue),
2752 GST_AML_V4L2_IMPORT_QUARK, NULL, NULL);
2753 gst_buffer_unref (to_queue);
2754 g_atomic_int_add (&pool->num_queued, -1);
2755 goto start_failed;
2756 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002757
bo.xiao857b8682024-09-12 16:40:32 +08002758 /* Remove our ref, we will still hold this buffer in acquire as needed,
2759 * otherwise the pool will think it is outstanding and will refuse to stop. */
2760 gst_buffer_unref (to_queue);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002761
bo.xiao857b8682024-09-12 16:40:32 +08002762 /* release as many buffer as possible */
2763 while (gst_aml_v4l2_buffer_pool_dequeue (pool, &buffer, FALSE) ==
2764 GST_FLOW_OK)
2765 {
2766 if (buffer->pool == NULL)
2767 gst_aml_v4l2_buffer_pool_release_buffer(bpool, buffer);
2768 }
2769
2770 if (g_atomic_int_get (&pool->num_queued) >= pool->min_latency)
2771 {
2772 /* all buffers are queued, try to dequeue one and release it back
2773 * into the pool so that _acquire can get to it again. */
2774 ret = gst_aml_v4l2_buffer_pool_dequeue (pool, &buffer, TRUE);
2775 if (ret == GST_FLOW_OK && buffer->pool == NULL)
2776 /* release the rendered buffer back into the pool. This wakes up any
2777 * thread waiting for a buffer in _acquire(). */
2778 gst_aml_v4l2_buffer_pool_release_buffer(bpool, buffer);
2779 }
2780 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002781 }
2782 default:
bo.xiao857b8682024-09-12 16:40:32 +08002783 g_assert_not_reached ();
2784 break;
2785 }
2786 break;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002787 default:
bo.xiao857b8682024-09-12 16:40:32 +08002788 g_assert_not_reached ();
2789 break;
2790 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002791done:
bo.xiao857b8682024-09-12 16:40:32 +08002792 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002793
bo.xiao857b8682024-09-12 16:40:32 +08002794 /* ERRORS */
xuesong.jiangae1548e2022-05-06 16:38:46 +08002795copy_failed:
bo.xiao857b8682024-09-12 16:40:32 +08002796 {
2797 GST_ERROR_OBJECT (pool, "failed to copy buffer");
xuesong.jiangae1548e2022-05-06 16:38:46 +08002798 return ret;
bo.xiao857b8682024-09-12 16:40:32 +08002799 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002800buffer_truncated:
bo.xiao857b8682024-09-12 16:40:32 +08002801 {
2802 GST_WARNING_OBJECT (pool,
2803 "Dropping truncated buffer, this is likely a driver bug.");
2804 gst_buffer_unref (*buf);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002805 *buf = NULL;
2806 return GST_AML_V4L2_FLOW_CORRUPTED_BUFFER;
bo.xiao857b8682024-09-12 16:40:32 +08002807 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002808eos:
bo.xiao857b8682024-09-12 16:40:32 +08002809 {
2810 GST_DEBUG_OBJECT (pool, "end of stream reached");
2811 gst_buffer_unref (*buf);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002812 *buf = NULL;
2813 return GST_AML_V4L2_FLOW_LAST_BUFFER;
bo.xiao857b8682024-09-12 16:40:32 +08002814 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002815acquire_failed:
bo.xiao857b8682024-09-12 16:40:32 +08002816 {
xuesong.jiangae1548e2022-05-06 16:38:46 +08002817 if (ret == GST_FLOW_FLUSHING)
bo.xiao857b8682024-09-12 16:40:32 +08002818 GST_DEBUG_OBJECT (pool, "flushing");
xuesong.jiangae1548e2022-05-06 16:38:46 +08002819 else
bo.xiao857b8682024-09-12 16:40:32 +08002820 GST_WARNING_OBJECT (pool, "failed to acquire a buffer: %s",
2821 gst_flow_get_name (ret));
xuesong.jiangae1548e2022-05-06 16:38:46 +08002822 return ret;
bo.xiao857b8682024-09-12 16:40:32 +08002823 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002824prepare_failed:
bo.xiao857b8682024-09-12 16:40:32 +08002825 {
2826 GST_ERROR_OBJECT (pool, "failed to prepare data");
xuesong.jiangae1548e2022-05-06 16:38:46 +08002827 return ret;
bo.xiao857b8682024-09-12 16:40:32 +08002828 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002829queue_failed:
bo.xiao857b8682024-09-12 16:40:32 +08002830 {
2831 GST_ERROR_OBJECT (pool, "failed to queue buffer");
xuesong.jiangae1548e2022-05-06 16:38:46 +08002832 return ret;
bo.xiao857b8682024-09-12 16:40:32 +08002833 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002834start_failed:
bo.xiao857b8682024-09-12 16:40:32 +08002835 {
2836 GST_ERROR_OBJECT (pool, "failed to start streaming");
xuesong.jiangae1548e2022-05-06 16:38:46 +08002837 return GST_FLOW_ERROR;
bo.xiao857b8682024-09-12 16:40:32 +08002838 }
xuesong.jiangae1548e2022-05-06 16:38:46 +08002839}
2840
bo.xiao857b8682024-09-12 16:40:32 +08002841void
2842gst_aml_v4l2_buffer_pool_set_other_pool (GstAmlV4l2BufferPool * pool,
2843 GstBufferPool * other_pool)
xuesong.jiangae1548e2022-05-06 16:38:46 +08002844{
bo.xiao857b8682024-09-12 16:40:32 +08002845 g_return_if_fail (!gst_buffer_pool_is_active (GST_BUFFER_POOL (pool)));
xuesong.jiangae1548e2022-05-06 16:38:46 +08002846
bo.xiao857b8682024-09-12 16:40:32 +08002847 if (pool->other_pool)
2848 gst_object_unref (pool->other_pool);
2849 pool->other_pool = gst_object_ref (other_pool);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002850}
2851
bo.xiao857b8682024-09-12 16:40:32 +08002852void
2853gst_aml_v4l2_buffer_pool_copy_at_threshold (GstAmlV4l2BufferPool * pool, gboolean copy)
xuesong.jiangae1548e2022-05-06 16:38:46 +08002854{
bo.xiao857b8682024-09-12 16:40:32 +08002855 GST_OBJECT_LOCK (pool);
2856 pool->enable_copy_threshold = copy;
2857 GST_OBJECT_UNLOCK (pool);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002858}
2859
2860gboolean
2861gst_aml_v4l2_buffer_pool_flush(GstBufferPool *bpool)
2862{
bo.xiao857b8682024-09-12 16:40:32 +08002863 GstAmlV4l2BufferPool *pool = GST_AML_V4L2_BUFFER_POOL(bpool);
2864 gboolean ret = TRUE;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002865
bo.xiao857b8682024-09-12 16:40:32 +08002866 gst_aml_v4l2_buffer_pool_streamoff (pool);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002867
bo.xiao857b8682024-09-12 16:40:32 +08002868 if (!V4L2_TYPE_IS_OUTPUT (pool->obj->type))
2869 ret = gst_aml_v4l2_buffer_pool_streamon (pool);
xuesong.jiangae1548e2022-05-06 16:38:46 +08002870
bo.xiao857b8682024-09-12 16:40:32 +08002871 return ret;
xuesong.jiangae1548e2022-05-06 16:38:46 +08002872}
2873
2874void gst_aml_v4l2_buffer_pool_dump_stat(GstAmlV4l2BufferPool *pool, const gchar *file_name, gint try_num)
2875{
2876 const gchar *dump_dir = NULL;
2877 gchar *full_file_name = NULL;
2878 FILE *out = NULL;
2879
2880 dump_dir = g_getenv("GST_DEBUG_DUMP_AMLV4L2DEC_STAT_DIR");
2881 if (G_LIKELY(dump_dir == NULL))
2882 return;
2883
2884 if (!file_name)
2885 {
2886 file_name = "unnamed";
2887 }
2888
2889 full_file_name = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s.stat", dump_dir, file_name);
2890
2891 if ((out = fopen(full_file_name, "w")))
2892 {
2893 GstStructure *config = NULL;
2894 config = gst_buffer_pool_get_config((GstBufferPool *)pool);
2895 if (config)
2896 {
2897 GstCaps *caps;
2898 guint size, min_buffers, max_buffers;
2899 if (gst_buffer_pool_config_get_params(config, &caps, &size, &min_buffers, &max_buffers))
2900 {
2901 gchar *stat_info;
2902
2903 /* set local pool info*/
2904 gint already_queued = 0;
2905 gint ready_to_queue_num = 0;
2906 for (gint i = 0; i < VIDEO_MAX_FRAME; i++)
2907 {
2908 if (pool->buffers[i])
2909 {
2910 already_queued++;
2911 }
2912 if (pool->read_to_free_bufs[i])
2913 {
2914 ready_to_queue_num++;
2915 }
2916 }
2917
2918 stat_info = g_strdup_printf("local pool | size:%d, min_bufs:%d, max_bufs:%d | queued:%d, allocated:%d | already_queued:%d, ready_to_queue:%d | try_num:%d\n",
2919 size, min_buffers, max_buffers,
2920 pool->num_queued, pool->num_allocated,
2921 already_queued, ready_to_queue_num, try_num);
2922 fputs(stat_info, out);
2923 g_free(stat_info);
2924
2925 /* set other pool info*/
2926 if (pool->other_pool)
2927 {
2928 GstStructure *other_config = NULL;
2929 other_config = gst_buffer_pool_get_config((GstBufferPool *)pool);
2930 if (other_config)
2931 {
2932 GstCaps *other_caps;
2933 guint other_size, other_min_buffers, other_max_buffers;
2934 if (gst_buffer_pool_config_get_params(config, &other_caps, &other_size, &other_min_buffers, &other_max_buffers))
2935 {
2936 stat_info = g_strdup_printf("other pool | size:%d, min_bufs:%d, max_bufs:%d\n",
2937 other_size, other_min_buffers, other_max_buffers);
2938
2939 // TODO:GstBufferPool中没有获取outstanding的接口,所以这里没有统计otherpool中在用buffer的状态,后续需要修改gstreamer-1.0中code新增接口
2940 fputs(stat_info, out);
2941 g_free(stat_info);
2942 }
2943 }
2944 }
2945 GST_INFO("wrote amlv4l2 bufferpool stat to : '%s' succ", full_file_name);
2946 }
2947 }
2948 else
2949 {
2950 GST_WARNING("Failed to get config for pool:%p", pool);
2951 }
2952 fclose(out);
2953 }
2954 else
2955 {
2956 GST_WARNING("Failed to open file '%s' for writing: %s", full_file_name, g_strerror(errno));
2957 }
2958 g_free(full_file_name);
2959}