media_module: mh264 [1/1]

PD#SWPL-6853

Problem:
	code section size for mh264 in ucode is nearly exhaust.

Solution:
	Parse sei data in c driver and get correct pic_struct for each field.
	ucode gerrit id: 54486
	ucode change id: I931ab485c4be0344c20648369dd32a172c542c3f

Verify:
	Verified T962X2-X301

Change-Id: I43f4a6b81b08c5f40ea82d881918fe0421dee7a6
Signed-off-by: Rong Zhang <rong.zhang@amlogic.com>
This commit is contained in:
Rong Zhang
2019-04-09 10:58:03 +08:00
committed by Dongjin Kim
parent 8dd9f4c08b
commit e299d162c4
4 changed files with 321 additions and 46 deletions

View File

@@ -385,6 +385,18 @@ void slice_prepare(struct h264_dpb_stru *p_H264_Dpb,
pSlice->structure = (p_H264_Dpb->
dpb_param.l.data[NEW_PICTURE_STRUCTURE] == 3) ?
FRAME : p_H264_Dpb->dpb_param.l.data[NEW_PICTURE_STRUCTURE];
if (pSlice->structure == FRAME) {
pSlice->field_pic_flag = 0;
pSlice->bottom_field_flag = 0;
} else {
pSlice->field_pic_flag = 1;
if (pSlice->structure == TOP_FIELD)
pSlice->bottom_field_flag = 0;
else
pSlice->bottom_field_flag = 1;
}
pSlice->pic_struct = p_H264_Dpb->dpb_param.l.data[PICTURE_STRUCT];
sps->num_ref_frames = p_H264_Dpb->
dpb_param.l.data[MAX_REFERENCE_FRAME_NUM];
sps->profile_idc =
@@ -1045,6 +1057,14 @@ static void init_picture(struct h264_dpb_stru *p_H264_Dpb,
currSlice->picture_structure_mmco);
}
if (currSlice->pic_struct >= 3)
dec_picture->pic_struct = currSlice->pic_struct + 2;
else if (currSlice->pic_struct == 1)
dec_picture->pic_struct = PIC_TOP_BOT;
else if (currSlice->pic_struct >= 2)
dec_picture->pic_struct = PIC_BOT_TOP;
else
dec_picture->pic_struct = PIC_INVALID;
}
void dump_pic(struct h264_dpb_stru *p_H264_Dpb)

View File

