From f6cd1db849478203ee8e49f86da283884958c399 Mon Sep 17 00:00:00 2001 From: Nanxin Qin Date: Sun, 4 Feb 2018 16:55:25 +0800 Subject: [PATCH] media: fixed the issure of mpeg12 playback. PD#156734: Change-Id: I87d814707d864a8fc81bcb35712ef0c25fea65db Signed-off-by: Nanxin Qin --- drivers/amlogic/media/frame_sync/ptsserv.c | 169 ++++++++++++++++++ .../linux/amlogic/media/frame_sync/ptsserv.h | 4 + include/linux/amlogic/media/utils/amstream.h | 93 +++++++++- 3 files changed, 263 insertions(+), 3 deletions(-) diff --git a/drivers/amlogic/media/frame_sync/ptsserv.c b/drivers/amlogic/media/frame_sync/ptsserv.c index df3416aec227..cd5bbe4e3fe8 100644 --- a/drivers/amlogic/media/frame_sync/ptsserv.c +++ b/drivers/amlogic/media/frame_sync/ptsserv.c @@ -966,6 +966,151 @@ static int pts_lookup_offset_inline_locked(u8 type, u32 offset, u32 *val, return -1; } +static int pts_pick_by_offset_inline_locked(u8 type, u32 offset, u32 *val, + u32 pts_margin, u64 *uS64) +{ + struct pts_table_s *pTable; + int lookup_threshold; + + int look_cnt = 0; + + if (type >= PTS_TYPE_MAX) + return -EINVAL; + + pTable = &pts_table[type]; + + if (pts_margin == 0) + lookup_threshold = pTable->lookup_threshold; + else + lookup_threshold = pts_margin; + + if (!pTable->first_lookup_ok) + lookup_threshold <<= 1; + + + + if (likely(pTable->status == PTS_RUNNING)) { + struct pts_rec_s *p = NULL; + struct pts_rec_s *p2 = NULL; + + if ((pTable->lookup_cache_valid) && + (offset == pTable->lookup_cache_offset)) { + *val = pTable->lookup_cache_pts; + return 0; + } + + if ((type == PTS_TYPE_VIDEO) + && !list_empty(&pTable->valid_list)) { + struct pts_rec_s *rec = NULL; + struct pts_rec_s *next = NULL; + int look_cnt1 = 0; + + list_for_each_entry_safe(rec, + next, &pTable->valid_list, list) { + if (OFFSET_DIFF(offset, rec->offset) > + PTS_VALID_OFFSET_TO_CHECK) { + if (pTable->pts_search == &rec->list) + pTable->pts_search = + rec->list.next; + + if (tsync_get_debug_vpts()) { + pr_info("remove node offset: 0x%x cnt:%d\n", + rec->offset, look_cnt1); + } + + list_move_tail(&rec->list, + &pTable->free_list); + look_cnt1++; + } else { + break; + } + } + } + + if (list_empty(&pTable->valid_list)) + return -1; + + if (pTable->pts_search == &pTable->valid_list) { + p = list_entry(pTable->valid_list.next, + struct pts_rec_s, list); + } else { + p = list_entry(pTable->pts_search, struct pts_rec_s, + list); + } + + if (OFFSET_LATER(offset, p->offset)) { + p2 = p; /* lookup candidate */ + + list_for_each_entry_continue(p, &pTable->valid_list, + list) { +#if 0 + if (type == PTS_TYPE_VIDEO) + pr_info(" >> rec: 0x%x\n", p->offset); +#endif + look_cnt++; + + if (OFFSET_LATER(p->offset, offset)) + break; + + p2 = p; + } + } else if (OFFSET_LATER(p->offset, offset)) { + list_for_each_entry_continue_reverse(p, + &pTable-> + valid_list, list) { +#if 0 + if (type == PTS_TYPE_VIDEO) + pr_info(" >> rec: 0x%x\n", p->offset); +#endif +#ifdef DEBUG + look_cnt++; +#endif + if (OFFSET_EQLATER(offset, p->offset)) { + p2 = p; + break; + } + } + } else + p2 = p; + + if ((p2) && + (OFFSET_DIFF(offset, p2->offset) < lookup_threshold)) { + + if (tsync_get_debug_pts_checkout()) { + if (tsync_get_debug_vpts() + && (type == PTS_TYPE_VIDEO)) { + pr_info + ("vpts look up offset<0x%x> -->", + offset); + pr_info + ("<0x%x:0x%x>, look_cnt = %d\n", + p2->offset, p2->val, look_cnt); + } + + if (tsync_get_debug_apts() + && (type == PTS_TYPE_AUDIO)) { + pr_info + ("apts look up offset<0x%x> -->", + offset); + pr_info + ("<0x%x:0x%x>, look_cnt = %d\n", + p2->offset, p2->val, look_cnt); + + } + } + *val = p2->val; + *uS64 = p2->pts_uS64; + + return 0; + + } + } + + + return -1; +} + + static int pts_lookup_offset_inline(u8 type, u32 offset, u32 *val, u32 pts_margin, u64 *uS64) { @@ -996,6 +1141,22 @@ static int pts_lookup_offset_inline(u8 type, u32 offset, u32 *val, return res; } +static int pts_pick_by_offset_inline(u8 type, u32 offset, u32 *val, + u32 pts_margin, u64 *uS64) +{ + unsigned long flags; + int res; + + spin_lock_irqsave(&lock, flags); + res = pts_pick_by_offset_inline_locked( + type, offset, val, pts_margin, uS64); + + spin_unlock_irqrestore(&lock, flags); + + return res; +} + + int pts_lookup_offset(u8 type, u32 offset, u32 *val, u32 pts_margin) { u64 pts_us; @@ -1011,6 +1172,14 @@ int pts_lookup_offset_us64(u8 type, u32 offset, u32 *val, u32 pts_margin, } EXPORT_SYMBOL(pts_lookup_offset_us64); +int pts_pickout_offset_us64(u8 type, u32 offset, u32 *val, u32 pts_margin, + u64 *uS64) +{ + return pts_pick_by_offset_inline(type, offset, val, pts_margin, uS64); +} +EXPORT_SYMBOL(pts_pickout_offset_us64); + + int pts_set_resolution(u8 type, u32 level) { if (type >= PTS_TYPE_MAX) diff --git a/include/linux/amlogic/media/frame_sync/ptsserv.h b/include/linux/amlogic/media/frame_sync/ptsserv.h index 1422adcac908..d17f1aaec14f 100644 --- a/include/linux/amlogic/media/frame_sync/ptsserv.h +++ b/include/linux/amlogic/media/frame_sync/ptsserv.h @@ -50,6 +50,10 @@ extern int pts_lookup_offset(u8 type, u32 offset, u32 *val, u32 pts_margin); extern int pts_lookup_offset_us64(u8 type, u32 offset, u32 *val, u32 pts_margin, u64 *uS64); +extern int pts_pickout_offset_us64(u8 type, u32 offset, + u32 *val, u32 pts_margin, + u64 *uS64); + extern int pts_set_resolution(u8 type, u32 level); extern int pts_set_rec_size(u8 type, u32 val); diff --git a/include/linux/amlogic/media/utils/amstream.h b/include/linux/amlogic/media/utils/amstream.h index f1e931d7146c..9f6ed853774c 100644 --- a/include/linux/amlogic/media/utils/amstream.h +++ b/include/linux/amlogic/media/utils/amstream.h @@ -120,10 +120,20 @@ #define AMSTREAM_IOC_UD_LENGTH _IOR((_A_M), 0x54, int) #define AMSTREAM_IOC_UD_POC _IOR((_A_M), 0x55, int) #define AMSTREAM_IOC_UD_FLUSH_USERDATA _IOR((_A_M), 0x56, int) + +#define AMSTREAM_IOC_UD_BUF_READ _IOR((_A_M), 0x57, struct userdata_param_t) + #define AMSTREAM_IOC_GET_SCREEN_MODE _IOR((_A_M), 0x58, int) #define AMSTREAM_IOC_SET_SCREEN_MODE _IOW((_A_M), 0x59, int) #define AMSTREAM_IOC_GET_VIDEO_DISCONTINUE_REPORT _IOR((_A_M), 0x5a, int) #define AMSTREAM_IOC_SET_VIDEO_DISCONTINUE_REPORT _IOW((_A_M), 0x5b, int) + +/* + * #define AMSTREAM_IOC_UD_BUF_STATUS _IOR((_A_M), + * 0x5c, struct userdata_buf_state_t) + */ + + #define AMSTREAM_IOC_VF_STATUS _IOR((_A_M), 0x60, int) #define AMSTREAM_IOC_CLEAR_VBUF _IO((_A_M), 0x80) @@ -138,6 +148,8 @@ #define AMSTREAM_IOC_SET_VSYNC_UPINT _IOW((_A_M), 0x89, int) #define AMSTREAM_IOC_GET_VSYNC_SLOW_FACTOR _IOW((_A_M), 0x8a, int) #define AMSTREAM_IOC_SET_VSYNC_SLOW_FACTOR _IOW((_A_M), 0x8b, int) +#define AMSTREAM_IOC_GET_FIRST_FRAME_LATENCY _IOR((_A_M), 0x8c, int) +#define AMSTREAM_IOC_CLEAR_FIRST_FRAME_LATENCY _IOR((_A_M), 0x8d, int) #define AMSTREAM_IOC_SET_DEMUX _IOW((_A_M), 0x90, int) #define AMSTREAM_IOC_SET_DRMMODE _IOW((_A_M), 0x91, int) #define AMSTREAM_IOC_TSTAMP_uS64 _IOW((_A_M), 0x95, int) @@ -380,12 +392,87 @@ struct codec_profile_t { struct userdata_poc_info_t { unsigned int poc_info; - unsigned int poc_number; + /* + * bit 0: + * 1, group start + * 0, not group start + * bit 1-2: + * 0, extension_and_user_data( 0 ) + * 1, extension_and_user_data( 1 ) + * 2, extension_and_user_data( 2 ) + */ + unsigned int flags; + unsigned int vpts; + unsigned int vpts_valid; + unsigned int duration; }; -/* -****************************************************************** +struct userdata_meta_info_t { + uint32_t poc_number; + /************ flags bit defination ***********/ + /* + * bit 0: //used for mpeg2 + * 1, group start + * 0, not group start + * bit 1-2: //used for mpeg2 + * 0, extension_and_user_data( 0 ) + * 1, extension_and_user_data( 1 ) + * 2, extension_and_user_data( 2 ) + * bit 3-6: //video format + * 0, VFORMAT_MPEG12 + * 1, VFORMAT_MPEG4 + * 2, VFORMAT_H264 + * 3, VFORMAT_MJPEG + * 4, VFORMAT_REAL + * 5, VFORMAT_JPEG + * 6, VFORMAT_VC1 + * 7, VFORMAT_AVS + * 8, VFORMAT_SW + * 9, VFORMAT_H264MVC + * 10, VFORMAT_H264_4K2K + * 11, VFORMAT_HEVC + * 12, VFORMAT_H264_ENC + * 13, VFORMAT_JPEG_ENC + * 14, VFORMAT_VP9 + * bit 7-9: //frame type + * 0, Unknown Frame Type + * 1, I Frame + * 2, B Frame + * 3, P Frame + * 4, D_Type_MPEG2 + * bit 10: //top_field_first_flag valid + * 0: top_field_first_flag is not valid + * 1: top_field_first_flag is valid + * bit 11: //top_field_first bit val + */ + uint32_t flags; + uint32_t vpts; /*video frame pts*/ + /* + * 0: pts is invalid, please use duration to calcuate + * 1: pts is valid + */ + uint32_t vpts_valid; + /*duration for frame*/ + uint32_t duration; + /* how many records left in queue waiting to be read*/ + uint32_t records_in_que; + unsigned long long priv_data; + uint32_t padding_data[4]; +}; + +struct userdata_param_t { + uint32_t version; + uint32_t instance_id; /*input, 0~9*/ + uint32_t buf_len; /*input*/ + uint32_t data_size; /*output*/ + unsigned long long pbuf_addr; /*input*/ + struct userdata_meta_info_t meta_info; /*output*/ +}; + + + +/******************************************************************* * 0x100~~0x1FF : set cmd * 0x200~~0x2FF : set ex cmd * 0x300~~0x3FF : set ptr cmd