int max_mv;
int min_mv;
int avg_mv;
+
+ u32 hw_decode_time;
+ u32 frame_size; // For frame base mode
};
/*
#define SHOW_QOS_INFO
*/
- vframe_qos->size = framesize;
+ if (input_frame_based(hw_to_vdec(dec)))
+ vframe_qos->size = pic->frame_size;
+ else
+ vframe_qos->size = framesize;
vframe_qos->pts = pts;
#ifdef SHOW_QOS_INFO
avs2_print(dec, 0, "slice:%d\n", pic->slice_type);
vframe_qos->num++;
- if (dec->frameinfo_enable)
- vdec_fill_frame_info(vframe_qos, 1);
}
static void set_vframe(struct AVS2Decoder_s *dec,
{
unsigned long flags;
int stream_offset;
- unsigned int frame_size;
+ unsigned int frame_size = 0;
int pts_discontinue;
stream_offset = pic->stream_offset;
avs2_print(dec, AVS2_DBG_BUFMGR,
dec->vf_pre_count++;
}
+static inline void dec_update_gvs(struct AVS2Decoder_s *dec)
+{
+ if (dec->gvs->frame_height != dec->frame_height) {
+ dec->gvs->frame_width = dec->frame_width;
+ dec->gvs->frame_height = dec->frame_height;
+ }
+ if (dec->gvs->frame_dur != dec->frame_dur) {
+ dec->gvs->frame_dur = dec->frame_dur;
+ if (dec->frame_dur != 0)
+ dec->gvs->frame_rate = 96000 / dec->frame_dur;
+ else
+ dec->gvs->frame_rate = -1;
+ }
+ dec->gvs->status = dec->stat | dec->fatal_error;
+}
+
static int avs2_prepare_display_buf(struct AVS2Decoder_s *dec)
{
struct vframe_s *vf = NULL;
/*unsigned short slice_type;*/
struct avs2_frame_s *pic;
+ struct vdec_s *pvdec = hw_to_vdec(dec);
while (1) {
pic = get_disp_pic(dec);
if (pic == NULL)
}
if (vf) {
+ int stream_offset = pic->stream_offset;
set_vframe(dec, vf, pic, 0);
- decoder_do_frame_check(hw_to_vdec(dec), vf);
+ decoder_do_frame_check(pvdec, vf);
kfifo_put(&dec->display_q, (const struct vframe_s *)vf);
ATRACE_COUNTER(MODULE_NAME, vf->pts);
- #ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
+ dec_update_gvs(dec);
/*count info*/
- gvs->frame_dur = dec->frame_dur;
- vdec_count_info(gvs, 0, stream_offset);
- #endif
- hw_to_vdec(dec)->vdec_fps_detec(hw_to_vdec(dec)->id);
+ vdec_count_info(dec->gvs, 0, stream_offset);
+ dec->gvs->bit_rate = bit_depth_luma;
+ dec->gvs->frame_data = bit_depth_chroma;
+ dec->gvs->samp_cnt = get_double_write_mode(dec);
+ vdec_fill_vdec_frame(pvdec, &dec->vframe_qos, dec->gvs, vf, pic->hw_decode_time);
+ pvdec->vdec_fps_detec(pvdec->id);
if (without_display_mode == 0) {
vf_notify_receiver(dec->provider_name,
VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
static void get_picture_qos_info(struct AVS2Decoder_s *dec)
{
struct avs2_frame_s *picture = dec->avs2_dec.hc.cur_pic;
+ struct vdec_s *vdec = hw_to_vdec(dec);
if (!picture) {
avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
"%s decode picture is none exist\n");
return;
}
+ if (vdec->mvfrm) {
+ picture->frame_size = vdec->mvfrm->frame_size;
+ picture->hw_decode_time =
+ local_clock() - vdec->mvfrm->hw_decode_start;
+ }
/*
#define DEBUG_QOS
vstatus->error_count = 0;
vstatus->status = dec->stat | dec->fatal_error;
vstatus->frame_dur = dec->frame_dur;
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
- vstatus->bit_rate = gvs->bit_rate;
- vstatus->frame_data = gvs->frame_data;
- vstatus->total_data = gvs->total_data;
- vstatus->frame_count = gvs->frame_count;
- vstatus->error_frame_count = gvs->error_frame_count;
- vstatus->drop_frame_count = gvs->drop_frame_count;
- vstatus->total_data = gvs->total_data;
- vstatus->samp_cnt = gvs->samp_cnt;
- vstatus->offset = gvs->offset;
+ vstatus->bit_rate = dec->gvs->bit_rate;
+ vstatus->frame_data = dec->gvs->frame_data;
+ vstatus->total_data = dec->gvs->total_data;
+ vstatus->frame_count = dec->gvs->frame_count;
+ vstatus->error_frame_count = dec->gvs->error_frame_count;
+ vstatus->drop_frame_count = dec->gvs->drop_frame_count;
+ vstatus->total_data = dec->gvs->total_data;
+ vstatus->samp_cnt = dec->gvs->samp_cnt;
+ vstatus->offset = dec->gvs->offset;
snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name),
"%s", DRIVER_NAME);
-#endif
return 0;
}
if (vavs2_local_init(dec) < 0)
return -EBUSY;
+ vdec_set_vframe_comm(vdec, DRIVER_NAME);
+
fw = vmalloc(sizeof(struct firmware_s) + fw_size);
if (IS_ERR_OR_NULL(fw))
return -ENOMEM;
WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, 0);
r = dec->chunk->size +
(dec->chunk->offset & (VDEC_FIFO_ALIGN - 1));
+ if (vdec->mvfrm)
+ vdec->mvfrm->frame_size = dec->chunk->size;
}
WRITE_VREG(HEVC_DECODE_SIZE, r);
mod_timer(&dec->timer, jiffies);
dec->stat |= STAT_TIMER_ARM;
dec->stat |= STAT_ISR_REG;
+ if (vdec->mvfrm)
+ vdec->mvfrm->hw_decode_start = local_clock();
amhevc_start();
dec->stat |= STAT_VDEC_RUN;
}
}
#endif
+
+static inline void avs_update_gvs(struct vdec_avs_hw_s *hw)
+{
+ if (hw->gvs->frame_height != hw->frame_height) {
+ hw->gvs->frame_width = hw->frame_width;
+ hw->gvs->frame_height = hw->frame_height;
+ }
+ if (hw->gvs->frame_dur != hw->frame_dur) {
+ hw->gvs->frame_dur = hw->frame_dur;
+ if (hw->frame_dur != 0)
+ hw->gvs->frame_rate = 96000 / hw->frame_dur;
+ else
+ hw->gvs->frame_rate = -1;
+ }
+
+ hw->gvs->status = hw->stat;
+ hw->gvs->error_count = READ_VREG(AV_SCRATCH_C);
+ hw->gvs->drop_frame_count = hw->drop_frame_count;
+
+}
+
#ifdef HANDLE_AVS_IRQ
static irqreturn_t vavs_isr(int irq, void *dev_id)
#else
#endif
{
u32 reg;
- struct vframe_s *vf;
+ struct vframe_s *vf = NULL;
u32 dur;
u32 repeat_count;
u32 picture_type;
}
/*count info*/
- hw->gvs->frame_dur = hw->frame_dur;
vdec_count_info(hw->gvs, 0, offset);
+ avs_update_gvs(hw);
+ vdec_fill_vdec_frame(hw_to_vdec(hw), NULL, hw->gvs, vf, 0);
/* pr_info("PicType = %d, PTS = 0x%x\n",
* picture_type, vf->pts);
vdec_set_prepare_level(pdata, start_decode_buf_level);
+ vdec_set_vframe_comm(pdata, DRIVER_NAME);
+
if (pdata->parallel_dec == 1)
vdec_core_request(pdata, CORE_MASK_VDEC_1);
else {
}
return true;
}
+
+static inline void h264_update_gvs(void)
+{
+ u32 ratio_control;
+ u32 ar;
+
+ if (gvs->frame_height != frame_height) {
+ gvs->frame_width = frame_width;
+ gvs->frame_height = frame_height;
+ }
+ if (gvs->frame_dur != frame_dur) {
+ gvs->frame_dur = frame_dur;
+ if (frame_dur != 0)
+ gvs->frame_rate = 96000 / frame_dur;
+ else
+ gvs->frame_rate = -1;
+ }
+ gvs->error_count = READ_VREG(AV_SCRATCH_D);
+ gvs->status = stat;
+ if (fatal_error_reset)
+ gvs->status |= fatal_error_flag;
+ ar = min_t(u32,
+ h264_ar,
+ DISP_RATIO_ASPECT_RATIO_MAX);
+ ratio_control =
+ ar << DISP_RATIO_ASPECT_RATIO_BIT;
+ gvs->ratio_control = ratio_control;
+}
+
+
#ifdef HANDLE_H264_IRQ
static irqreturn_t vh264_isr(int irq, void *dev_id)
#else
frame_count++;
s_vframe_qos.num = frame_count;
- vdec_fill_frame_info(&s_vframe_qos, 1);
+ //vdec_fill_frame_info(&s_vframe_qos, 1);
/* on second IDR frame,check the diff between pts
* compute from duration and pts from lookup ,
*/
/*count info*/
- gvs->frame_dur = frame_dur;
+ h264_update_gvs();
vdec_count_info(gvs, error, b_offset);
+ vdec_fill_vdec_frame(vdec_h264, &s_vframe_qos, gvs, vf, 0);
if ((pts_valid) && (check_pts_discontinue)
&& (!error)) {
atomic_set(&vh264_active, 1);
mutex_unlock(&vh264_mutex);
+ vdec_set_vframe_comm(pdata, DRIVER_NAME);
return 0;
}
struct StorablePicture *p,
unsigned char data_flag)
{
+ struct vdec_frames_s *mvfrm = p_H264_Dpb->vdec->mvfrm;
struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo;
/* InputParameters *p_Inp = p_Vid->p_Inp;
* dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
//fs->pts64 = p->pts64;
}
fs->timestamp = p->timestamp;
+ if (mvfrm) {
+ fs->frame_size2 = mvfrm->frame_size;
+ fs->hw_decode_time = mvfrm->hw_decode_time;
+ }
}
void reset_frame_store(struct h264_dpb_stru *p_H264_Dpb,
int min_mv;
int avg_mv;
int dpb_frame_count;
+ u32 hw_decode_time;
+ u32 frame_size2; // For recording the chunk->size in frame mode
};
static void fill_frame_info(struct vdec_h264_hw_s *hw, struct FrameStore *frame)
{
struct vframe_qos_s *vframe_qos = &hw->vframe_qos;
+
if (frame->slice_type == I_SLICE)
vframe_qos->type = 1;
else if (frame->slice_type == P_SLICE)
else if (frame->slice_type == B_SLICE)
vframe_qos->type = 3;
- vframe_qos->size = frame->frame_size;
+ if (input_frame_based(hw_to_vdec(hw)))
+ vframe_qos->size = frame->frame_size2;
+ else
+ vframe_qos->size = frame->frame_size;
vframe_qos->pts = frame->pts64;
vframe_qos->max_mv = frame->max_mv;
vframe_qos->min_skip);
*/
vframe_qos->num++;
- if (hw->frameinfo_enable)
- vdec_fill_frame_info(vframe_qos, 1);
}
static int is_iframe(struct FrameStore *frame) {
vf->duration = vf->duration/2;
}
- if (i == 0)
- decoder_do_frame_check(hw_to_vdec(hw), vf);
+ if (i == 0) {
+ struct vdec_s *pvdec;
+ struct vdec_info vs;
+
+ pvdec = hw_to_vdec(hw);
+ memset(&vs, 0, sizeof(struct vdec_info));
+ pvdec->dec_status(pvdec, &vs);
+ decoder_do_frame_check(pvdec, vf);
+ vdec_fill_vdec_frame(pvdec, &hw->vframe_qos, &vs, vf, frame->hw_decode_time);
+ }
/*vf->ratio_control |= (0x3FF << DISP_RATIO_ASPECT_RATIO_BIT);*/
vf->sar_width = hw->width_aspect_ratio;
struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
int ret;
+ if (vdec->mvfrm)
+ vdec->mvfrm->hw_decode_time =
+ local_clock() - vdec->mvfrm->hw_decode_start;
+
if (input_frame_based(vdec) &&
(!(hw->i_only & 0x2)) &&
frmbase_cont_bitlevel != 0 &&
vstatus->frame_width = hw->frame_width;
vstatus->frame_height = hw->frame_height;
- if (hw->frame_dur != 0)
+ if (hw->frame_dur != 0) {
+ vstatus->frame_dur = hw->frame_dur;
vstatus->frame_rate = 96000 / hw->frame_dur;
+ }
else
vstatus->frame_rate = -1;
vstatus->error_count = 0;
WRITE_VREG(H264_DECODE_INFO, (1<<13));
WRITE_VREG(H264_DECODE_SIZE, decode_size);
WRITE_VREG(VIFF_BIT_CNT, decode_size * 8);
+ if (vdec->mvfrm)
+ vdec->mvfrm->frame_size = hw->chunk->size;
} else {
if (size <= 0)
size = 0x7fffffff; /*error happen*/
else
CLEAR_VREG_MASK(VDEC_ASSIST_MMC_CTRL1, 1 << 3);
}
+ if (vdec->mvfrm)
+ vdec->mvfrm->hw_decode_start = local_clock();
amvdec_start();
if (hw->mmu_enable /*&& !hw->frame_busy && !hw->frame_done*/) {
WRITE_VREG(HEVC_ASSIST_SCRATCH_0, 0x0);
| CORE_MASK_COMBINE);
atomic_set(&hw->vh264_active, 1);
+ vdec_set_vframe_comm(pdata, DRIVER_NAME);
return 0;
}
static DEFINE_MUTEX(vh265_log_mutex);
-static struct vdec_info *gvs;
+//static struct vdec_info *gvs;
static u32 without_display_mode;
int min_mv;
int avg_mv;
+ u32 hw_decode_time;
+ u32 frame_size; // For frame base mode
bool vframe_bound;
} /*PIC_t */;
void *v4l2_ctx;
bool v4l_params_parsed;
u32 mem_map_mode;
+ struct vdec_info *gvs;
} /*hevc_stru_t */;
#ifdef AGAIN_HAS_THRESHOLD
pic = get_pic_by_POC(hevc, decoded_poc);
if (pic && (pic->POC != INVALID_POC)) {
+ struct vdec_s *vdec = hw_to_vdec(hevc);
+
/*PB skip control */
if (pic->error_mark == 0
&& hevc->PB_skip_mode == 1) {
pic->output_mark = 1;
pic->recon_mark = 1;
pic->dis_mark = 1;
+ if (vdec->mvfrm) {
+ pic->frame_size = vdec->mvfrm->frame_size;
+ pic->hw_decode_time = (u32)vdec->mvfrm->hw_decode_time;
+ }
}
do {
pic_display = output_pic(hevc, 0);
if (hevc->cur_pic->error_mark
&& ((hevc->ignore_bufmgr_error & 0x1) == 0)) {
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
/*count info*/
- vdec_count_info(gvs, hevc->cur_pic->error_mark,
+ vdec_count_info(hevc->gvs, hevc->cur_pic->error_mark,
hevc->cur_pic->stream_offset);
-#endif
}
if (is_skip_decoding(hevc,
hevc_print(hevc, 0,
"Discard this picture index %d\n",
hevc->cur_pic->index);
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
/*count info*/
- vdec_count_info(gvs, hevc->cur_pic->error_mark,
+ vdec_count_info(hevc->gvs, hevc->cur_pic->error_mark,
hevc->cur_pic->stream_offset);
-#endif
return 2;
}
#ifdef MCRCC_ENABLE
hevc->frame_mmu_map_addr = NULL;
}
- kfree(gvs);
- gvs = NULL;
+ //pr_err("[%s line %d] hevc->gvs=0x%p operation\n",__func__, __LINE__, hevc->gvs);
+ if (hevc->gvs)
+ kfree(hevc->gvs);
+ hevc->gvs = NULL;
}
static int hevc_local_init(struct hevc_state_s *hevc)
/*
#define SHOW_QOS_INFO
*/
- vframe_qos->size = framesize;
+ if (input_frame_based(hw_to_vdec(hevc)))
+ vframe_qos->size = pic->frame_size;
+ else
+ vframe_qos->size = framesize;
vframe_qos->pts = pts;
#ifdef SHOW_QOS_INFO
hevc_print(hevc, 0, "slice:%d, poc:%d\n", pic->slice_type, pic->POC);
vframe_qos->num++;
- if (hevc->frameinfo_enable)
- vdec_fill_frame_info(vframe_qos, 1);
+}
+
+static inline void hevc_update_gvs(struct hevc_state_s *hevc)
+{
+ if (hevc->gvs->frame_height != hevc->frame_height) {
+ hevc->gvs->frame_width = hevc->frame_width;
+ hevc->gvs->frame_height = hevc->frame_height;
+ }
+ if (hevc->gvs->frame_dur != hevc->frame_dur) {
+ hevc->gvs->frame_dur = hevc->frame_dur;
+ if (hevc->frame_dur != 0)
+ hevc->gvs->frame_rate = 96000 / hevc->frame_dur;
+ else
+ hevc->gvs->frame_rate = -1;
+ }
+ hevc->gvs->status = hevc->stat | hevc->fatal_error;
+ if (hevc->gvs->ratio_control != hevc->ratio_control)
+ hevc->gvs->ratio_control = hevc->ratio_control;
}
static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
{
-#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
struct vdec_s *vdec = hw_to_vdec(hevc);
-#endif
struct vframe_s *vf = NULL;
int stream_offset = pic->stream_offset;
unsigned short slice_type = pic->slice_type;
- u32 frame_size;
+ u32 frame_size = 0;
if (force_disp_pic_index & 0x100) {
/*recycle directly*/
}
#ifdef MULTI_INSTANCE_SUPPORT
- if (vdec_frame_based(hw_to_vdec(hevc))) {
+ if (vdec_frame_based(vdec)) {
vf->pts = pic->pts;
vf->pts_us64 = pic->pts64;
vf->timestamp = pic->timestamp;
| VIDTYPE_VIU_NV21;
}
hevc->vf_pre_count++;
- decoder_do_frame_check(hw_to_vdec(hevc), vf);
+ decoder_do_frame_check(vdec, vf);
kfifo_put(&hevc->display_q,
(const struct vframe_s *)vf);
ATRACE_COUNTER(MODULE_NAME, vf->pts);
| VIDTYPE_VIU_NV21;
}
hevc->vf_pre_count++;
- decoder_do_frame_check(hw_to_vdec(hevc), vf);
+ decoder_do_frame_check(vdec, vf);
kfifo_put(&hevc->display_q,
(const struct vframe_s *)vf);
ATRACE_COUNTER(MODULE_NAME, vf->pts);
process_pending_vframe(hevc,
pic, (pic->pic_struct == 9));
- decoder_do_frame_check(hw_to_vdec(hevc), vf);
+ decoder_do_frame_check(vdec, vf);
/* process current vf */
kfifo_put(&hevc->pending_q,
(const struct vframe_s *)vf);
VIDTYPE_VIU_NV21 | VIDTYPE_VIU_FIELD;
vf->index = (pic->index << 8) | 0xff;
}
- decoder_do_frame_check(hw_to_vdec(hevc), vf);
+ decoder_do_frame_check(vdec, vf);
kfifo_put(&hevc->pending_q,
(const struct vframe_s *)vf);
if (hevc->vf_pre_count == 0)
break;
}
hevc->vf_pre_count++;
- decoder_do_frame_check(hw_to_vdec(hevc), vf);
+ decoder_do_frame_check(vdec, vf);
kfifo_put(&hevc->display_q,
(const struct vframe_s *)vf);
ATRACE_COUNTER(MODULE_NAME, vf->pts);
vf->type_original = vf->type;
pic->vf_ref = 1;
hevc->vf_pre_count++;
- decoder_do_frame_check(hw_to_vdec(hevc), vf);
+ decoder_do_frame_check(vdec, vf);
kfifo_put(&hevc->display_q, (const struct vframe_s *)vf);
ATRACE_COUNTER(MODULE_NAME, vf->pts);
vf->pts, vf->pts_us64,
vf->duration);
#endif
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
/*count info*/
- vdec_count_info(gvs, 0, stream_offset);
-#endif
- hw_to_vdec(hevc)->vdec_fps_detec(hw_to_vdec(hevc)->id);
+ vdec_count_info(hevc->gvs, 0, stream_offset);
+ hevc_update_gvs(hevc);
+ hevc->gvs->bit_rate = hevc->bit_depth_luma;
+ hevc->gvs->frame_data = hevc->bit_depth_chroma;
+ hevc->gvs->samp_cnt = get_double_write_mode(hevc);
+ vdec_fill_vdec_frame(vdec, &hevc->vframe_qos, hevc->gvs, vf, pic->hw_decode_time);
+ vdec->vdec_fps_detec(vdec->id);
if (without_display_mode == 0) {
vf_notify_receiver(hevc->provider_name,
VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
struct PIC_s *pic;
struct PIC_s *pic_display;
int decoded_poc;
+
+ if (vdec->mvfrm)
+ vdec->mvfrm->hw_decode_time =
+ local_clock() - vdec->mvfrm->hw_decode_start;
#ifdef DETREFILL_ENABLE
if (hevc->is_swap &&
get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM) {
pic->output_mark = 1;
pic->recon_mark = 1;
+ if (vdec->mvfrm) {
+ pic->frame_size =
+ vdec->mvfrm->frame_size;
+ pic->hw_decode_time =
+ (u32)vdec->mvfrm->hw_decode_time;
+ }
}
check_pic_decoded_error(hevc,
READ_VREG(HEVC_PARSER_LCU_START) & 0xffffff);
&hevc->notify_work);
hevc->get_frame_dur = true;
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
- gvs->frame_dur = hevc->frame_dur;
-#endif
+ //hevc->gvs->frame_dur = hevc->frame_dur;
}
if (hevc->video_signal_type !=
#endif
} else {
/* skip, search next start code */
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
- gvs->drop_frame_count++;
-#endif
+ hevc->gvs->drop_frame_count++;
WRITE_VREG(HEVC_WAIT_FLAG, READ_VREG(HEVC_WAIT_FLAG) & (~0x2));
hevc->skip_flag = 1;
WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE);
vstatus->frame_rate = -1;
vstatus->error_count = 0;
vstatus->status = hevc->stat | hevc->fatal_error;
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
- vstatus->bit_rate = gvs->bit_rate;
+ vstatus->bit_rate = hevc->gvs->bit_rate;
vstatus->frame_dur = hevc->frame_dur;
- if (gvs) {
- vstatus->bit_rate = gvs->bit_rate;
- vstatus->frame_data = gvs->frame_data;
- vstatus->total_data = gvs->total_data;
- vstatus->frame_count = gvs->frame_count;
- vstatus->error_frame_count = gvs->error_frame_count;
- vstatus->drop_frame_count = gvs->drop_frame_count;
- vstatus->total_data = gvs->total_data;
- vstatus->samp_cnt = gvs->samp_cnt;
- vstatus->offset = gvs->offset;
+ if (hevc->gvs) {
+ vstatus->bit_rate = hevc->gvs->bit_rate;
+ vstatus->frame_data = hevc->gvs->frame_data;
+ vstatus->total_data = hevc->gvs->total_data;
+ vstatus->frame_count = hevc->gvs->frame_count;
+ vstatus->error_frame_count = hevc->gvs->error_frame_count;
+ vstatus->drop_frame_count = hevc->gvs->drop_frame_count;
+ vstatus->samp_cnt = hevc->gvs->samp_cnt;
+ vstatus->offset = hevc->gvs->offset;
}
+
snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name),
"%s", DRIVER_NAME);
-#endif
vstatus->ratio_control = hevc->ratio_control;
return 0;
}
return 0;
}
-static int vh265_vdec_info_init(void)
+static int vh265_vdec_info_init(struct hevc_state_s *hevc)
{
- gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL);
- if (NULL == gvs) {
+ hevc->gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL);
+ //pr_err("[%s line %d] hevc->gvs=0x%p operation\n",__func__, __LINE__, hevc->gvs);
+ if (NULL == hevc->gvs) {
pr_info("the struct of vdec status malloc failed.\n");
return -ENOMEM;
}
+ vdec_set_vframe_comm(hw_to_vdec(hevc), DRIVER_NAME);
return 0;
}
hevc->frame_dur =
(hevc->vh265_amstream_dec_info.rate ==
0) ? 3600 : hevc->vh265_amstream_dec_info.rate;
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
- gvs->frame_dur = hevc->frame_dur;
-#endif
+ //hevc->gvs->frame_dur = hevc->frame_dur;
if (hevc->frame_width && hevc->frame_height)
hevc->frame_ar = hevc->frame_height * 0x100 / hevc->frame_width;
uninit_mmu_buffers(hevc);
amhevc_disable();
- kfree(gvs);
- gvs = NULL;
+ //pr_err("[%s line %d] hevc->gvs=0x%p operation\n",__func__, __LINE__, hevc->gvs);
+ if (hevc->gvs)
+ kfree(hevc->gvs);
+ hevc->gvs = NULL;
return 0;
}
r = hevc->chunk->size +
(hevc->chunk->offset & (VDEC_FIFO_ALIGN - 1));
hevc->decode_size = r;
+ if (vdec->mvfrm)
+ vdec->mvfrm->frame_size = hevc->chunk->size;
}
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
else {
mod_timer(&hevc->timer, jiffies);
hevc->stat |= STAT_TIMER_ARM;
hevc->stat |= STAT_ISR_REG;
+ if (vdec->mvfrm)
+ vdec->mvfrm->hw_decode_start = local_clock();
amhevc_start();
hevc->stat |= STAT_VDEC_RUN;
}
workaround_enable &= ~3;
#endif
hevc->cma_dev = pdata->cma_dev;
- vh265_vdec_info_init();
+ vh265_vdec_info_init(hevc);
#ifdef MULTI_INSTANCE_SUPPORT
pdata->private = hevc;
#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
int config_val;
#endif
+ //pr_err("[%s pid=%d tgid=%d] \n",__func__, current->pid, current->tgid);
if (pdata == NULL) {
pr_info("\nammvdec_h265 memory resource undefined.\n");
return -EFAULT;
hevc->double_write_mode);
hevc->cma_dev = pdata->cma_dev;
+ vh265_vdec_info_init(hevc);
if (vh265_init(pdata) < 0) {
hevc_print(hevc, 0,
if (hevc == NULL)
return 0;
+ //pr_err("%s [pid=%d,tgid=%d]\n", __func__, current->pid, current->tgid);
if (get_dbg_flag(hevc))
hevc_print(hevc, 0, "%s\r\n", __func__);
u64 pts64;
bool pts_valid;
ulong v4l_ref_buf_addr;
+ u32 hw_decode_time;
+ u32 frame_size; // For frame base mode
};
struct vdec_mpeg12_hw_s {
bool v4l_params_parsed;
u32 buf_num;
u32 dynamic_buf_num_margin;
+ struct vdec_info gvs;
+ struct vframe_qos_s vframe_qos;
};
static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw);
static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw);
static void reset_process_time(struct vdec_mpeg12_hw_s *hw);
-static struct vdec_info gvs;
static int debug_enable;
/*static struct work_struct userdata_push_work;*/
#undef pr_info
return hw->buf_num;
}
+/* +[SE][BUG-145343][huanghang] fixed:mpeg2 frame qos info notify */
+static void fill_frame_info(struct vdec_mpeg12_hw_s *hw, u32 slice_type,
+ int frame_size, u32 pts)
+{
+ unsigned char a[3];
+ unsigned char i, j, t;
+ unsigned long data;
+ struct vframe_qos_s *vframe_qos = &hw->vframe_qos;
+
+ vframe_qos->type = ((slice_type & PICINFO_TYPE_MASK) ==
+ PICINFO_TYPE_I) ? 1 :
+ ((slice_type &
+ PICINFO_TYPE_MASK) ==
+ PICINFO_TYPE_P) ? 2 : 3;
+ vframe_qos->size = frame_size;
+ vframe_qos->pts = pts;
+
+ get_random_bytes(&data, sizeof(unsigned long));
+ if (vframe_qos->type == 1)
+ data = 0;
+ a[0] = data & 0xff;
+ a[1] = (data >> 8) & 0xff;
+ a[2] = (data >> 16) & 0xff;
+
+ for (i = 0; i < 3; i++) {
+ for (j = i+1; j < 3; j++) {
+ if (a[j] < a[i]) {
+ t = a[j];
+ a[j] = a[i];
+ a[i] = t;
+ } else if (a[j] == a[i]) {
+ a[i]++;
+ t = a[j];
+ a[j] = a[i];
+ a[i] = t;
+ }
+ }
+ }
+ vframe_qos->max_mv = a[2];
+ vframe_qos->avg_mv = a[1];
+ vframe_qos->min_mv = a[0];
+
+ get_random_bytes(&data, sizeof(unsigned long));
+ a[0] = data & 0x1f;
+ a[1] = (data >> 8) & 0x3f;
+ a[2] = (data >> 16) & 0x7f;
+
+ for (i = 0; i < 3; i++) {
+ for (j = i+1; j < 3; j++) {
+ if (a[j] < a[i]) {
+ t = a[j];
+ a[j] = a[i];
+ a[i] = t;
+ } else if (a[j] == a[i]) {
+ a[i]++;
+ t = a[j];
+ a[j] = a[i];
+ a[i] = t;
+ }
+ }
+ }
+ vframe_qos->max_qp = a[2];
+ vframe_qos->avg_qp = a[1];
+ vframe_qos->min_qp = a[0];
+
+ get_random_bytes(&data, sizeof(unsigned long));
+ a[0] = data & 0x1f;
+ a[1] = (data >> 8) & 0x3f;
+ a[2] = (data >> 16) & 0x7f;
+
+ for (i = 0; i < 3; i++) {
+ for (j = i + 1; j < 3; j++) {
+ if (a[j] < a[i]) {
+ t = a[j];
+ a[j] = a[i];
+ a[i] = t;
+ } else if (a[j] == a[i]) {
+ a[i]++;
+ t = a[j];
+ a[j] = a[i];
+ a[i] = t;
+ }
+ }
+ }
+ vframe_qos->max_skip = a[2];
+ vframe_qos->avg_skip = a[1];
+ vframe_qos->min_skip = a[0];
+
+ vframe_qos->num++;
+
+ return;
+}
+
static void set_frame_info(struct vdec_mpeg12_hw_s *hw, struct vframe_s *vf)
{
u32 ar_bits;
}
+static inline void hw_update_gvs(struct vdec_mpeg12_hw_s *hw)
+{
+ if (hw->gvs.frame_height != hw->frame_height) {
+ hw->gvs.frame_width = hw->frame_width;
+ hw->gvs.frame_height = hw->frame_height;
+ }
+ if (hw->gvs.frame_dur != hw->frame_dur) {
+ hw->gvs.frame_dur = hw->frame_dur;
+ if (hw->frame_dur != 0)
+ hw->gvs.frame_rate = 96000 / hw->frame_dur;
+ else
+ hw->gvs.frame_rate = -1;
+ }
+ if (hw->gvs.ratio_control != hw->ratio_control)
+ hw->gvs.ratio_control = hw->ratio_control;
+
+ hw->gvs.status = hw->stat;
+ hw->gvs.error_count = READ_VREG(AV_SCRATCH_C);
+ hw->gvs.drop_frame_count = hw->drop_frame_count;
+
+}
+
static int prepare_display_buf(struct vdec_mpeg12_hw_s *hw,
struct pic_info_t *pic)
{
__func__, hw->disp_num, GET_SLICE_TYPE(info), i,
vf->pts, vf->pts_us64, vf->duration, vf->type);
hw->disp_num++;
- if (i == 0)
- decoder_do_frame_check(hw_to_vdec(hw), vf);
+ if (i == 0) {
+ struct vdec_s *vdec = hw_to_vdec(hw);
+
+ decoder_do_frame_check(vdec, vf);
+ hw_update_gvs(hw);
+ vdec_fill_vdec_frame(vdec, &hw->vframe_qos,
+ &hw->gvs, vf, pic->hw_decode_time);
+ }
vdec->vdec_fps_detec(vdec->id);
vf->mem_handle =
decoder_bmmu_box_get_mem_handle(
static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq)
{
- u32 reg, index, info, seqinfo, offset, pts, frame_size, tmp;
+ u32 reg, index, info, seqinfo, offset, pts, frame_size=0, tmp;
u64 pts_us64 = 0;
struct pic_info_t *new_pic, *disp_pic;
struct vdec_mpeg12_hw_s *hw =
hw->dec_num++;
hw->dec_result = DEC_RESULT_DONE;
new_pic = &hw->pics[index];
+ if (vdec->mvfrm) {
+ new_pic->frame_size = vdec->mvfrm->frame_size;
+ new_pic->hw_decode_time =
+ local_clock() - vdec->mvfrm->hw_decode_start;
+ }
tmp = READ_VREG(MREG_PIC_WIDTH);
if ((tmp > 1920) || (tmp == 0)) {
new_pic->width = 1920;
if (disp_pic->pts_valid)
hw->lastpts64 = disp_pic->pts64;
+ if (input_frame_based(hw_to_vdec(hw)))
+ frame_size = new_pic->frame_size;
+
+ fill_frame_info(hw, info, frame_size, new_pic->pts);
+
if ((hw->first_i_frame_ready == 0) &&
((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) &&
((info & PICINFO_ERROR) == 0))
info = READ_VREG(MREG_PIC_INFO);
offset = READ_VREG(MREG_FRAME_OFFSET);
- vdec_count_info(&gvs, info & PICINFO_ERROR, offset);
+ vdec_count_info(&hw->gvs, info & PICINFO_ERROR, offset);
WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
vstatus->frame_rate = -1;
vstatus->error_count = READ_VREG(AV_SCRATCH_C);
vstatus->status = hw->stat;
- vstatus->bit_rate = gvs.bit_rate;
+ vstatus->bit_rate = hw->gvs.bit_rate;
vstatus->frame_dur = hw->frame_dur;
- vstatus->frame_data = gvs.frame_data;
- vstatus->total_data = gvs.total_data;
- vstatus->frame_count = gvs.frame_count;
- vstatus->error_frame_count = gvs.error_frame_count;
+ vstatus->frame_data = hw->gvs.frame_data;
+ vstatus->total_data = hw->gvs.total_data;
+ vstatus->frame_count = hw->gvs.frame_count;
+ vstatus->error_frame_count = hw->gvs.error_frame_count;
vstatus->drop_frame_count = hw->drop_frame_count;
- vstatus->total_data = gvs.total_data;
- vstatus->samp_cnt = gvs.samp_cnt;
- vstatus->offset = gvs.offset;
+ vstatus->total_data = hw->gvs.total_data;
+ vstatus->samp_cnt = hw->gvs.samp_cnt;
+ vstatus->offset = hw->gvs.offset;
vstatus->ratio_control = hw->ratio_control;
snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name),
"%s", DRIVER_NAME);
READ_PARSER_REG(PARSER_VIDEO_WP),
size);
+ if (vdec->mvfrm && hw->chunk)
+ vdec->mvfrm->frame_size = hw->chunk->size;
hw->input_empty = 0;
vdec_enable_input(vdec);
hw->stat |= STAT_MC_LOAD;
hw->last_vld_level = 0;
start_process_time(hw);
+ if (vdec->mvfrm)
+ vdec->mvfrm->hw_decode_start = local_clock();
amvdec_start();
hw->stat |= STAT_VDEC_RUN;
hw->init_flag = 1;
}
vdec_set_prepare_level(pdata, start_decode_buf_level);
+ vdec_set_vframe_comm(pdata, DRIVER_NAME);
+
if (pdata->parallel_dec == 1)
vdec_core_request(pdata, CORE_MASK_VDEC_1);
else {
hw = NULL;
}
pr_info("ammvdec_mpeg12 removed.\n");
- memset(&gvs, 0x0, sizeof(gvs));
return 0;
}
u32 duration;
u32 repeat_cnt;
ulong v4l_ref_buf_addr;
+ u32 hw_decode_time;
+ u32 frame_size; // For frame base mode;
};
struct vdec_mpeg4_hw_s {
kfifo_put(&hw->newframe_q,
(const struct vframe_s *)vf);
} else {
+ struct vdec_info vinfo;
+
vf->mem_handle =
decoder_bmmu_box_get_mem_handle(
hw->mm_blk_handle, index);
decoder_do_frame_check(vdec, vf);
hw->frame_num++;
+ vdec->dec_status(vdec, &vinfo);
+ vdec_fill_vdec_frame(vdec, NULL,
+ &vinfo, vf, pic->hw_decode_time);
if (without_display_mode == 0) {
vf_notify_receiver(vdec->vf_provider_name,
VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
}
hw->dec_result = DEC_RESULT_DONE;
dec_pic = &hw->pic[index];
+ if (vdec->mvfrm) {
+ dec_pic->frame_size = vdec->mvfrm->frame_size;
+ dec_pic->hw_decode_time =
+ local_clock() - vdec->mvfrm->hw_decode_start;
+ }
dec_pic->pts_valid = false;
dec_pic->pts = 0;
dec_pic->pts64 = 0;
size = hw->chunk_size +
(hw->chunk_offset & (VDEC_FIFO_ALIGN - 1));
WRITE_VREG(VIFF_BIT_CNT, size * 8);
+ if (vdec->mvfrm)
+ vdec->mvfrm->frame_size = hw->chunk->size;
}
hw->input_empty = 0;
hw->last_vld_level = 0;
/* wmb before ISR is handled */
wmb();
+ if (vdec->mvfrm)
+ vdec->mvfrm->hw_decode_start = local_clock();
amvdec_start();
hw->stat |= STAT_VDEC_RUN;
hw->init_flag = 1;
}
vdec_set_prepare_level(pdata, start_decode_buf_level);
+ vdec_set_vframe_comm(pdata, DRIVER_NAME);
+
if (pdata->parallel_dec == 1)
vdec_core_request(pdata, CORE_MASK_VDEC_1);
else {
//static int path_debug = 0;
-static struct vframe_qos_s *frame_info_buf_in = NULL;
-static struct vframe_qos_s *frame_info_buf_out = NULL;
-static int frame_qos_wr = 0;
-static int frame_qos_rd = 0;
+static int enable_mvdec_info = 1;
+
int decode_underflow = 0;
#define CANVAS_MAX_SIZE (AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1)
master->slave = vdec;
master->sched = 1;
}
+ if (enable_mvdec_info) {
+ vdec->mvfrm = (struct vdec_frames_s *)
+ vzalloc(sizeof(struct vdec_frames_s));
+ if (!vdec->mvfrm)
+ pr_err("vzalloc: vdec_frames_s failed\n");
+ }
}
pr_debug("vdec_create instance %p, total %d\n", vdec,
vdec_profile_flush(vdec);
#endif
ida_simple_remove(&vdec_core->ida, vdec->id);
+ if (vdec->mvfrm)
+ vfree(vdec->mvfrm);
vfree(vdec);
atomic_dec(&vdec_core->vdec_nr);
const char *dev_name;
int id = PLATFORM_DEVID_AUTO;/*if have used my self*/
+ //pr_err("%s [pid=%d,tgid=%d]\n", __func__, current->pid, current->tgid);
dev_name = get_dev_name(vdec_single(vdec), vdec->format);
if (dev_name == NULL)
vdec->sys_info->height);
/* vdec is now ready to be active */
vdec_set_status(vdec, VDEC_STATUS_DISCONNECTED);
- if (p->use_vfm_path) {
- frame_info_buf_in = (struct vframe_qos_s *)
- kmalloc(QOS_FRAME_NUM*sizeof(struct vframe_qos_s), GFP_KERNEL);
- if (!frame_info_buf_in)
- pr_err("kmalloc: frame_info_buf_in failed\n");
- else
- memset(frame_info_buf_in, 0,
- QOS_FRAME_NUM*sizeof(struct vframe_qos_s));
-
- frame_info_buf_out = (struct vframe_qos_s *)
- kmalloc(QOS_FRAME_NUM*sizeof(struct vframe_qos_s), GFP_KERNEL);
- if (!frame_info_buf_out)
- pr_err("kmalloc: frame_info_buf_out failed\n");
- else
- memset(frame_info_buf_out, 0,
- QOS_FRAME_NUM*sizeof(struct vframe_qos_s));
- frame_qos_wr = 0;
- frame_qos_rd = 0;
- }
return 0;
error:
platform_device_unregister(vdec->dev);
pr_debug("vdec_release instance %p, total %d\n", vdec,
atomic_read(&vdec_core->vdec_nr));
- if (vdec->use_vfm_path) {
- kfree(frame_info_buf_in);
- frame_info_buf_in = NULL;
- kfree(frame_info_buf_out);
- frame_info_buf_out = NULL;
- frame_qos_wr = 0;
- frame_qos_rd = 0;
- }
vdec_destroy(vdec);
mutex_lock(&vdec_mutex);
vdec->tfn_ns = local_clock();
isr2tfn = vdec->tfn_ns - vdec->isr_ns;
if (isr2tfn > 10000000)
- pr_err("!!!!!!! %s vdec_isr to %s took %uns !!!\n",
+ pr_err("!!!!!!! %s vdec_isr to %s took %u ns !!!\n",
vdec->vf_provider_name, __func__, isr2tfn);
}
if (c->dev_threaded_isr) {
return ret;
}
+static ssize_t enable_mvdec_info_show(struct class *cla,
+ struct class_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", enable_mvdec_info);
+}
+
+static ssize_t enable_mvdec_info_store(struct class *cla,
+ struct class_attribute *attr,
+ const char *buf, size_t count)
+{
+ int r;
+ int val;
+
+ r = kstrtoint(buf, 0, &val);
+ if (r < 0)
+ return -EINVAL;
+ enable_mvdec_info = val;
+
+ return count;
+}
+
+
static ssize_t store_poweron_clock_level(struct class *class,
struct class_attribute *attr,
const char *buf, size_t size)
return sprintf(buf, "%d\n", keep_vdec_mem);
}
+
#ifdef VDEC_DEBUG_SUPPORT
static ssize_t store_debug(struct class *class,
struct class_attribute *attr,
__ATTR_RO(amrisc_regs),
__ATTR_RO(dump_trace),
__ATTR_RO(clock_level),
+ __ATTR(enable_mvdec_info, S_IRUGO | S_IWUSR | S_IWGRP,
+ enable_mvdec_info_show, enable_mvdec_info_store),
__ATTR(poweron_clock_level, S_IRUGO | S_IWUSR | S_IWGRP,
show_poweron_clock_level, store_poweron_clock_level),
__ATTR(dump_risc_mem, S_IRUGO | S_IWUSR | S_IWGRP,
return 0;
}
-void vdec_fill_frame_info(struct vframe_qos_s *vframe_qos, int debug)
+
+void vdec_set_vframe_comm(struct vdec_s *vdec, char *n)
{
- if (frame_info_buf_in == NULL) {
- pr_info("error,frame_info_buf_in is null\n");
- return;
- }
- if (frame_info_buf_out == NULL) {
- pr_info("error,frame_info_buf_out is null\n");
- return;
- }
- if (frame_qos_wr >= QOS_FRAME_NUM)
- frame_qos_wr = 0;
+ struct vdec_frames_s *mvfrm = vdec->mvfrm;
- if (frame_qos_wr >= QOS_FRAME_NUM ||
- frame_qos_wr < 0) {
- pr_info("error,index :%d is error\n", frame_qos_wr);
+ if (!mvfrm)
return;
- }
- if (frameinfo_flag == DISABLE_FRAME_INFO)
+
+ mvfrm->comm.vdec_id = vdec->id;
+
+ snprintf(mvfrm->comm.vdec_name, sizeof(mvfrm->comm.vdec_name)-1,
+ "%s", n);
+ mvfrm->comm.vdec_type = vdec->type;
+}
+EXPORT_SYMBOL(vdec_set_vframe_comm);
+
+void vdec_fill_vdec_frame(struct vdec_s *vdec, struct vframe_qos_s *vframe_qos,
+ struct vdec_info *vinfo,struct vframe_s *vf,
+ u32 hw_dec_time)
+{
+ u32 i;
+ struct vframe_counter_s *fifo_buf;
+ struct vdec_frames_s *mvfrm = vdec->mvfrm;
+
+ if (!mvfrm)
return;
+ fifo_buf = mvfrm->fifo_buf;
+
+ /* assume fps==60,mv->wr max value can support system running 828 days,
+ this is enough for us */
+ i = mvfrm->wr & (NUM_FRAME_VDEC-1); //find the slot num in fifo_buf
+ mvfrm->fifo_buf[i].decode_time_cost = hw_dec_time;
+ if (vframe_qos)
+ memcpy(&fifo_buf[i].qos, vframe_qos, sizeof(struct vframe_qos_s));
+ if (vinfo) {
+ memcpy(&fifo_buf[i].frame_width, &vinfo->frame_width,
+ ((char*)&vinfo->reserved[0] - (char*)&vinfo->frame_width));
+ }
+ if (vf) {
+ fifo_buf[i].vf_type = vf->type;
+ fifo_buf[i].signal_type = vf->signal_type;
+ fifo_buf[i].pts = vf->pts;
+ fifo_buf[i].pts_us64 = vf->pts_us64;
+ }
+ mvfrm->wr++;
+}
+EXPORT_SYMBOL(vdec_fill_vdec_frame);
+
+/* In this function,if we use copy_to_user, we may encounter sleep,
+which may block the vdec_fill_vdec_frame,this is not acceptable.
+So, we should use a tmp buffer(passed by caller) to get the content */
+u32 vdec_get_frame_vdec(struct vdec_s *vdec, struct vframe_counter_s *tmpbuf)
+{
+ u32 toread = 0;
+ u32 slot_rd;
+ struct vframe_counter_s *fifo_buf = NULL;
+ struct vdec_frames_s *mvfrm = NULL;
- if (frameinfo_flag == PRINT_FRAME_INFO) {
- pr_info("num %d size %d pts %d\n",
- vframe_qos->num,
- vframe_qos->size,
- vframe_qos->pts);
- pr_info("mv min_mv %d avg_mv %d max_mv %d\n",
- vframe_qos->min_mv,
- vframe_qos->avg_mv,
- vframe_qos->max_mv);
- pr_info("qp min_qp %d avg_qp %d max_qp %d\n",
- vframe_qos->min_qp,
- vframe_qos->avg_qp,
- vframe_qos->max_qp);
- pr_info("skip min_skip %d avg_skip %d max_skip %d\n",
- vframe_qos->min_skip,
- vframe_qos->avg_skip,
- vframe_qos->max_skip);
- }
- memcpy(&frame_info_buf_in[frame_qos_wr++],
- vframe_qos, sizeof(struct vframe_qos_s));
- if (frame_qos_wr >= QOS_FRAME_NUM)
- frame_qos_wr = 0;
-
- /*pr_info("frame_qos_wr:%d\n", frame_qos_wr);*/
-
-}
-EXPORT_SYMBOL(vdec_fill_frame_info);
-
-struct vframe_qos_s *vdec_get_qos_info(void)
-{
- int write_count = 0;
- int qos_wr = frame_qos_wr;
-
- if (frame_info_buf_in == NULL) {
- pr_info("error,frame_info_buf_in is null\n");
- return NULL;
- }
- if (frame_info_buf_out == NULL) {
- pr_info("error,frame_info_buf_out is null\n");
- return NULL;
+ /*
+ switch (version) {
+ case version_1:
+ f1();
+ case version_2:
+ f2();
+ default:
+ break;
}
+ */
+
+ if (!vdec)
+ return 0;
+ mvfrm = vdec->mvfrm;
+ if (!mvfrm)
+ return 0;
+ fifo_buf = &mvfrm->fifo_buf[0];
- memset(frame_info_buf_out, 0,
- QOS_FRAME_NUM*sizeof(struct vframe_qos_s));
- if (frame_qos_rd > qos_wr) {
- write_count = QOS_FRAME_NUM - frame_qos_rd;
- if (write_count > 0 && write_count <= QOS_FRAME_NUM) {
- memcpy(frame_info_buf_out, &frame_info_buf_in[0],
- write_count*sizeof(struct vframe_qos_s));
- if ((write_count + qos_wr) <= QOS_FRAME_NUM)
- memcpy(&frame_info_buf_out[write_count], frame_info_buf_in,
- qos_wr*sizeof(struct vframe_qos_s));
- else
- pr_info("get_qos_info:%d,out of range\n", __LINE__);
- } else
- pr_info("get_qos_info:%d,out of range\n", __LINE__);
- } else if (frame_qos_rd < qos_wr) {
- write_count = qos_wr - frame_qos_rd;
- if (write_count > 0 && write_count < QOS_FRAME_NUM)
- memcpy(frame_info_buf_out, &frame_info_buf_in[frame_qos_rd],
- (write_count)*sizeof(struct vframe_qos_s));
- else
- pr_info("get_qos_info:%d, out of range\n", __LINE__);
+ toread = mvfrm->wr - mvfrm->rd;
+ if (toread) {
+ if (toread >= NUM_FRAME_VDEC - QOS_FRAME_NUM) {
+ /* round the fifo_buf length happens, give QOS_FRAME_NUM for buffer */
+ mvfrm->rd = mvfrm->wr - (NUM_FRAME_VDEC - QOS_FRAME_NUM);
+ }
+
+ if (toread >= QOS_FRAME_NUM) {
+ toread = QOS_FRAME_NUM; //by default, we use this num
+ }
+
+ slot_rd = mvfrm->rd &( NUM_FRAME_VDEC-1); //In this case it equals to x%y
+ if (slot_rd + toread <= NUM_FRAME_VDEC) {
+ memcpy(tmpbuf, &fifo_buf[slot_rd], toread*sizeof(struct vframe_counter_s));
+ } else {
+ u32 exeed;
+ exeed = slot_rd + toread - NUM_FRAME_VDEC;
+ memcpy(tmpbuf, &fifo_buf[slot_rd], (NUM_FRAME_VDEC - slot_rd)*sizeof(struct vframe_counter_s));
+ memcpy(&tmpbuf[NUM_FRAME_VDEC-slot_rd], &fifo_buf[0], exeed*sizeof(struct vframe_counter_s));
+ }
+
+ mvfrm->rd += toread;
}
- /*
- pr_info("cnt:%d,size:%d,num:%d,rd:%d,wr:%d\n",
- wirte_count,
- frame_info_buf_out[0].size,
- frame_info_buf_out[0].num,
- frame_qos_rd,qos_wr);
- */
- frame_qos_rd = qos_wr;
- return frame_info_buf_out;
+ return toread;
}
-EXPORT_SYMBOL(vdec_get_qos_info);
-
+EXPORT_SYMBOL(vdec_get_frame_vdec);
RESERVEDMEM_OF_DECLARE(vdec, "amlogic, vdec-memory", vdec_mem_setup);
/*
unsigned int get_vdec_clk_config_settings(void);
void update_vdec_clk_config_settings(unsigned int config);
//unsigned int get_mmu_mode(void);//DEBUG_TMP
-extern void vdec_fill_frame_info(struct vframe_qos_s *vframe_qos, int debug);
+//extern void vdec_fill_frame_info(struct vframe_qos_s *vframe_qos, int debug);
+extern void vdec_fill_vdec_frame(struct vdec_s *vdec,
+ struct vframe_qos_s *vframe_qos,
+ struct vdec_info *vinfo,
+ struct vframe_s *vf, u32 hw_dec_time);
+extern void vdec_set_vframe_comm(struct vdec_s *vdec, char *n);
+
struct vdec_s;
enum vformat_t;
int parallel_dec;
volatile u64 isr_ns;
volatile u64 tfn_ns;
+ struct vdec_frames_s *mvfrm;
};
/* common decoder vframe provider name to use default vfm path */
void vdec_set_timestamp(struct vdec_s *vdec, u64 timestamp);
-extern struct vframe_qos_s *vdec_get_qos_info(void);
+extern u32 vdec_get_frame_vdec(struct vdec_s *vdec, struct vframe_counter_s *tmpbuf);
int vdec_get_frame_num(struct vdec_s *vdec);
int min_mv;
int avg_mv;
+ u32 hw_decode_time;
+ u32 frame_size2; // For frame base mode
bool vframe_bound;
} PIC_BUFFER_CONFIG;
}
}
+static inline void pbi_update_gvs(struct VP9Decoder_s *pbi)
+{
+ if (pbi->gvs->frame_height != frame_height) {
+ pbi->gvs->frame_width = frame_width;
+ pbi->gvs->frame_height = frame_height;
+ }
+ if (pbi->gvs->frame_dur != pbi->frame_dur) {
+ pbi->gvs->frame_dur = pbi->frame_dur;
+ if (pbi->frame_dur != 0)
+ pbi->gvs->frame_rate = 96000 / pbi->frame_dur;
+ else
+ pbi->gvs->frame_rate = -1;
+ }
+ pbi->gvs->status = pbi->stat | pbi->fatal_error;
+}
+
static int prepare_display_buf(struct VP9Decoder_s *pbi,
struct PIC_BUFFER_CONFIG_s *pic_config)
{
struct vframe_s *vf = NULL;
+ struct vdec_s *pvdec = hw_to_vdec(pbi);
int stream_offset = pic_config->stream_offset;
unsigned short slice_type = pic_config->slice_type;
u32 pts_valid = 0, pts_us64_valid = 0;
u32 pts_save;
u64 pts_us64_save;
- u32 frame_size;
+ u32 frame_size = 0;
if (debug & VP9_DEBUG_BUFMGR)
pr_info("%s index = %d\r\n", __func__, pic_config->index);
}
#ifdef MULTI_INSTANCE_SUPPORT
- if (vdec_frame_based(hw_to_vdec(pbi))) {
+ if (vdec_frame_based(pvdec)) {
vf->pts = pic_config->pts;
vf->pts_us64 = pic_config->pts64;
vf->timestamp = pic_config->timestamp;
&& (debug & VP9_DEBUG_NO_TRIGGER_FRAME) == 0
&& (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_TXLX))) {
inc_vf_ref(pbi, pic_config->index);
- decoder_do_frame_check(hw_to_vdec(pbi), vf);
+ decoder_do_frame_check(pvdec, vf);
kfifo_put(&pbi->display_q, (const struct vframe_s *)vf);
ATRACE_COUNTER(MODULE_NAME, vf->pts);
pbi->vf_pre_count++;
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
+ pbi_update_gvs(pbi);
/*count info*/
- gvs->frame_dur = pbi->frame_dur;
- vdec_count_info(gvs, 0, stream_offset);
-#endif
- hw_to_vdec(pbi)->vdec_fps_detec(hw_to_vdec(pbi)->id);
+ vdec_count_info(pbi->gvs, 0, stream_offset);
+ pbi->gvs->bit_rate = bit_depth_luma;
+ pbi->gvs->frame_data = bit_depth_chroma;
+ pbi->gvs->samp_cnt = get_double_write_mode(pbi);
+ vdec_fill_vdec_frame(pvdec, &pbi->vframe_qos, pbi->gvs,
+ vf, pic_config->hw_decode_time);
+ pvdec->vdec_fps_detec(pvdec->id);
if (without_display_mode == 0) {
vf_notify_receiver(pbi->provider_name,
VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
/*
#define SHOW_QOS_INFO
*/
- vframe_qos->size = framesize;
+ if (input_frame_based(hw_to_vdec(pbi)))
+ vframe_qos->size = frame->frame_size2;
+ else
+ vframe_qos->size = framesize;
vframe_qos->pts = pts;
#ifdef SHOW_QOS_INFO
vp9_print(pbi, 0, "slice:%d\n", frame->slice_type);
vframe_qos->min_skip);
#endif
vframe_qos->num++;
-
- if (pbi->frameinfo_enable)
- vdec_fill_frame_info(vframe_qos, 1);
}
/* only when we decoded one field or one frame,
static void get_picture_qos_info(struct VP9Decoder_s *pbi)
{
struct PIC_BUFFER_CONFIG_s *frame = &pbi->cur_buf->buf;
+ struct vdec_s *vdec = hw_to_vdec(pbi);
if (!frame)
return;
+ if (vdec->mvfrm) {
+ frame->frame_size2 = vdec->mvfrm->frame_size;
+ frame->hw_decode_time =
+ local_clock() - vdec->mvfrm->hw_decode_start;
+ }
if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) {
unsigned char a[3];
vstatus->error_count = 0;
vstatus->status = vp9->stat | vp9->fatal_error;
vstatus->frame_dur = vp9->frame_dur;
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
- vstatus->bit_rate = gvs->bit_rate;
- vstatus->frame_data = gvs->frame_data;
- vstatus->total_data = gvs->total_data;
- vstatus->frame_count = gvs->frame_count;
- vstatus->error_frame_count = gvs->error_frame_count;
- vstatus->drop_frame_count = gvs->drop_frame_count;
- vstatus->total_data = gvs->total_data;
- vstatus->samp_cnt = gvs->samp_cnt;
- vstatus->offset = gvs->offset;
+ vstatus->bit_rate = vp9->gvs->bit_rate;
+ vstatus->frame_data = vp9->gvs->frame_data;
+ vstatus->total_data = vp9->gvs->total_data;
+ vstatus->frame_count = vp9->gvs->frame_count;
+ vstatus->error_frame_count = vp9->gvs->error_frame_count;
+ vstatus->drop_frame_count = vp9->gvs->drop_frame_count;
+ vstatus->total_data = vp9->gvs->total_data;
+ vstatus->samp_cnt = vp9->gvs->samp_cnt;
+ vstatus->offset = vp9->gvs->offset;
snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name),
"%s", DRIVER_NAME);
-#endif
return 0;
}
pr_info("the struct of vdec status malloc failed.\n");
return -1;
}
+ vdec_set_vframe_comm(hw_to_vdec(pbi), DRIVER_NAME);
#ifdef DEBUG_PTS
pbi->pts_missed = 0;
pbi->pts_hit = 0;
WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, 0);
size = pbi->chunk->size +
(pbi->chunk->offset & (VDEC_FIFO_ALIGN - 1));
+ if (vdec->mvfrm)
+ vdec->mvfrm->frame_size = pbi->chunk->size;
}
WRITE_VREG(HEVC_DECODE_SIZE, size);
WRITE_VREG(HEVC_DECODE_COUNT, pbi->slice_idx);
PRINT_FLAG_VDEC_DETAIL, "%s mask %lx\r\n",
__func__, mask);
+ if (vdec->mvfrm)
+ vdec->mvfrm->hw_decode_start = local_clock();
run_count[pbi->index]++;
pbi->vdec_cb_arg = arg;
pbi->vdec_cb = callback;
if (iminor(inode) >= amstream_port_num)
return -ENODEV;
+ //pr_err("%s, port name %s\n", __func__, port->name);
+ //pr_err("%s [pid=%d,tgid=%d]\n", __func__, current->pid, current->tgid);
mutex_lock(&amstream_mutex);
if (port->type & PORT_TYPE_VIDEO) {
r = -EINVAL;
break;
case AMSTREAM_IOC_GET_QOSINFO:
+ case AMSTREAM_IOC_GET_MVDECINFO:
{
- struct av_param_qosinfo_t __user *uarg = (void *)arg;
- struct vframe_qos_s *qos_info = vdec_get_qos_info();
- if (this->type & PORT_TYPE_VIDEO) {
- if (qos_info != NULL && copy_to_user((void *)uarg->vframe_qos,
- qos_info,
- QOS_FRAME_NUM*sizeof(struct vframe_qos_s))) {
- r = -EFAULT;
+ u32 slots = 0;
+ u32 struct_size = 0;
+ int vdec_id = 0;
+ struct vdec_s *vdec = NULL;
+ struct vframe_counter_s tmpbuf[QOS_FRAME_NUM] = {0};
+ struct av_param_mvdec_t __user *uarg = (void *)arg;
+
+ if (AMSTREAM_IOC_GET_MVDECINFO == cmd) {
+ if (get_user(vdec_id, &uarg->vdec_id) < 0
+ || get_user(struct_size, &uarg->struct_size) < 0) {
+ r = -EFAULT;
+ break;
+ }
+ if (struct_size != sizeof(struct av_param_mvdec_t)) {
+ pr_err("pass in size %u != expected size %u\n",
+ struct_size, sizeof(struct av_param_mvdec_t));
+ pr_err("App using old structue,we will support it.\n");
+ //Here will add the compatibility for old structure when
+ //current struecture be substituded by newer structure.
+ //msleep(1000); let app handle it.
break;
}
}
+ vdec = vdec_get_vdec_by_id(vdec_id);
+ if (!vdec) {
+ r = 0;
+ break;
+ }
+
+ slots = vdec_get_frame_vdec(vdec, tmpbuf);
+ if (AMSTREAM_IOC_GET_MVDECINFO == cmd)
+ put_user(slots, &uarg->slots);
+ if (slots) {
+ if (AMSTREAM_IOC_GET_MVDECINFO == cmd) {
+ if (copy_to_user((void *)&uarg->comm,
+ &vdec->mvfrm->comm,
+ sizeof(struct vframe_comm_s))) {
+ r = -EFAULT;
+ break;
+ }
+ if (copy_to_user((void *)&uarg->minfo[0],
+ tmpbuf,
+ slots*sizeof(struct vframe_counter_s))) {
+ r = -EFAULT;
+ kfree(tmpbuf);
+ break;
+ }
+ }else { //For compatibility, only copy the qos
+ struct av_param_qosinfo_t __user *uarg = (void *)arg;
+ int i;
+ for (i=0; i<slots; i++)
+ if (copy_to_user((void *)&uarg->vframe_qos[i],
+ &tmpbuf[i].qos,
+ sizeof(struct vframe_qos_s))) {
+ r = -EFAULT;
+ break;
+ }
+ }
+ } else {
+ /*Vdec didn't produce item,wait for 10 ms to avoid user application
+ infinitely calling*/
+ //msleep(10); let user app handle it.
+ }
}
break;
default:
case AMSTREAM_IOC_SET_PTR:
case AMSTREAM_IOC_SYSINFO:
case AMSTREAM_IOC_GET_QOSINFO:
+ case AMSTREAM_IOC_GET_MVDECINFO:
r = amstream_do_ioctl_new(priv, cmd, arg);
break;
default: