media_module: frame crc32 check and dump yuv [1/2]

PD#SWPL-1738

Problem:
support frame crc32 check and dump yuv.

Solution:
1.do crc32 check for frames output from decoder, trigger
  yuv dump if it is not match with preset crc32 file;
2.trigger yuv dump before play or playing.

Verify:
u212

Change-Id: I5b2374d248698c4d6a4e67bc4dc18907d50ce2ea
Signed-off-by: shihong.zheng <shihong.zheng@amlogic.com>
This commit is contained in:
shihong.zheng
2019-01-08 16:55:49 +08:00
committed by Dongjin Kim
parent ea997a972b
commit 2f70df330d
12 changed files with 1430 additions and 20 deletions

View File

@@ -4425,7 +4425,7 @@ static int avs2_prepare_display_buf(struct AVS2Decoder_s *dec)
if (vf) {
set_vframe(dec, vf, pic, 0);
decoder_do_frame_check(vf, CORE_MASK_HEVC);
kfifo_put(&dec->display_q, (const struct vframe_s *)vf);
#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC

View File

@@ -242,6 +242,8 @@ static u32 max_refer_buf = 1;
static u32 decoder_force_reset;
static unsigned int no_idr_error_count;
static unsigned int no_idr_error_max = 60;
static unsigned int canvas_mode;
#ifdef SUPPORT_BAD_MACRO_BLOCK_REDUNDANCY
/* 0~128*/
static u32 bad_block_scale;
@@ -328,6 +330,7 @@ static bool block_display_q;
static int vh264_stop(int mode);
static s32 vh264_init(void);
#define DFS_HIGH_THEASHOLD 3
static bool pts_discontinue;
@@ -426,16 +429,19 @@ static inline int fifo_level(void)
void spec_set_canvas(struct buffer_spec_s *spec,
unsigned int width, unsigned int height)
{
canvas_config(spec->y_canvas_index,
int endian;
endian = (canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0;
canvas_config_ex(spec->y_canvas_index,
spec->y_addr,
width, height,
CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
CANVAS_ADDR_NOWRAP, canvas_mode, endian);
canvas_config_ex(spec->u_canvas_index,
spec->u_addr,
width, height / 2,
CANVAS_ADDR_NOWRAP, canvas_mode, endian);
canvas_config(spec->u_canvas_index,
spec->u_addr,
width, height / 2,
CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
return;
}
static void vh264_notify_work(struct work_struct *work)
@@ -900,7 +906,7 @@ static void vh264_set_params(struct work_struct *work)
int max_dpb_size, actual_dpb_size, max_reference_size;
int i, mb_mv_byte, ret;
unsigned long addr;
unsigned int post_canvas, buf_size;
unsigned int post_canvas, buf_size, endian;
unsigned int frame_mbs_only_flag;
unsigned int chroma_format_idc, chroma444, video_signal;
unsigned int crop_infor, crop_bottom, crop_right, level_idc;
@@ -1120,16 +1126,17 @@ static void vh264_set_params(struct work_struct *work)
buffer_spec[i].v_canvas_width = mb_width << 4;
buffer_spec[i].v_canvas_height = mb_height << 4;
canvas_config(128 + i * 2,
endian = (canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0;
canvas_config_ex(128 + i * 2,
buffer_spec[i].y_addr,
mb_width << 4, mb_height << 4,
CANVAS_ADDR_NOWRAP,
CANVAS_BLKMODE_32X32);
canvas_config(128 + i * 2 + 1,
canvas_mode, endian);
canvas_config_ex(128 + i * 2 + 1,
buffer_spec[i].u_addr,
mb_width << 4, mb_height << 3,
CANVAS_ADDR_NOWRAP,
CANVAS_BLKMODE_32X32);
canvas_mode, endian);
WRITE_VREG(ANC0_CANVAS_ADDR + i,
spec2canvas(&buffer_spec[i]));
} else {
@@ -1906,6 +1913,7 @@ static void vh264_isr(void)
decoder_bmmu_box_get_mem_handle(
mm_blk_handle,
VF_BUFFER_IDX(buffer_index));
decoder_do_frame_check(vf, CORE_MASK_VDEC_1);
if ((error_recovery_mode_use & 2) && error) {
kfifo_put(&recycle_q,
(const struct vframe_s *)vf);
@@ -1956,6 +1964,7 @@ static void vh264_isr(void)
decoder_bmmu_box_get_mem_handle(
mm_blk_handle,
VF_BUFFER_IDX(buffer_index));
decoder_do_frame_check(vf, CORE_MASK_VDEC_1);
if ((error_recovery_mode_use & 2) && error) {
kfifo_put(&recycle_q,
(const struct vframe_s *)vf);
@@ -2096,6 +2105,7 @@ static void vh264_isr(void)
p_last_vf = vf;
pts_discontinue = false;
iponly_early_mode = 1;
decoder_do_frame_check(vf, CORE_MASK_VDEC_1);
kfifo_put(&delay_display_q,
(const struct vframe_s *)vf);
WRITE_VREG(AV_SCRATCH_0, 0);
@@ -3031,6 +3041,7 @@ static int amvdec_h264_probe(struct platform_device *pdev)
mutex_unlock(&vh264_mutex);
return -EFAULT;
}
canvas_mode = pdata->canvas_mode;
tvp_flag = vdec_secure(pdata) ? CODEC_MM_FLAGS_TVP : 0;
if (pdata->sys_info)
vh264_amstream_dec_info = *pdata->sys_info;

View File

@@ -809,6 +809,7 @@ struct vdec_h264_hw_s {
int wait_for_udr_send;
#endif
u32 no_mem_count;
u32 canvas_mode;
bool is_used_v4l;
void *v4l2_ctx;
wait_queue_head_t wait_q;
@@ -1659,7 +1660,7 @@ static int alloc_one_buf_spec(struct vdec_h264_hw_s *hw, int i)
hw->buffer_spec[i].canvas_config[0].height =
hw->mb_height << 4;
hw->buffer_spec[i].canvas_config[0].block_mode =
CANVAS_BLKMODE_32X32;
hw->canvas_mode;
hw->buffer_spec[i].canvas_config[1].phy_addr =
hw->buffer_spec[i].u_addr;
@@ -1668,7 +1669,7 @@ static int alloc_one_buf_spec(struct vdec_h264_hw_s *hw, int i)
hw->buffer_spec[i].canvas_config[1].height =
hw->mb_height << 3;
hw->buffer_spec[i].canvas_config[1].block_mode =
CANVAS_BLKMODE_32X32;
hw->canvas_mode;
dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
"%s, alloc buf for bufspec%d\n",
__func__, i
@@ -1826,8 +1827,13 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx)
static void config_decode_canvas(struct vdec_h264_hw_s *hw, int i)
{
int blkmode = hw->is_used_v4l ? CANVAS_BLKMODE_LINEAR :
int endian = 0;
int blkmode = ((hw->canvas_mode == CANVAS_BLKMODE_LINEAR) ||
hw->is_used_v4l) ? CANVAS_BLKMODE_LINEAR :
CANVAS_BLKMODE_32X32;
if (blkmode == CANVAS_BLKMODE_LINEAR)
endian = 7;
canvas_config_ex(hw->buffer_spec[i].
y_canvas_index,
hw->buffer_spec[i].y_addr,
@@ -1835,7 +1841,7 @@ static void config_decode_canvas(struct vdec_h264_hw_s *hw, int i)
hw->mb_height << 4,
CANVAS_ADDR_NOWRAP,
blkmode,
hw->is_used_v4l ? 7 : 0);
endian);
if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32,
(1 << 11) | /* canvas_blk32_wr */
@@ -1852,7 +1858,7 @@ static void config_decode_canvas(struct vdec_h264_hw_s *hw, int i)
hw->mb_height << 3,
CANVAS_ADDR_NOWRAP,
blkmode,
hw->is_used_v4l ? 7 : 0);
endian);
if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32,
(1 << 11) |
@@ -2558,6 +2564,13 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame)
vf->duration = vf->duration/2;
}
if (i == 0) {
if (hw->mmu_enable)
decoder_do_frame_check(vf, CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
else
decoder_do_frame_check(vf, CORE_MASK_VDEC_1);
}
kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
hw->vf_pre_count++;
@@ -7660,6 +7673,8 @@ static int ammvdec_h264_probe(struct platform_device *pdev)
/* the ctx from v4l2 driver. */
hw->v4l2_ctx = pdata->private;
hw->canvas_mode = pdata->canvas_mode;
platform_set_drvdata(pdev, pdata);
hw->mmu_enable = 0;

View File

@@ -3660,7 +3660,7 @@ static void hevc_config_work_space_hw(struct hevc_state_s *hevc)
struct BuffInfo_s *buf_spec = hevc->work_space_buf;
if (get_dbg_flag(hevc))
hevc_print(hevc, 0,
hevc_print(hevc, H265_DEBUG_BUFMGR_MORE,
"%s %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
__func__,
buf_spec->ipp.buf_start,
@@ -7519,6 +7519,7 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
vf->type_original = vf->type;
pic->vf_ref = 1;
hevc->vf_pre_count++;
decoder_do_frame_check(vf, CORE_MASK_HEVC);
kfifo_put(&hevc->display_q, (const struct vframe_s *)vf);
if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT)

View File

@@ -3,3 +3,5 @@ decoder_common-objs += utils.o vdec.o vdec_input.o amvdec.o
decoder_common-objs += decoder_mmu_box.o decoder_bmmu_box.o
decoder_common-objs += config_parser.o secprot.o vdec_profile.o
decoder_common-objs += amstream_profile.o
decoder_common-objs += frame_check.o amlogic_fbc_hook.o

View File

@@ -0,0 +1,104 @@
/*
* drivers/amlogic/media/frame_provider/decoder/utils/amlogic_fbc_hook.c
*
* Copyright (C) 2016 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include "amlogic_fbc_hook.h"
static AMLOGIC_FBC_vframe_decoder_fun_t g_decoder_fun;
static AMLOGIC_FBC_vframe_encoder_fun_t g_encoder_fun;
int AMLOGIC_FBC_vframe_decoder(
void *dstyuv[4],
struct vframe_s *vf,
int out_format,
int flags)
{
if (g_decoder_fun) {
return g_decoder_fun(dstyuv,
vf,
out_format,
flags);
}
printk("no AMLOGIC_FBC_vframe_decoder ERRR!!\n");
return -1;
}
EXPORT_SYMBOL(AMLOGIC_FBC_vframe_decoder);
int AMLOGIC_FBC_vframe_encoder(
void *srcyuv[4],
void *dst_header,
void *dst_body,
int in_format,
int flags)
{
if (g_encoder_fun) {
return g_encoder_fun(
srcyuv,
dst_header,
dst_body,
in_format,
flags);
}
printk("no AMLOGIC_FBC_vframe_encoder ERRR!!\n");
return -1;
}
EXPORT_SYMBOL(AMLOGIC_FBC_vframe_encoder);
int register_amlogic_afbc_dec_fun(AMLOGIC_FBC_vframe_decoder_fun_t fn)
{
if (g_decoder_fun) {
pr_err("error!!,AMLOGIC_FBC dec have register\n");
return -1;
}
printk("register_amlogic_afbc_dec_fun\n");
g_decoder_fun = fn;
return 0;
}
EXPORT_SYMBOL(register_amlogic_afbc_dec_fun);
int register_amlogic_afbc_enc_fun(AMLOGIC_FBC_vframe_encoder_fun_t fn)
{
if (g_encoder_fun) {
pr_err("error!!,AMLOGIC_FBC enc have register\n");
return -1;
}
g_encoder_fun = fn;
return 0;
}
EXPORT_SYMBOL(register_amlogic_afbc_enc_fun);
int unregister_amlogic_afbc_dec_fun(void)
{
g_decoder_fun = NULL;
pr_err("unregister_amlogic_afbc_dec_fun\n");
return 0;
}
EXPORT_SYMBOL(unregister_amlogic_afbc_dec_fun);
int unregister_amlogic_afbc_enc_fun(void)
{
g_encoder_fun = NULL;
pr_err("unregister_amlogic_afbc_dec_fun\n");
return 0;
}
EXPORT_SYMBOL(unregister_amlogic_afbc_enc_fun);

View File

@@ -0,0 +1,55 @@
/*
* drivers/amlogic/media/frame_provider/decoder/utils/amlogic_fbc_hook.h
*
* Copyright (C) 2016 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#ifndef AMLGIC_FBC_HEADER___
#define AMLGIC_FBC_HEADER___
#include <linux/amlogic/media/vfm/vframe.h>
/*
unsigned short *planes[4],
unsigned char *buf,
unsigned *v2_head_buf // v2_head_buf_size=(((frame_info->mbw + 1)>>1)*2) * (((frame_info->mbh + 15)>>4)*16)
);
*/
int AMLOGIC_FBC_vframe_decoder(
void *dstyuv[4],
struct vframe_s *vf,
int out_format,
int flags);
int AMLOGIC_FBC_vframe_encoder(
void *srcyuv[4],
void *dst_header,
void *dst_body,
int in_format,
int flags);
typedef int (*AMLOGIC_FBC_vframe_decoder_fun_t)(
void **,
struct vframe_s *,
int,
int);
typedef int (*AMLOGIC_FBC_vframe_encoder_fun_t)(
void **,
void *,
void *,
int,
int);
int register_amlogic_afbc_dec_fun(AMLOGIC_FBC_vframe_decoder_fun_t fn);
int register_amlogic_afbc_enc_fun(AMLOGIC_FBC_vframe_encoder_fun_t fn);
int unregister_amlogic_afbc_dec_fun(void);
int unregister_amlogic_afbc_enc_fun(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,110 @@
/*
* drivers/amlogic/media/frame_provider/decoder/utils/frame_check.h
*
* Copyright (C) 2016 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#ifndef __FRAME_CHECK_H__
#define __FRAME_CHECK_H__
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/amlogic/media/vfm/vframe.h>
#include <linux/kfifo.h>
#define FRAME_CHECK
#define YUV_MAX_DUMP_NUM 20
#define SIZE_CRC 64
#define SIZE_CHECK_Q 128
struct pic_dump_t{
struct file *yuv_fp;
loff_t yuv_pos;
unsigned int start;
unsigned int num;
unsigned int end;
unsigned int dump_cnt;
unsigned int buf_size;
char *buf_addr;
};
struct pic_check_t{
struct file *check_fp;
loff_t check_pos;
struct file *compare_fp;
loff_t compare_pos;
unsigned int cmp_crc_cnt;
void *fbc_planes[4];
void *check_addr;
DECLARE_KFIFO(new_chk_q, char *, SIZE_CHECK_Q);
DECLARE_KFIFO(wr_chk_q, char *, SIZE_CHECK_Q);
};
struct pic_check_mgr_t{
int id;
int enable;
unsigned int frame_cnt;
/* pic info */
unsigned int canvas_w;
unsigned int canvas_h;
unsigned int size_y; //real size
unsigned int size_uv;
unsigned int size_pic;
unsigned int last_size_pic;
void *y_vaddr;
void *uv_vaddr;
ulong y_phyaddr;
ulong uv_phyaddr;
int file_cnt;
atomic_t work_inited;
struct work_struct frame_check_work;
struct pic_check_t pic_check;
struct pic_dump_t pic_dump;
};
int dump_yuv_trig(struct pic_check_mgr_t *mgr,
int id, int start, int num);
int decoder_do_frame_check(struct vframe_s *vf, int core_mask);
int frame_check_init(struct pic_check_mgr_t *mgr, int id);
void frame_check_exit(struct pic_check_mgr_t *mgr);
ssize_t frame_check_show(struct class *class,
struct class_attribute *attr, char *buf);
ssize_t frame_check_store(struct class *class,
struct class_attribute *attr,
const char *buf, size_t size);
ssize_t dump_yuv_show(struct class *class,
struct class_attribute *attr, char *buf);
ssize_t dump_yuv_store(struct class *class,
struct class_attribute *attr,
const char *buf, size_t size);
void vdec_frame_check_exit(struct vdec_s *vdec);
int vdec_frame_check_init(struct vdec_s *vdec);
#endif /* __FRAME_CHECK_H__ */

View File

@@ -68,6 +68,7 @@
#include <linux/amlogic/media/frame_sync/ptsserv.h>
#include "secprot.h"
#include "../../../common/chips/decoder_cpu_ver_info.h"
#include "frame_check.h"
static DEFINE_MUTEX(vdec_mutex);
@@ -88,7 +89,6 @@ static unsigned int clk_config;
static unsigned int debug;
static int hevc_max_reset_count;
#define MAX_INSTANCE_MUN 9
static int no_powerdown;
static int parallel_decode = 1;
@@ -1608,6 +1608,52 @@ static const char *get_dev_name(bool use_legacy_vdec, int format)
#endif
}
struct vdec_s *vdec_get_with_id(unsigned id)
{
struct vdec_s *vdec, *ret_vdec = NULL;
struct vdec_core_s *core = vdec_core;
unsigned long flags;
if (id >= MAX_INSTANCE_MUN)
return NULL;
flags = vdec_core_lock(vdec_core);
if (!list_empty(&core->connected_vdec_list)) {
list_for_each_entry(vdec, &core->connected_vdec_list, list) {
if (vdec->id == id) {
pr_info("searched avaliable vdec connected, id = %d\n", id);
ret_vdec = vdec;
break;
}
}
}
vdec_core_unlock(vdec_core, flags);
return ret_vdec;
}
void *vdec_get_active_vfc(int core_mask)
{
void *p = NULL;
struct vdec_s *vdec = vdec_core->last_vdec;
if (vdec_core->parallel_dec == 1) {
if (core_mask & CORE_MASK_VDEC_1)
vdec = vdec_core->active_vdec;
else if (core_mask & CORE_MASK_HEVC)
vdec = vdec_core->active_hevc;
else
vdec = vdec_core->last_vdec;
}
if (vdec == NULL)
return NULL;
p = &vdec->vfc;
return p;
}
/*
*register vdec_device
* create output, vfm or create ionvideo output
@@ -1666,6 +1712,12 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k)
id = vdec->id;
p->parallel_dec = parallel_decode;
vdec_core->parallel_dec = parallel_decode;
vdec->canvas_mode = CANVAS_BLKMODE_32X32;
#ifdef FRAME_CHECK
if (vdec_single(vdec))
vdec_core->last_vdec = vdec;
vdec_frame_check_init(vdec);
#endif
p->dev = platform_device_register_data(
&vdec_core->vdec_core_platform_device->dev,
dev_name,
@@ -1903,6 +1955,11 @@ void vdec_release(struct vdec_s *vdec)
|| (atomic_read(&vdec->inirq_thread_flag) > 0))
schedule();
#ifdef FRAME_CHECK
vdec_frame_check_exit(vdec);
if (vdec_single(vdec))
vdec_core->active_vdec = NULL;
#endif
platform_device_unregister(vdec->dev);
pr_debug("vdec_release instance %p, total %d\n", vdec,
atomic_read(&vdec_core->vdec_nr));
@@ -4018,6 +4075,12 @@ static struct class_attribute vdec_class_attrs[] = {
#ifdef VDEC_DEBUG_SUPPORT
__ATTR(debug, S_IRUGO | S_IWUSR | S_IWGRP,
show_debug, store_debug),
#endif
#ifdef FRAME_CHECK
__ATTR(dump_yuv, S_IRUGO | S_IWUSR | S_IWGRP,
dump_yuv_show, dump_yuv_store),
__ATTR(frame_check, S_IRUGO | S_IWUSR | S_IWGRP,
frame_check_show, frame_check_store),
#endif
__ATTR_NULL
};

View File

@@ -32,6 +32,7 @@
/*#define CONFIG_AM_VDEC_DV*/
#include "vdec_input.h"
#include "frame_check.h"
s32 vdec_dev_register(void);
s32 vdec_dev_unregister(void);
@@ -43,6 +44,8 @@ struct device *get_vdec_device(void);
int vdec_module_init(void);
void vdec_module_exit(void);
#define MAX_INSTANCE_MUN 9
#define VDEC_DEBUG_SUPPORT
#define DEC_FLAG_HEVC_WORKAROUND 0x01
@@ -180,6 +183,7 @@ struct vdec_s {
int flag;
int sched;
int need_more_data;
u32 canvas_mode;
struct completion inactive_done;
@@ -197,6 +201,8 @@ struct vdec_s {
/* input */
struct vdec_input_s input;
struct pic_check_mgr_t vfc;
/* mc cache */
u32 mc[4096 * 4];
bool mc_loaded;
@@ -431,4 +437,8 @@ int vdec_get_status(struct vdec_s *vdec);
void vdec_set_timestamp(struct vdec_s *vdec, u64 timestamp);
struct vdec_s *vdec_get_with_id(unsigned id);
void *vdec_get_active_vfc(int core_mask);
#endif /* VDEC_H */

View File

@@ -6878,6 +6878,7 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi,
&& (debug & VP9_DEBUG_NO_TRIGGER_FRAME) == 0
)) {
inc_vf_ref(pbi, pic_config->index);
decoder_do_frame_check(vf, CORE_MASK_HEVC);
kfifo_put(&pbi->display_q, (const struct vframe_s *)vf);
pbi->vf_pre_count++;
#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC