amlv4l2dec: add a new interface for getting and sending cc data [1/1]
PD#SH-19658
Problem:
add a new interface for getting and sending cc data
Solution:
add the process for getting and sending cc data
Verify:
yocto-4.0-smarthome
Signed-off-by: zengliang.li <zengliang.li@amlogic.com>
Change-Id: If7a0d23e872a95b99df995e276a0204672577066
diff --git a/src/aml_v4l2_calls.c b/src/aml_v4l2_calls.c
index c0b7cb2..7f0411b 100644
--- a/src/aml_v4l2_calls.c
+++ b/src/aml_v4l2_calls.c
@@ -185,6 +185,11 @@
if (v4l2object->ioctl(v4l2object->video_fd, VIDIOC_SUBSCRIBE_EVENT, &sub) < 0)
goto failed;
+ sub.type = V4L2_EVENT_PRIVATE_EXT_REPORT_DECINFO;
+ sub.id = AML_DECINFO_EVENT_CC;
+ if (v4l2object->ioctl(v4l2object->video_fd, VIDIOC_SUBSCRIBE_EVENT, &sub) < 0)
+ goto failed;
+
v4l2object->can_wait_event = TRUE;
return TRUE;
@@ -193,7 +198,7 @@
failed:
{
GST_WARNING_OBJECT(e, "Cannot subscribe V4L2_EVENT_SOURCE_CHANGE or "
- "V4L2_EVENT_EOS event for device '%s'.",
+ "V4L2_EVENT_EOS or V4L2_EVENT_PRIVATE_EXT_REPORT_DECINFO event for device '%s'.",
v4l2object->videodev);
return TRUE;
}
diff --git a/src/ext/videodev2.h b/src/ext/videodev2.h
index 9530213..15dfdfc 100644
--- a/src/ext/videodev2.h
+++ b/src/ext/videodev2.h
@@ -172,6 +172,20 @@
V4L2_TUNER_RF = 5,
};
+enum E_DECINFO_EVENT {
+ AML_DECINFO_EVENT_STREAM = 0,
+ AML_DECINFO_EVENT_STATISTIC,
+ AML_DECINFO_EVENT_AFD,
+ AML_DECINFO_EVENT_CC,
+ AML_DECINFO_EVENT_HDR10,
+ AML_DECINFO_EVENT_HDR10P,
+ AML_DECINFO_EVENT_CUVA,
+ AML_DECINFO_EVENT_DV,
+ AML_DECINFO_EVENT_FRAME,
+ AML_DECINFO_EVENT_COMPOSITE = 30,
+ AML_DECINFO_EVENT_BOTTOM = 31,
+};
+
/* Deprecated, do not use */
#define V4L2_TUNER_ADC V4L2_TUNER_SDR
@@ -2308,6 +2322,9 @@
#define V4L2_EVENT_SOURCE_CHANGE 5
#define V4L2_EVENT_MOTION_DET 6
#define V4L2_EVENT_PRIVATE_START 0x08000000
+#define V4L2_EVENT_PRIVATE_EXT_VSC_BASE (V4L2_EVENT_PRIVATE_START + 0x2000)
+#define V4L2_EVENT_PRIVATE_EXT_REPORT_DECINFO (V4L2_EVENT_PRIVATE_EXT_VSC_BASE + 4)
+
/* Payload for V4L2_EVENT_VSYNC */
struct v4l2_event_vsync
diff --git a/src/gstamlv4l2bufferpool.c b/src/gstamlv4l2bufferpool.c
index 3b95429..a4f0716 100644
--- a/src/gstamlv4l2bufferpool.c
+++ b/src/gstamlv4l2bufferpool.c
@@ -68,6 +68,178 @@
static gboolean gst_aml_v4l2_buffer_pool_release_buffer_aml_patch(GstBufferPool *bpool);
#endif
+#define MAX_CC_LEN 72
+#ifndef V4L2_CID_USER_AMLOGIC_BASE
+#define V4L2_CID_USER_AMLOGIC_BASE (V4L2_CID_USER_BASE + 0x1100)
+#define AML_V4L2_GET_DECINFO_SET (V4L2_CID_USER_AMLOGIC_BASE + 13)
+#endif
+
+enum E_DECINFO_CMD_GET {
+AML_DECINFO_GET_STREAM_TYPE = 0,
+AML_DECINFO_GET_STATISTIC_TYPE,
+AML_DECINFO_GET_AFD_TYPE,
+AML_DECINFO_GET_CC_TYPE,
+AML_DECINFO_GET_HDR10_TYPE,
+AML_DECINFO_GET_HDR10P_TYPE,
+AML_DECINFO_GET_CUVA_TYPE,
+AML_DECINFO_GET_DV_TYPE,
+AML_DECINFO_GET_FRAME_TYPE,
+AML_DECINFO_GET_COMPOSITE_TYPE = 30,
+AML_DECINFO_GET_CMD_BOTTOM = 31,
+};
+
+struct v4l_userdata_meta_data_t {
+__u32 poc_number;
+__u16 flags;
+__u16 video_format;
+__u16 extension_data;
+__u16 frame_type;
+__u32 vpts;
+__u32 vpts_valid;
+__u64 timestamp;
+__u32 records_in_que;
+unsigned long long priv_data;
+__u32 padding_data[64];
+};
+
+struct sei_usd_param_s {
+__u32 info_type; /* CC or AFD or aux data*/
+__u32 data_size; /* size of the data domain */
+__u64 data; /* pointer to data domain */
+__u64 v_addr; /* used for kernelspace data */
+struct v4l_userdata_meta_data_t meta_data; /* meta_data */
+};
+
+enum E_ASPECT_RATIO {
+ASPECT_RATIO_4_3,
+ASPECT_RATIO_16_9,
+ASPECT_UNDEFINED = 255
+};
+
+struct aspect_ratio_size {
+__s32 sar_width;
+__s32 sar_height;
+__s32 dar_width;
+__s32 dar_height;
+};
+
+struct dec_stream_info_s {
+__u32 info_type;
+char vdec_name[32];
+__u32 vdec_type;
+__u32 dual_core_flag;
+__u32 is_secure;
+__u32 profile_idc;
+__u32 level_idc;
+__u32 filed_flag;
+__u32 frame_width;
+__u32 frame_height;
+__u32 crop_top;
+__u32 crop_bottom;
+__u32 crop_left;
+__u32 crop_right;
+__u32 frame_rate;
+__u32 fence_enable;
+__u32 fast_output_enable;
+__u32 trick_mode;
+__u32 bit_depth;
+__u32 double_write_mode;
+__u32 error_handle_policy;
+enum E_ASPECT_RATIO eu_aspect_ratio;
+struct aspect_ratio_size ratio_size;
+char reserved[64];
+};
+
+struct dec_statistics_info_s {
+__u32 info_ype;
+__u32 total_decoded_frames;
+__u32 error_frames;
+__u32 drop_frames;
+__u32 i_decoded_frames;
+__u32 i_drop_frames;
+__u32 i_error_frames;
+__u32 p_decoded_frames;
+__u32 p_drop_frames;
+__u32 p_error_frames;
+__u32 b_decoded_frames;
+__u32 b_drop_frames;
+__u32 b_error_frames;
+__u32 av_resynch_counter;
+__u64 total_decoded_datasize;
+char reserved[64];
+};
+
+struct vframe_qos_s {
+__u32 num;
+__u32 type;
+__u32 size;
+__u32 pts;
+int max_qp;
+int avg_qp;
+int min_qp;
+int max_skip;
+int avg_skip;
+int min_skip;
+int max_mv;
+int min_mv;
+int avg_mv;
+int decode_buffer;
+} /*vframe_qos */;
+
+struct dec_frame_info_s {
+__u32 info_type;
+struct vframe_qos_s qos; /* qos */
+__u32 num;
+__u32 type;
+__s32 frame_poc;
+__u32 decode_time_cost;
+__u32 pic_width;
+__u32 pic_height;
+__u32 error_flag;
+__u32 status;
+__u32 bitrate;
+__u32 field_output_order;
+__u32 offset;
+__u32 ratio_control;
+__u32 vf_type;
+__u32 signal_type;
+__u32 ext_signal_type;
+__u32 pts;
+__u64 pts_us64;
+__u64 timestamp;
+__u32 frame_size;
+char reserved[64];
+};
+
+struct aux_data_static_t {
+__u32 info_type; /* HDR10 HLG FMM or IMAX */
+struct aml_vdec_hdr_infos hdr_info;
+};
+
+struct v4l_dec_data_extension {
+ulong ptr; /* for future extension */
+__u32 data_size;
+};
+
+/**
+* struct vdec_common_s - Structure used to receive infos from decoder
+*/
+struct vdec_common_s {
+ __u32 version_magic;
+ __u32 vdec_id;
+ __u32 type;
+ union {
+ struct dec_stream_info_s stream_info;
+ struct dec_frame_info_s frame_info;
+ struct dec_statistics_info_s decoder_statistics;
+ struct sei_usd_param_s usd_param;
+ struct aux_data_static_t aux_data;
+ struct v4l_dec_data_extension data_ext;
+ char raw_data[512];
+ } u;
+ __u32 size;
+};
+
static gboolean
gst_aml_v4l2_is_buffer_valid(GstBuffer *buffer, GstAmlV4l2MemoryGroup **out_group)
{
@@ -1384,6 +1556,61 @@
case V4L2_EVENT_EOS:
return GST_AML_V4L2_FLOW_LAST_BUFFER;
break;
+ case V4L2_EVENT_PRIVATE_EXT_REPORT_DECINFO:
+ if (evt.id == AML_DECINFO_EVENT_CC)
+ {
+ struct v4l2_ext_control control;
+ struct v4l2_ext_controls ctrls;
+ struct vdec_common_s vdec_comm;
+ char cc_data[MAX_CC_LEN] = {0};
+
+ memset(&ctrls, 0, sizeof(ctrls));
+ memset(&control, 0, sizeof(control));
+ memset(&vdec_comm, 0, sizeof(vdec_comm));
+
+ vdec_comm.type = AML_DECINFO_GET_CC_TYPE;
+ vdec_comm.u.usd_param.data = (void *)cc_data;
+ vdec_comm.u.usd_param.data_size = MAX_CC_LEN;
+
+ control.ptr = &vdec_comm;
+ control.id = AML_V4L2_GET_DECINFO_SET;
+ control.size = sizeof(struct vdec_common_s);
+
+ ctrls.count = 1;
+ ctrls.controls = &control;
+
+ if (v4l2object->ioctl (pool->video_fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
+ {
+ GST_DEBUG("VIDIOC_S_EXT_CTRLS fail");
+ }
+ else
+ {
+ if (v4l2object->ioctl (pool->video_fd, VIDIOC_G_EXT_CTRLS, &ctrls) == 0)
+ {
+ GstBuffer *cc_buffer = gst_buffer_new ();
+ GstMemory *mem = gst_allocator_alloc (NULL, MAX_CC_LEN, NULL);
+ gst_buffer_insert_memory (cc_buffer, -1, mem);
+ gsize cc_size = gst_buffer_fill (cc_buffer, 0, vdec_comm.u.usd_param.data, vdec_comm.u.usd_param.data_size);
+ GST_DEBUG("copy cc data size:%d",cc_size);
+ cc_buffer->pts = vdec_comm.u.usd_param.meta_data.timestamp;
+ pool->cc_buffer_list = g_list_append (pool->cc_buffer_list,cc_buffer);
+ GST_DEBUG("cc_buffer_list size:%d",g_list_length(pool->cc_buffer_list));
+ #if 0
+ //dump decoder metadata
+ GST_DEBUG("cc pack pts:%lld",vdec_comm.u.usd_param.meta_data.timestamp);
+ int fd=open("/data/test/cc0.data",O_RDWR |O_CREAT|O_APPEND,0777);
+ write(fd,vdec_comm.u.usd_param.data,vdec_comm.u.usd_param.data_size);
+ close(fd);
+ #endif
+ }
+ else
+ {
+ GST_DEBUG("VIDIOC_G_EXT_CTRLS fail");
+ }
+ }
+ return GST_AML_V4L2_FLOW_CC_DATA;
+ }
+ break;
default:
break;
}
@@ -1987,6 +2214,12 @@
{
GstAmlV4l2BufferPool *pool = GST_AML_V4L2_BUFFER_POOL(object);
+ if (g_list_length (pool->cc_buffer_list) > 0)
+ {
+ g_list_free_full (pool->cc_buffer_list, (GDestroyNotify) gst_buffer_unref);
+ pool->cc_buffer_list = NULL;
+ }
+
if (pool->video_fd >= 0)
pool->obj->close(pool->video_fd);
@@ -2014,6 +2247,7 @@
pool->empty = TRUE;
GST_OBJECT_UNLOCK(pool);
pool->orphaned = FALSE;
+ pool->cc_buffer_list = NULL;
}
static void
diff --git a/src/gstamlv4l2bufferpool.h b/src/gstamlv4l2bufferpool.h
index f351944..8babf22 100644
--- a/src/gstamlv4l2bufferpool.h
+++ b/src/gstamlv4l2bufferpool.h
@@ -50,6 +50,8 @@
* occure for mem-2-mem devices. */
#define GST_AML_V4L2_FLOW_SOURCE_CHANGE GST_FLOW_CUSTOM_SUCCESS_2
+#define GST_AML_V4L2_FLOW_CC_DATA (GST_FLOW_CUSTOM_SUCCESS_2+1)
+
#define GST_AML_SPEC_FLOW_FOR_VBP 1
struct _GstAmlV4l2BufferPool
@@ -65,6 +67,8 @@
gboolean empty;
GCond empty_cond;
+ GList *cc_buffer_list;
+
gboolean orphaned;
GstAmlV4l2Allocator *vallocator;
diff --git a/src/gstamlv4l2object.c b/src/gstamlv4l2object.c
index b31af56..c1fad8b 100644
--- a/src/gstamlv4l2object.c
+++ b/src/gstamlv4l2object.c
@@ -413,11 +413,17 @@
"TRUE for stream mode, FALSE for frame mode",
FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
g_object_class_install_property(gobject_class, PROP_LOW_LATENCY_MODE,
g_param_spec_boolean("low-latency-mode", "set low latency mode",
"enable is TURE, disable is FALSE, default is disable",
FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_CC_DATA,
+ g_param_spec_boolean ("enable-cc-data",
+ "enable get cc data",
+ "0: disable; 1: enable", FALSE, G_PARAM_READWRITE));
}
/* Support for 32bit off_t, this wrapper is casting off_t to gint64 */
@@ -487,6 +493,7 @@
v4l2object->keep_aspect = TRUE;
v4l2object->stream_mode = FALSE;
v4l2object->have_set_par = FALSE;
+ v4l2object->enable_cc_data = FALSE;
v4l2object->n_v4l2_planes = 0;
@@ -692,6 +699,10 @@
v4l2object->low_latency_mode = g_value_get_boolean(value);
GST_DEBUG_OBJECT(v4l2object, "set low latency: %d",v4l2object->low_latency_mode);
break;
+ case PROP_CC_DATA:
+ v4l2object->enable_cc_data = g_value_get_boolean(value);
+ GST_DEBUG_OBJECT(v4l2object, "enable cc data: %d",v4l2object->enable_cc_data);
+ break;
default:
return FALSE;
break;
@@ -796,6 +807,9 @@
case PROP_STREAM_MODE:
g_value_set_boolean(value, v4l2object->stream_mode);
break;
+ case PROP_CC_DATA:
+ g_value_set_boolean(value, v4l2object->enable_cc_data);
+ break;
default:
return FALSE;
break;
diff --git a/src/gstamlv4l2object.h b/src/gstamlv4l2object.h
index 8fe08d7..82c5ba1 100644
--- a/src/gstamlv4l2object.h
+++ b/src/gstamlv4l2object.h
@@ -202,6 +202,7 @@
GValue *par;
gboolean have_set_par;
GValue *fps;
+ gboolean enable_cc_data;
/* funcs */
GstAmlV4l2GetInOutFunction get_in_out_func;
@@ -265,7 +266,8 @@
PROP_FORCE_ASPECT_RATIO, \
PROP_DUMP_FRAME_LOCATION, \
PROP_STREAM_MODE, \
- PROP_LOW_LATENCY_MODE
+ PROP_LOW_LATENCY_MODE, \
+ PROP_CC_DATA
/* create/destroy */
GstAmlV4l2Object *gst_aml_v4l2_object_new(GstElement *element,
diff --git a/src/gstamlv4l2videodec.c b/src/gstamlv4l2videodec.c
index 415b187..b528334 100644
--- a/src/gstamlv4l2videodec.c
+++ b/src/gstamlv4l2videodec.c
@@ -57,6 +57,8 @@
}
#endif
+#define GST_AML_V4L2_CC_IMPORT_QUARK gst_aml_v4l2_buffer_pool_cc_import_quark ()
+
#ifndef ABSDIFF
#define ABSDIFF(a,b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a)))
#endif
@@ -143,6 +145,13 @@
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
}
break;
+ case PROP_CC_DATA:
+ if (!gst_aml_v4l2_object_set_property_helper(self->v4l2capture,
+ prop_id, value, pspec))
+ {
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+ break;
#if GST_IMPORT_LGE_PROP
case LGE_RESOURCE_INFO:
{
@@ -210,7 +219,13 @@
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
}
break;
-
+ case PROP_CC_DATA:
+ if (!gst_aml_v4l2_object_get_property_helper(self->v4l2capture,
+ prop_id, value, pspec))
+ {
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+ break;
#if GST_IMPORT_LGE_PROP
case LGE_DECODE_SIZE:
{
@@ -949,6 +964,57 @@
}
}
+static GQuark
+gst_aml_v4l2_buffer_pool_cc_import_quark (void)
+{
+ static GQuark quark = 0;
+
+ if (quark == 0)
+ quark = g_quark_from_string ("GstAmlV4l2BufferPoolCcUsePtrData");
+
+ return quark;
+}
+
+static gboolean
+foreach_cc_buffer_list_match_pts_func(GList *list , GstVideoCodecFrame *frame)
+{
+ GList *l;
+ if (g_list_length (list) > 0)
+ {
+ for (l = list; l != NULL; l = l->next)
+ {
+ GstBuffer *cc_buffer = l->data;
+ if (GST_BUFFER_TIMESTAMP (frame->output_buffer) == GST_BUFFER_TIMESTAMP (cc_buffer))
+ {
+ gst_mini_object_set_qdata (GST_MINI_OBJECT (frame->output_buffer), GST_AML_V4L2_CC_IMPORT_QUARK,
+ gst_buffer_ref(cc_buffer), (GDestroyNotify) gst_buffer_unref);
+ #if 0
+ //Debug code:dump cc data
+ GstMapInfo gst_map;
+ gst_buffer_map(cc_buffer,&gst_map,GST_MAP_READ);
+ int fd=open("/data/test/cc1.data",O_RDWR |O_CREAT|O_APPEND,0777);
+ if (gst_map.size>0)
+ write(fd,gst_map.data,gst_map.size);
+ close(fd);
+ gst_buffer_unmap(cc_buffer,&gst_map);
+ #endif
+ GST_DEBUG("match success");
+ return TRUE;
+ }
+ else
+ {
+ GST_DEBUG("match fail");
+ }
+ }
+ GST_WARNING("no match frame in the bufferlist");
+ }
+ else
+ {
+ GST_WARNING("list is null,can not foreach");
+ }
+ return FALSE;
+}
+
static void
gst_aml_v4l2_video_dec_loop(GstVideoDecoder *decoder)
{
@@ -1106,6 +1172,7 @@
}
ret = gst_buffer_pool_acquire_buffer(pool, &buffer, NULL);
+
//calculate a new pts for interlace stream
if (ret == GST_FLOW_OK && self->v4l2capture->info.interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED)
{
@@ -1146,6 +1213,12 @@
}
}
+ if (ret == GST_AML_V4L2_FLOW_CC_DATA)
+ {
+ GST_DEBUG_OBJECT(decoder, "continue get cc data ");
+ continue;
+ }
+
if (ret == GST_AML_V4L2_FLOW_SOURCE_CHANGE)
{
GST_LOG_OBJECT(decoder, "Get GST_AML_V4L2_FLOW_SOURCE_CHANGE");
@@ -1173,7 +1246,7 @@
return;
}
- } while (ret == GST_AML_V4L2_FLOW_CORRUPTED_BUFFER);
+ } while ((ret == GST_AML_V4L2_FLOW_CORRUPTED_BUFFER) || (ret == GST_AML_V4L2_FLOW_CC_DATA));
if (ret != GST_FLOW_OK)
goto beach;
@@ -1206,6 +1279,33 @@
frame->pts = GST_BUFFER_TIMESTAMP(buffer);
frame->duration = GST_BUFFER_DURATION(buffer);
buffer = NULL;
+
+ GST_DEBUG_OBJECT (decoder,"enable_cc_data:%d",self->v4l2capture->enable_cc_data);
+ if (self->v4l2capture->enable_cc_data)
+ {
+ if (foreach_cc_buffer_list_match_pts_func(v4l2_pool->cc_buffer_list, frame))
+ {
+ GST_DEBUG("cc buffer and frame bind success");
+ GstBuffer *cc_buffer = gst_mini_object_get_qdata (GST_MINI_OBJECT (frame->output_buffer),
+ GST_AML_V4L2_CC_IMPORT_QUARK);
+ #if 0
+ //Debug code:dump cc data
+ GstMapInfo gst_map;
+ gst_buffer_map(cc_buffer,&gst_map,GST_MAP_READ);
+ int fd=open("/data/test/cc2.data",O_RDWR |O_CREAT|O_APPEND,0777);
+ if (gst_map.size>0)
+ write(fd,gst_map.data,gst_map.size);
+ close(fd);
+ gst_buffer_unmap(cc_buffer,&gst_map);
+ #endif
+ v4l2_pool->cc_buffer_list = g_list_remove(v4l2_pool->cc_buffer_list,cc_buffer);
+ gst_buffer_unref(cc_buffer);
+ }
+ else
+ {
+ GST_WARNING("bufferlist is empty or no match frame in the bufferlist");
+ }
+ }
ret = gst_video_decoder_finish_frame(decoder, frame);
if (ret != GST_FLOW_OK)