@@ -42,6 +42,14 @@
#define DISABLE_ERROR_HANDLE 0x10000
#define DEBUG_DUMP_STAT 0x80000
#define PIC_SINGLE_FRAME 0
#define PIC_TOP_BOT_TOP 1
#define PIC_BOT_TOP_BOT 2
#define PIC_DOUBLE_FRAME 3
#define PIC_TRIPLE_FRAME 4
#define PIC_TOP_BOT 5
#define PIC_BOT_TOP 6
#define PIC_INVALID 7
#define MVC_EXTENSION_ENABLE 0
#define PRINTREFLIST 0
@@ -78,6 +86,9 @@
#define H264_FIND_NEXT_DVEL_NAL 0x51
#define H264_AUX_DATA_READY 0x52
#define H264_SEI_DATA_READY 0x53
#define H264_SEI_DATA_DONE 0x54
/* 0x8x, search state*/
#define H264_STATE_SEARCH_AFTER_SPS 0x80
#define H264_STATE_SEARCH_AFTER_PPS 0x81
@@ -515,6 +526,7 @@ struct Slice {
unsigned char dec_ref_pic_marking_buffer_valid;
struct DecRefPicMarking_s
dec_ref_pic_marking_buffer[DEC_REF_PIC_MARKING_BUFFER_NUM_MAX];
int pic_struct;
};
struct OldSliceParams {
@@ -693,6 +705,8 @@ struct StorablePicture {
u64 pts64;
u64 timestamp;
unsigned char data_flag;
int pic_struct;
/* picture qos infomation*/
int frame_size;
int max_qp;

View File

@@ -81,6 +81,7 @@
#define CHECK_INTERVAL (HZ/100)
#define SEI_DATA_SIZE (8*1024)
#define SEI_ITU_DATA_SIZE (4*1024)
#define RATE_MEASURE_NUM 8
@@ -354,14 +355,7 @@ static inline bool close_to(int a, int b, int m)
/*#define V_BUF_ADDR_OFFSET (0x13e000)*/
u32 V_BUF_ADDR_OFFSET = 0x200000;
#define DCAC_READ_MARGIN (64 * 1024)
#define PIC_SINGLE_FRAME 0
#define PIC_TOP_BOT_TOP 1
#define PIC_BOT_TOP_BOT 2
#define PIC_DOUBLE_FRAME 3
#define PIC_TRIPLE_FRAME 4
#define PIC_TOP_BOT 5
#define PIC_BOT_TOP 6
#define PIC_INVALID 7
#define EXTEND_SAR 0xff
#define BUFSPEC_POOL_SIZE 64
@@ -613,6 +607,11 @@ struct vdec_h264_hw_s {
u32 suffix_aux_size;
void *aux_addr;
dma_addr_t aux_phy_addr;
/* buffer for store all sei data */
void *sei_data_buf;
u32 sei_data_len;
/* buffer for storing one itu35 recored */
void *sei_itu_data_buf;
u32 sei_itu_data_len;
@@ -4949,6 +4948,211 @@ static bool is_buffer_available(struct vdec_s *vdec)
return buffer_available;
}
#define AUX_TAG_SEI 0x2
#define SEI_BUFFERING_PERIOD 0
#define SEI_PicTiming 1
#define SEI_USER_DATA 4
#define SEI_RECOVERY_POINT 6
/*
*************************************************************************
* Function:Reads bits from the bitstream buffer
* Input:
byte buffer[]
containing sei message data bits
int totbitoffset
bit offset from start of partition
int bytecount
total bytes in bitstream
int numbits
number of bits to read
* Output:
int *info
* Return:
-1: failed
> 0: the count of bit read
* Attention:
*************************************************************************
*/
static int get_bits(unsigned char buffer[],
int totbitoffset,
int *info,
int bytecount,
int numbits)
{
register int inf;
long byteoffset;
int bitoffset;
int bitcounter = numbits;
byteoffset = totbitoffset / 8;
bitoffset = 7 - (totbitoffset % 8);
inf = 0;
while (numbits) {
inf <<= 1;
inf |= (buffer[byteoffset] & (0x01 << bitoffset)) >> bitoffset;
numbits--;
bitoffset--;
if (bitoffset < 0) {
byteoffset++;
bitoffset += 8;
if (byteoffset > bytecount)
return -1;
}
}
*info = inf;
return bitcounter;
}
static int parse_one_sei_record(struct vdec_h264_hw_s *hw,
u8 *sei_data_buf,
u8 *sei_data_buf_end)
{
int payload_type;
int payload_size;
u8 *p_sei;
int temp;
int bit_offset;
int read_size;
struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
p_sei = sei_data_buf;
read_size = 0;
payload_type = 0;
do {
if (p_sei >= sei_data_buf_end)
return read_size;
payload_type += *p_sei;
read_size++;
} while (*p_sei++ == 255);
payload_size = 0;
do {
if (p_sei >= sei_data_buf_end)
return read_size;
payload_size += *p_sei;
read_size++;
} while (*p_sei++ == 255);
if (p_sei + payload_size > sei_data_buf_end) {
dpb_print(DECODE_ID(hw), 0,
"%s: payload_type = %d, payload_size = %d is over\n",
__func__, payload_type, payload_size);
return read_size;
}
bit_offset = 0;
if (payload_size <= 0) {
dpb_print(DECODE_ID(hw), 0,
"%s warning: this is a null sei message for payload_type = %d\n",
__func__, payload_type);
return read_size;
}
switch (payload_type) {
case SEI_BUFFERING_PERIOD:
break;
case SEI_PicTiming:
if (p_H264_Dpb->vui_status & 0xc) {
int cpb_removal_delay;
int dpb_output_delay;
u32 delay_len;
delay_len = p_H264_Dpb->dpb_param.l.data[DELAY_LENGTH];
cpb_removal_delay
= (delay_len & 0x1F) + 1;
dpb_output_delay
= ((delay_len >> 5) & 0x1F) + 1;
get_bits(p_sei, bit_offset,
&temp, payload_size,
dpb_output_delay+cpb_removal_delay);
bit_offset += dpb_output_delay+cpb_removal_delay;
}
if (p_H264_Dpb->vui_status & 0x10) {
get_bits(p_sei, bit_offset, &temp, payload_size, 4);
bit_offset += 4;
p_H264_Dpb->dpb_param.l.data[PICTURE_STRUCT] = temp;
}
break;
case SEI_USER_DATA:
if (enable_itu_t35) {
int i;
int j;
int data_len;
u8 *user_data_buf;
user_data_buf
= hw->sei_itu_data_buf + hw->sei_itu_data_len;
/* user data length should be align with 8 bytes,
if not, then padding with zero*/
for (i = 0; i < payload_size; i += 8) {
for (j = 0; j < 8; j++) {
int index;
index = i+7-j;
if (index >= payload_size)
user_data_buf[i+j] = 0;
else
user_data_buf[i+j]
= p_sei[i+7-j];
}
}
data_len = payload_size;
if (payload_size % 8)
data_len = ((payload_size + 8) >> 3) << 3;
hw->sei_itu_data_len += data_len;
/*
dpb_print(DECODE_ID(hw), 0,
"%s: user data, and len = %d:\n",
__func__, hw->sei_itu_data_len);
*/
}
break;
case SEI_RECOVERY_POINT:
p_H264_Dpb->dpb_param.l.data[RECOVERY_POINT] = 1;
break;
}
return read_size + payload_size;
}
static void parse_sei_data(struct vdec_h264_hw_s *hw,
u8 *sei_data_buf,
int len)
{
char *p_sei;
char *p_sei_end;
int parsed_size;
int read_size;
p_sei = sei_data_buf;
p_sei_end = p_sei + len;
parsed_size = 0;
while (parsed_size < len) {
read_size = parse_one_sei_record(hw, p_sei, p_sei_end);
p_sei += read_size;
parsed_size += read_size;
if (*p_sei == 0x80) {
p_sei++;
parsed_size++;
}
}
}
static void check_decoded_pic_error(struct vdec_h264_hw_s *hw)
{
struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
@@ -5166,6 +5370,8 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq)
data_low,
data_hight);*/
parse_sei_data(hw, hw->sei_data_buf, hw->sei_data_len);
if (hw->config_bufmgr_done == 0) {
hw->dec_result = DEC_RESULT_DONE;
vdec_schedule_work(&hw->work);
@@ -5661,63 +5867,72 @@ send_again:
hw->dec_result = DEC_RESULT_DONE;
vdec_schedule_work(&hw->work);
return IRQ_HANDLED;
}
if (READ_VREG(AV_SCRATCH_G) == 1) {
} else if (dec_dpb_status == H264_SEI_DATA_READY) {
int aux_data_len;
aux_data_len =
(READ_VREG(H264_AUX_DATA_SIZE) >> 16) << 4;
if (aux_data_len > SEI_ITU_DATA_SIZE * 2) {
if (aux_data_len > SEI_DATA_SIZE) {
dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
"itu data size more than 4K: %d, discarded it\n",
aux_data_len);
aux_data_len = 0;
"sei data size more than 4K: %d, discarded it\n",
hw->sei_itu_data_len);
hw->sei_itu_data_len = 0;
}
if (aux_data_len != 0) {
u8 *trans_data_buf;
u8 *sei_data_buf;
u32 temp;
u32 *pswap_data;
int new_size;
int bContinue;
u8 swap_byte;
dma_sync_single_for_cpu(
amports_get_dma_device(),
hw->aux_phy_addr,
hw->prefix_aux_size + hw->suffix_aux_size,
DMA_FROM_DEVICE);
amports_get_dma_device(),
hw->aux_phy_addr,
hw->prefix_aux_size + hw->suffix_aux_size,
DMA_FROM_DEVICE);
#if 0
dump_aux_buf(hw);
#endif
trans_data_buf = (u8 *)hw->aux_addr;
new_size = hw->sei_itu_data_len + aux_data_len / 2;
bContinue = 1;
if (new_size > SEI_ITU_DATA_SIZE) {
dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
"itu data size over (0x%x, 0x%x), discarded it\n",
if (trans_data_buf[7] == AUX_TAG_SEI) {
int left_len;
sei_data_buf = (u8 *)hw->sei_data_buf
+ hw->sei_data_len;
left_len = SEI_DATA_SIZE - hw->sei_data_len;
if (aux_data_len/2 <= left_len) {
for (i = 0; i < aux_data_len/2; i++)
sei_data_buf[i]
= trans_data_buf[i*2];
aux_data_len = aux_data_len / 2;
for (i = 0; i < aux_data_len; i = i+4) {
swap_byte = sei_data_buf[i];
sei_data_buf[i]
= sei_data_buf[i+3];
sei_data_buf[i+3] = swap_byte;
swap_byte = sei_data_buf[i+1];
sei_data_buf[i+1]
= sei_data_buf[i+2];
sei_data_buf[i+2] = swap_byte;
}
for (i = aux_data_len-1; i >= 0; i--)
if (sei_data_buf[i] != 0)
break;
hw->sei_data_len += i+1;
} else
dpb_print(DECODE_ID(hw),
PRINT_FLAG_ERROR,
"sei data size %d and more than left space: %d, discarded it\n",
hw->sei_itu_data_len,
new_size);
bContinue = 0;
}
if (bContinue) {
sei_data_buf = (u8 *)hw->sei_itu_data_buf + hw->sei_itu_data_len;
for (i = 0; i < aux_data_len/2; i++)
sei_data_buf[i] = trans_data_buf[i*2];
hw->sei_itu_data_len += aux_data_len / 2;
pswap_data = (u32 *)sei_data_buf;
for (i = 0; i < aux_data_len/8; i = i+2) {
temp = pswap_data[i];
pswap_data[i] = pswap_data[i+1];
pswap_data[i+1] = temp;
}
left_len);
}
}
WRITE_VREG(AV_SCRATCH_G, 0);
WRITE_VREG(DPB_STATUS_REG, H264_SEI_DATA_DONE);
return IRQ_HANDLED;
}
@@ -6561,10 +6776,21 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw)
hw->aux_addr = NULL;
return -1;
}
hw->sei_data_buf = kmalloc(SEI_DATA_SIZE, GFP_KERNEL);
if (hw->sei_data_buf == NULL) {
pr_err("%s: failed to alloc sei itu data buffer\n",
__func__);
return -1;
}
hw->sei_itu_data_buf = kmalloc(SEI_ITU_DATA_SIZE, GFP_KERNEL);
if (hw->sei_itu_data_buf == NULL) {
pr_err("%s: failed to alloc sei itu data buffer\n",
__func__);
kfree(hw->aux_addr);
hw->aux_addr = NULL;
kfree(hw->sei_data_buf);
hw->sei_data_buf = NULL;
return -1;
}
@@ -6574,6 +6800,13 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw)
if (!hw->sei_user_data_buffer) {
pr_info("%s: Can not allocate sei_data_buffer\n",
__func__);
kfree(hw->aux_addr);
hw->aux_addr = NULL;
kfree(hw->sei_data_buf);
hw->sei_data_buf = NULL;
kfree(hw->sei_itu_data_buf);
hw->sei_itu_data_buf = NULL;
return -1;
}
hw->sei_user_data_wp = 0;
@@ -6641,6 +6874,10 @@ static int vh264_stop(struct vdec_h264_hw_s *hw)
kfree(hw->aux_addr);
hw->aux_addr = NULL;
}
if (hw->sei_data_buf != NULL) {
kfree(hw->sei_data_buf);
hw->sei_data_buf = NULL;
}
if (hw->sei_itu_data_buf != NULL) {
kfree(hw->sei_itu_data_buf);
hw->sei_itu_data_buf = NULL;
@@ -7054,6 +7291,9 @@ static void vmh264_udc_fill_vpts(struct vdec_h264_hw_s *hw,
p_userdata_rec->rec_len = data_length;
hw->userdata_info.last_wp = wp;
p_userdata_rec->meta_info.flags |=
p_H264_Dpb->mVideo.dec_picture->pic_struct << 12;
hw->wait_for_udr_send = 1;
schedule_work(&hw->user_data_ready_work);
#endif
@@ -7872,6 +8112,7 @@ static void run(struct vdec_s *vdec, unsigned long mask,
config_decode_mode(hw);
vdec_enable_input(vdec);
WRITE_VREG(NAL_SEARCH_CTL, 0);
hw->sei_data_len = 0;
if (enable_itu_t35)
WRITE_VREG(NAL_SEARCH_CTL, READ_VREG(NAL_SEARCH_CTL) | 0x1);
if (!hw->init_flag) {

Binary file not shown.