mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 04:48:04 +09:00
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:
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
Reference in New Issue
Block a user