mirror of
https://gitee.com/Vancouver2017/luban-lite-t3e-pro.git
synced 2025-12-14 10:28:54 +00:00
V1.0.6
This commit is contained in:
@@ -603,6 +603,33 @@ int fm_decoder_frame_to_render(struct frame_manager *fm, struct frame *frame, in
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fm_decoder_reclaim_all_used_frame(struct frame_manager *fm)
|
||||
{
|
||||
int i;
|
||||
struct frame_impl *frm_impl;
|
||||
|
||||
aicos_mutex_take(fm->lock, AICOS_WAIT_FOREVER);
|
||||
|
||||
for (i = 0; i < fm->frame_count; i++) {
|
||||
frm_impl = &fm->frame_node[i];
|
||||
logd("frame ref_count: %d, id: %d, used_by_decoder: %d", frm_impl->ref_count,
|
||||
frm_impl->node_id, frm_impl->used_by_decoder);
|
||||
if (frm_impl->used_by_decoder) {
|
||||
mpp_list_del_init(&frm_impl->list);
|
||||
mpp_list_add_tail(&frm_impl->list, &fm->empty_list);
|
||||
fm->empty_num++;
|
||||
frm_impl->used_by_decoder = 0;
|
||||
frm_impl->used_by_display = 0;
|
||||
frm_impl->displayed = 1;
|
||||
frm_impl->ref_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
aicos_mutex_give(fm->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct frame *fm_get_frame_by_id(struct frame_manager *fm, int id)
|
||||
{
|
||||
struct frame_impl *frm_impl;
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Artinchip Technology Co. Ltd
|
||||
*
|
||||
* author: <qi.xu@artinchip.com>
|
||||
* Desc: h264 decoder interface
|
||||
*
|
||||
*/
|
||||
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* author: <qi.xu@artinchip.com>
|
||||
* Desc: h264 decoder interface
|
||||
*
|
||||
*/
|
||||
|
||||
#define LOG_TAG "h264_decoder"
|
||||
#include <stdlib.h>
|
||||
@@ -55,7 +57,7 @@ static int find_startcode(unsigned char* buf, int len)
|
||||
* @len: [in] length of input buffer
|
||||
* return: remove bytes number
|
||||
*/
|
||||
static int remove_eptb(unsigned char* dst, int* offset, unsigned char* src, int len )
|
||||
static int remove_eptb(unsigned char* dst, int* offset, unsigned char* src, int len)
|
||||
{
|
||||
int si = 0;
|
||||
int di = 0;
|
||||
@@ -159,8 +161,7 @@ static int procese_nalu(struct h264_dec_ctx *s, unsigned char* buf, int len, int
|
||||
|
||||
s->idr_pic_flag = 0;
|
||||
switch(s->nal_unit_type) {
|
||||
case NAL_TYPE_IDR:
|
||||
{
|
||||
case NAL_TYPE_IDR: {
|
||||
logd("idr frame");
|
||||
s->idr_pic_flag = 1;
|
||||
s->prev_frame_num = s->prev_frame_num_offset = 0;
|
||||
@@ -174,8 +175,7 @@ static int procese_nalu(struct h264_dec_ctx *s, unsigned char* buf, int len, int
|
||||
for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++)
|
||||
s->frame_info.last_pocs[i] = INT_MIN;
|
||||
}
|
||||
case NAL_TYPE_SLICE:
|
||||
{
|
||||
case NAL_TYPE_SLICE: {
|
||||
logd("decode slice");
|
||||
ret = h264_decode_slice_header(s);
|
||||
if (ret) {
|
||||
@@ -183,7 +183,7 @@ static int procese_nalu(struct h264_dec_ctx *s, unsigned char* buf, int len, int
|
||||
}
|
||||
|
||||
ret = decode_slice(s);
|
||||
if(ret) {
|
||||
if (ret) {
|
||||
loge("decode_slice error, ret: %d", ret);
|
||||
error_flag = 1;
|
||||
ret = DEC_ERR_NOT_SUPPORT;
|
||||
@@ -192,18 +192,22 @@ static int procese_nalu(struct h264_dec_ctx *s, unsigned char* buf, int len, int
|
||||
*use_len = len;
|
||||
break;
|
||||
}
|
||||
case NAL_TYPE_SPS:
|
||||
{
|
||||
case NAL_TYPE_SPS: {
|
||||
logd("sps");
|
||||
ret = h264_decode_sps(s);
|
||||
if (ret) {
|
||||
s->error = H264_DECODER_ERROR_SPS;
|
||||
}
|
||||
*use_len = read_bits_count(&s->gb) / 8 +
|
||||
s->sc_byte_offset + s->remove_bytes;
|
||||
break;
|
||||
}
|
||||
case NAL_TYPE_PPS:
|
||||
{
|
||||
case NAL_TYPE_PPS: {
|
||||
logd("pps");
|
||||
ret = h264_decode_pps(s);
|
||||
if (ret) {
|
||||
s->error = H264_DECODER_ERROR_PPS;
|
||||
}
|
||||
*use_len = read_bits_count(&s->gb) / 8 +
|
||||
s->sc_byte_offset + s->remove_bytes;
|
||||
break;
|
||||
@@ -215,14 +219,17 @@ static int procese_nalu(struct h264_dec_ctx *s, unsigned char* buf, int len, int
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(s->nal_unit_type != NAL_TYPE_IDR && s->nal_unit_type != NAL_TYPE_SLICE)
|
||||
if(s->nal_unit_type != NAL_TYPE_IDR && s->nal_unit_type != NAL_TYPE_SLICE) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
s->prev_poc_lsb = s->sh.poc_lsb;
|
||||
s->prev_poc_msb = s->sh.poc_msb;
|
||||
s->prev_frame_num = s->sh.frame_num;
|
||||
s->prev_frame_num_offset = s->frame_num_offset;
|
||||
|
||||
s->nal_ref_idc_pre = s->nal_ref_idc;
|
||||
if ((s->decode_mb_num >= s->mbs_in_pic || error_flag) && s->nal_ref_idc) {
|
||||
// execute_ref_pic
|
||||
execute_ref_pic_marking(s);
|
||||
@@ -274,16 +281,16 @@ int __h264_decode_frame(struct mpp_decoder *ctx)
|
||||
struct h264_dec_ctx *s = (struct h264_dec_ctx*)ctx;
|
||||
s->slice_offset = 0;
|
||||
|
||||
//* 1. get a packet data
|
||||
// 1. get a packet data
|
||||
s->curr_packet = pm_dequeue_ready_packet(s->decoder.pm);
|
||||
if(s->curr_packet == NULL) {
|
||||
loge("pm_dequeue_ready_packet error, ready_packet num: %d", pm_get_ready_packet_num(s->decoder.pm));
|
||||
return DEC_NO_READY_PACKET;
|
||||
}
|
||||
|
||||
s->error = H264_DECODER_ERROR_NONE;
|
||||
s->eos = s->curr_packet->flag & PACKET_FLAG_EOS;
|
||||
|
||||
//* 2. process extra data
|
||||
// 2. process extra data
|
||||
if(s->curr_packet->flag & PACKET_FLAG_EXTRA_DATA) {
|
||||
s->avcc = 1;
|
||||
ret = process_extradata(s, s->curr_packet->data, s->curr_packet->size);
|
||||
@@ -291,18 +298,14 @@ int __h264_decode_frame(struct mpp_decoder *ctx)
|
||||
return ret;
|
||||
}
|
||||
|
||||
//* 3. process this packet
|
||||
// 3. process this packet
|
||||
while (s->slice_offset+4 < s->curr_packet->size) {
|
||||
int use_len = 0;
|
||||
unsigned char* pos = s->curr_packet->data + s->slice_offset;
|
||||
ret = procese_nalu(s, s->curr_packet->data + s->slice_offset,
|
||||
s->curr_packet->size - s->slice_offset, &use_len);
|
||||
if(ret) {
|
||||
if(ret == DEC_NO_EMPTY_FRAME)
|
||||
pm_reclaim_ready_packet(s->decoder.pm, s->curr_packet);
|
||||
else
|
||||
pm_enqueue_empty_packet(s->decoder.pm, s->curr_packet);
|
||||
return ret;
|
||||
if (ret) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (s->avcc)
|
||||
@@ -313,14 +316,20 @@ int __h264_decode_frame(struct mpp_decoder *ctx)
|
||||
logi("offset: %d 0x%x", s->slice_offset, s->slice_offset);
|
||||
}
|
||||
|
||||
pm_enqueue_empty_packet(s->decoder.pm, s->curr_packet);
|
||||
|
||||
if(s->curr_packet->flag & PACKET_FLAG_EOS) {
|
||||
render_all_delayed_frame(s);
|
||||
}
|
||||
|
||||
if (s->error == H264_DECODER_ERROR_NOEMPTYFRAME) {
|
||||
pm_reclaim_ready_packet(s->decoder.pm, s->curr_packet);
|
||||
} else {
|
||||
pm_enqueue_empty_packet(s->decoder.pm, s->curr_packet);
|
||||
}
|
||||
|
||||
|
||||
logd("__h264_decode_frame end");
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int __h264_decode_destroy(struct mpp_decoder *ctx)
|
||||
@@ -370,6 +379,10 @@ int __h264_decode_reset(struct mpp_decoder *ctx)
|
||||
render_all_delayed_frame(s);
|
||||
// refresh reference frame
|
||||
reference_refresh(s);
|
||||
|
||||
//force reclaim all frame used by decoder avoid frame lost
|
||||
fm_decoder_reclaim_all_used_frame(s->decoder.fm);
|
||||
|
||||
s->next_output_poc = INT_MIN;
|
||||
for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++)
|
||||
s->frame_info.last_pocs[i] = INT_MIN;
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Artinchip Technology Co. Ltd
|
||||
*
|
||||
* author: <qi.xu@artinchip.com>
|
||||
* Desc: h264 decoder contxet
|
||||
*
|
||||
*/
|
||||
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* author: <qi.xu@artinchip.com>
|
||||
* Desc: h264 decoder contxet
|
||||
*
|
||||
*/
|
||||
#ifndef _H264_DECODER_H_
|
||||
#define _H264_DECODER_H_
|
||||
|
||||
@@ -36,6 +38,25 @@
|
||||
// extra frames for picture reorder
|
||||
#define MAX_B_FRAMES 2
|
||||
|
||||
/*
|
||||
planing to perform appropriate error handling base on error indicators
|
||||
*/
|
||||
enum h264_decoder_error{
|
||||
H264_DECODER_ERROR_NONE = 0,
|
||||
H264_DECODER_ERROR_SLICETYPE,
|
||||
H264_DECODER_ERROR_SLICENUM,
|
||||
H264_DECODER_ERROR_SPS,
|
||||
H264_DECODER_ERROR_PPS,
|
||||
H264_DECODER_ERROR_PICTURESTRUCTUTE,
|
||||
H264_DECODER_ERROR_NOEMPTYFRAME,
|
||||
H264_DECODER_ERROR_REFPICMARKING,
|
||||
H264_DECODER_ERROR_DEBLOCKINGFILTER,
|
||||
H264_DECODER_ERROR_HARD,
|
||||
H264_DECODER_ERROR_REFLISTREORDERING,
|
||||
H264_DECODER_ERROR_CHECKLASTFRAME,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Memory management control operation opcode.
|
||||
*/
|
||||
@@ -76,127 +97,127 @@ enum NAL_TYPE
|
||||
|
||||
struct pred_weight_table
|
||||
{
|
||||
int luma_log2_weight_denom;
|
||||
int chroma_log2_weight_denom;
|
||||
int wp_weight[2][32][3]; // [list][index][component], range(-128~127)
|
||||
int wp_offset[2][32][3]; // [list][index][component], range(-128~127)
|
||||
int luma_log2_weight_denom;
|
||||
int chroma_log2_weight_denom;
|
||||
int wp_weight[2][32][3]; // [list][index][component], range(-128~127)
|
||||
int wp_offset[2][32][3]; // [list][index][component], range(-128~127)
|
||||
};
|
||||
|
||||
struct h264_sps_info
|
||||
{
|
||||
u8 mbaff;
|
||||
u8 frame_mbs_only_flag;
|
||||
u8 direct_8x8_inference_flag;
|
||||
u8 scaling_matrix_present_flag; // u(1)
|
||||
u32 level_idc;
|
||||
u32 profile_idc;
|
||||
u32 constraint_set_flags;
|
||||
u32 chroma_format_idc; // use(v)
|
||||
u8 scaling_matrix4[6][16];
|
||||
u8 scaling_matrix8[2][64];
|
||||
int log2_max_frm_num; // ue(v), log2_max_frm_num_minus4 + 4
|
||||
int poc_type;
|
||||
// poc_type == 0
|
||||
int log2_max_poc_lsb; // ue(v), log2_max_pic_order_cnt_lsb_minus4 + 4
|
||||
// poc_type == 1
|
||||
int delta_pic_order_always_zero_flag; // u(1)
|
||||
int offset_for_non_ref_pic; // se(v)
|
||||
int offset_for_top_to_bottom_field; // se(v)
|
||||
int num_ref_frames_in_poc_cycle; // ue(v) (0~255)
|
||||
u16 offset_for_ref_frame[256];
|
||||
int max_num_ref_frames; // ue(v)
|
||||
int gaps_in_frame_num_value_allowed_flag;
|
||||
int pic_mb_width;
|
||||
int pic_mb_height;
|
||||
int frame_cropping_rect_left_offset;
|
||||
int frame_cropping_rect_right_offset;
|
||||
int frame_cropping_rect_top_offset;
|
||||
int frame_cropping_rect_bottom_offset;
|
||||
u8 mbaff;
|
||||
u8 frame_mbs_only_flag;
|
||||
u8 direct_8x8_inference_flag;
|
||||
u8 scaling_matrix_present_flag; // u(1)
|
||||
u32 level_idc;
|
||||
u32 profile_idc;
|
||||
u32 constraint_set_flags;
|
||||
u32 chroma_format_idc; // use(v)
|
||||
u8 scaling_matrix4[6][16];
|
||||
u8 scaling_matrix8[2][64];
|
||||
int log2_max_frm_num; // ue(v), log2_max_frm_num_minus4 + 4
|
||||
int poc_type;
|
||||
// poc_type == 0
|
||||
int log2_max_poc_lsb; // ue(v), log2_max_pic_order_cnt_lsb_minus4 + 4
|
||||
// poc_type == 1
|
||||
int delta_pic_order_always_zero_flag; // u(1)
|
||||
int offset_for_non_ref_pic; // se(v)
|
||||
int offset_for_top_to_bottom_field; // se(v)
|
||||
int num_ref_frames_in_poc_cycle; // ue(v) (0~255)
|
||||
u16 offset_for_ref_frame[256];
|
||||
int max_num_ref_frames; // ue(v)
|
||||
int gaps_in_frame_num_value_allowed_flag;
|
||||
int pic_mb_width;
|
||||
int pic_mb_height;
|
||||
int frame_cropping_rect_left_offset;
|
||||
int frame_cropping_rect_right_offset;
|
||||
int frame_cropping_rect_top_offset;
|
||||
int frame_cropping_rect_bottom_offset;
|
||||
};
|
||||
|
||||
struct h264_pps_info
|
||||
{
|
||||
u8 deblocking_filter_control_present_flag;
|
||||
u8 transform_8x8_mode_flag;
|
||||
u8 constrained_intra_pred_flag;
|
||||
u8 entropy_coding_flag; // 0: cavlc; 1: cabac
|
||||
u8 bottom_field_pic_order_in_frame_flag;
|
||||
u8 weighted_pred_flag;
|
||||
u8 weighted_bipred_flag;
|
||||
u8 redundant_pic_cnt_present_flag;
|
||||
u32 sps_id;
|
||||
int num_ref_idx[2]; // num_ref_idx_l0/l1_active_minus1 +1
|
||||
u32 pic_init_qp; // pic_init_qp_minus26 + 26
|
||||
int chroma_qp_index_offset[2];
|
||||
u8 scaling_matrix4[6][16];
|
||||
u8 scaling_matrix8[2][64];
|
||||
u8 deblocking_filter_control_present_flag;
|
||||
u8 transform_8x8_mode_flag;
|
||||
u8 constrained_intra_pred_flag;
|
||||
u8 entropy_coding_flag; // 0: cavlc; 1: cabac
|
||||
u8 bottom_field_pic_order_in_frame_flag;
|
||||
u8 weighted_pred_flag;
|
||||
u8 weighted_bipred_flag;
|
||||
u8 redundant_pic_cnt_present_flag;
|
||||
u32 sps_id;
|
||||
int num_ref_idx[2]; // num_ref_idx_l0/l1_active_minus1 +1
|
||||
u32 pic_init_qp; // pic_init_qp_minus26 + 26
|
||||
int chroma_qp_index_offset[2];
|
||||
u8 scaling_matrix4[6][16];
|
||||
u8 scaling_matrix8[2][64];
|
||||
};
|
||||
|
||||
struct h264_slice_header
|
||||
{
|
||||
u8 field_pic_flag; // u(1)
|
||||
u8 bottom_field_flag; // u(1)
|
||||
u8 mbaff_frame;
|
||||
u32 first_mb_in_slice; // ue(v)
|
||||
u32 slice_type; // ue(v)
|
||||
u32 pps_id; // ue(v)
|
||||
int frame_num; // u(v)
|
||||
u32 idr_pic_id; // ue(v)
|
||||
u8 field_pic_flag; // u(1)
|
||||
u8 bottom_field_flag; // u(1)
|
||||
u8 mbaff_frame;
|
||||
u32 first_mb_in_slice; // ue(v)
|
||||
u32 slice_type; // ue(v)
|
||||
u32 pps_id; // ue(v)
|
||||
int frame_num; // u(v)
|
||||
u32 idr_pic_id; // ue(v)
|
||||
|
||||
// poc type == 0
|
||||
int poc_lsb; // u(v)
|
||||
int poc_msb;
|
||||
int delta_poc_bottom; // se(v)
|
||||
// poc_type == 1 && !delta_pic_order_always_zero_flag
|
||||
int delta_poc[2]; // se(v)
|
||||
// poc type == 0
|
||||
int poc_lsb; // u(v)
|
||||
int poc_msb;
|
||||
int delta_poc_bottom; // se(v)
|
||||
// poc_type == 1 && !delta_pic_order_always_zero_flag
|
||||
int delta_poc[2]; // se(v)
|
||||
|
||||
int num_ref_idx[2];
|
||||
int direct_spatial_mv_pred;
|
||||
int num_ref_idx_active_override;
|
||||
int num_ref_idx[2];
|
||||
int direct_spatial_mv_pred;
|
||||
int num_ref_idx_active_override;
|
||||
|
||||
int list_count; // count of ref lists(I:0, P:1, B:2)
|
||||
int list_count; // count of ref lists(I:0, P:1, B:2)
|
||||
|
||||
struct mmco mmco[MAX_MMCO_COUNT];
|
||||
int nb_mmco;
|
||||
int explicit_ref_marking; // adaptive_ref_pic_marking_mode_flag
|
||||
struct mmco mmco[MAX_MMCO_COUNT];
|
||||
int nb_mmco;
|
||||
int explicit_ref_marking; // adaptive_ref_pic_marking_mode_flag
|
||||
|
||||
int cur_pic_num;
|
||||
int max_pic_num;
|
||||
struct pred_weight_table pwt;
|
||||
int cabac_init_idc;
|
||||
int qp_y;
|
||||
int cur_pic_num;
|
||||
int max_pic_num;
|
||||
struct pred_weight_table pwt;
|
||||
int cabac_init_idc;
|
||||
int qp_y;
|
||||
|
||||
int deblocking_filter;
|
||||
int slice_alpha_c0_offset_div2;
|
||||
int slice_beta_offset_div2;
|
||||
int deblocking_filter;
|
||||
int slice_alpha_c0_offset_div2;
|
||||
int slice_beta_offset_div2;
|
||||
};
|
||||
|
||||
/*
|
||||
picture infomation
|
||||
*/
|
||||
struct h264_picture {
|
||||
u8 mbaff_frame; ///< 1 -> MBAFF frame 0-> not MBAFF
|
||||
u8 nal_ref_idc[2];
|
||||
u8 refrence; // 0: not used for refrence; PICT_FRAME: the frame used by refrence;
|
||||
// PICT_TOP/PICT_BOT: one field of this frame used by refrence
|
||||
// DELAYED_PIC_REF: not used by refrence, and not send to render (need renorder)
|
||||
u8 key_frame;
|
||||
u8 mmco_reset;
|
||||
u8 picture_structure;
|
||||
u8 displayed_flag; // this picture is displayed
|
||||
int field_poc[2]; // h264 top/bottom POC
|
||||
int poc; // h264 frame POC
|
||||
int frame_num; // h264 frame_num (raw frame_num from slice header)
|
||||
int pic_id; /**< h264 pic_num (short -> no wrap version of pic_num,
|
||||
pic_num & max_pic_num; long -> long_pic_num) */
|
||||
int long_ref; // 1->long term nReference 0->short term nReference
|
||||
int ref_poc[2][16]; // h264 POCs of the frames used as nReference
|
||||
int ref_count[2]; // number of entries in ref_nPoc
|
||||
u8 mbaff_frame; ///< 1 -> MBAFF frame 0-> not MBAFF
|
||||
u8 nal_ref_idc[2];
|
||||
u8 refrence; // 0: not used for refrence; PICT_FRAME: the frame used by refrence;
|
||||
// PICT_TOP/PICT_BOT: one field of this frame used by refrence
|
||||
// DELAYED_PIC_REF: not used by refrence, and not send to render (need renorder)
|
||||
u8 key_frame;
|
||||
u8 mmco_reset;
|
||||
u8 picture_structure;
|
||||
u8 displayed_flag; // this picture is displayed
|
||||
int field_poc[2]; // h264 top/bottom POC
|
||||
int poc; // h264 frame POC
|
||||
int frame_num; // h264 frame_num (raw frame_num from slice header)
|
||||
int pic_id; // h264 pic_num (short -> no wrap version of pic_num,
|
||||
//pic_num & max_pic_num; long -> long_pic_num)
|
||||
int long_ref; // 1->long term nReference 0->short term nReference
|
||||
int ref_poc[2][16]; // h264 POCs of the frames used as nReference
|
||||
int ref_count[2]; // number of entries in ref_nPoc
|
||||
|
||||
u32 buf_idx;
|
||||
u32 top_field_col_addr; // phy addr for top field col buf, it is a part of col_buf in struct h264_frame_info
|
||||
u32 bot_field_col_addr; // phy addr for bot field col buf
|
||||
struct frame* frame; // frame ptr get from frame manager
|
||||
u32 buf_idx;
|
||||
u32 top_field_col_addr; // phy addr for top field col buf, it is a part of col_buf in struct h264_frame_info
|
||||
u32 bot_field_col_addr; // phy addr for bot field col buf
|
||||
struct frame* frame; // frame ptr get from frame manager
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -204,31 +225,31 @@ the refrence field/frame context.
|
||||
if it is one field of picture, the variable refrence is set PICT_TOP/PICT_FIELD
|
||||
*/
|
||||
struct h264_ref {
|
||||
int refrence; // refrence type of current field/frame
|
||||
int poc; // poc of current field/frame
|
||||
int pic_id;
|
||||
struct h264_picture* parent; // pointer to picture in struct h264_frame_info
|
||||
int refrence; // refrence type of current field/frame
|
||||
int poc; // poc of current field/frame
|
||||
int pic_id;
|
||||
struct h264_picture* parent; // pointer to picture in struct h264_frame_info
|
||||
};
|
||||
|
||||
struct h264_frame_info {
|
||||
int max_valid_frame_num; // total frame number in frame_manager
|
||||
struct ve_buffer* col_buf; // col buf for all frames, used by ve
|
||||
struct ve_buffer* dblk_y_buf; // y data buffer for deblk, used by ve
|
||||
struct ve_buffer* dblk_c_buf; // c data buffer for deblk, used by ve
|
||||
struct ve_buffer* intrap_buf; // intra-pred buffer, used by ve
|
||||
struct ve_buffer* mb_info_buf; // mb info buffer, used by ve
|
||||
struct ve_buffer* mb_col_info_buf; // mb co-located info
|
||||
int max_valid_frame_num; // total frame number in frame_manager
|
||||
struct ve_buffer* col_buf; // col buf for all frames, used by ve
|
||||
struct ve_buffer* dblk_y_buf; // y data buffer for deblk, used by ve
|
||||
struct ve_buffer* dblk_c_buf; // c data buffer for deblk, used by ve
|
||||
struct ve_buffer* intrap_buf; // intra-pred buffer, used by ve
|
||||
struct ve_buffer* mb_info_buf; // mb info buffer, used by ve
|
||||
struct ve_buffer* mb_col_info_buf; // mb co-located info
|
||||
|
||||
struct h264_picture picture[32];
|
||||
struct h264_picture* long_ref[32];
|
||||
struct h264_picture* short_ref[32];
|
||||
struct h264_ref def_ref_list[2][32];
|
||||
struct h264_ref ref_list[2][48];
|
||||
struct h264_picture* delayed_output_pic;
|
||||
struct h264_picture* delayed_pic[MAX_DELAYED_PIC_COUNT + 2]; // render delayed picture in decoder, for reorder
|
||||
int delay_pic_num;
|
||||
int last_pocs[MAX_DELAYED_PIC_COUNT];
|
||||
struct h264_picture* cur_pic_ptr; // current decoding picture
|
||||
struct h264_picture picture[32];
|
||||
struct h264_picture* long_ref[32];
|
||||
struct h264_picture* short_ref[32];
|
||||
struct h264_ref def_ref_list[2][32];
|
||||
struct h264_ref ref_list[2][48];
|
||||
struct h264_picture* delayed_output_pic;
|
||||
struct h264_picture* delayed_pic[MAX_DELAYED_PIC_COUNT + 2]; // render delayed picture in decoder, for reorder
|
||||
int delay_pic_num;
|
||||
int last_pocs[MAX_DELAYED_PIC_COUNT];
|
||||
struct h264_picture* cur_pic_ptr; // current decoding picture
|
||||
};
|
||||
|
||||
#define SPS_MAX_NUM 32
|
||||
@@ -236,78 +257,81 @@ struct h264_frame_info {
|
||||
#define RBSP_BYTES 128
|
||||
struct h264_dec_ctx
|
||||
{
|
||||
struct mpp_decoder decoder;
|
||||
unsigned long regs_base;
|
||||
struct mpp_decoder decoder;
|
||||
unsigned long regs_base;
|
||||
|
||||
int active_pps_id; // the pps_buffers id
|
||||
int active_sps_id; // the sps_buffers id
|
||||
struct h264_pps_info* pps_buffers[PPS_MAX_NUM]; // we need malloc buffer if we get a new pps
|
||||
struct h264_sps_info* sps_buffers[SPS_MAX_NUM]; // we need malloc buffer if we get a new pps
|
||||
struct h264_slice_header sh;
|
||||
struct h264_frame_info frame_info;
|
||||
int extra_frame_num;
|
||||
int active_pps_id; // the pps_buffers id
|
||||
int active_sps_id; // the sps_buffers id
|
||||
struct h264_pps_info* pps_buffers[PPS_MAX_NUM]; // we need malloc buffer if we get a new pps
|
||||
struct h264_sps_info* sps_buffers[SPS_MAX_NUM]; // we need malloc buffer if we get a new pps
|
||||
struct h264_slice_header sh;
|
||||
struct h264_frame_info frame_info;
|
||||
int extra_frame_num;
|
||||
|
||||
struct ve_buffer_allocator* ve_buf_handle;
|
||||
struct packet* curr_packet;
|
||||
struct frame* curr_frame;
|
||||
enum mpp_pixel_format pix_format; // output pixel format
|
||||
int eos;
|
||||
struct ve_buffer_allocator* ve_buf_handle;
|
||||
struct packet* curr_packet;
|
||||
struct frame* curr_frame;
|
||||
enum mpp_pixel_format pix_format; // output pixel format
|
||||
int eos;
|
||||
|
||||
int avcc; // nalu_size + nalu, like mov
|
||||
int avcc; // nalu_size + nalu, like mov
|
||||
|
||||
int sc_byte_offset; // byte offset of startcode
|
||||
int remove_bytes; // remove 0x03 bytes
|
||||
int first_eptb_offset; // offste of first 0x03 byte in eptb
|
||||
unsigned char rbsp_buffer[RBSP_BYTES]; // rbsp buffer (remove eptb)
|
||||
int rbsp_len;
|
||||
int sc_byte_offset; // byte offset of startcode
|
||||
int remove_bytes; // remove 0x03 bytes
|
||||
int first_eptb_offset; // offste of first 0x03 byte in eptb
|
||||
unsigned char rbsp_buffer[RBSP_BYTES]; // rbsp buffer (remove eptb)
|
||||
int rbsp_len;
|
||||
|
||||
struct read_bit_context gb;
|
||||
int nal_ref_idc;
|
||||
int nal_unit_type;
|
||||
int idr_pic_flag; // IDR nalu
|
||||
struct read_bit_context gb;
|
||||
int nal_ref_idc;
|
||||
int nal_ref_idc_pre;
|
||||
int nal_unit_type;
|
||||
int idr_pic_flag; // IDR nalu
|
||||
|
||||
int width;
|
||||
int height;
|
||||
int cur_slice_num;
|
||||
int first_field;
|
||||
int picture_structure;
|
||||
int decode_mb_num; // current decode mb number
|
||||
int mbs_in_pic; // total mb number in a picture
|
||||
int width;
|
||||
int height;
|
||||
int cur_slice_num;
|
||||
int first_field;
|
||||
int picture_structure;
|
||||
int decode_mb_num; // current decode mb number
|
||||
int mbs_in_pic; // total mb number in a picture
|
||||
|
||||
int frame_num; // for ref_mark
|
||||
int frame_num; // for ref_mark
|
||||
|
||||
int avc_start; // for hw reset
|
||||
int avc_start; // for hw reset
|
||||
|
||||
// for poc, ffmpeg s->poc
|
||||
int prev_poc_msb; // poc_msb of the last reference pic for POC type 0
|
||||
int prev_poc_lsb; // poc_lsb of the last reference pic for POC type 0
|
||||
int frame_num_offset; // for POC type 2
|
||||
int prev_frame_num_offset; // for POC type 2
|
||||
int prev_frame_num; // frame_num of the last pic for POC type 1/2
|
||||
// for poc, ffmpeg s->poc
|
||||
int prev_poc_msb; // poc_msb of the last reference pic for POC type 0
|
||||
int prev_poc_lsb; // poc_lsb of the last reference pic for POC type 0
|
||||
int frame_num_offset; // for POC type 2
|
||||
int prev_frame_num_offset; // for POC type 2
|
||||
int prev_frame_num; // frame_num of the last pic for POC type 1/2
|
||||
|
||||
int min_display_poc; // last displayed poc, for reorder display picture
|
||||
int poc_delta; // poc delta between two pictures
|
||||
int next_output_poc; // next poc, for reorder display picture
|
||||
int min_display_poc; // last displayed poc, for reorder display picture
|
||||
int poc_delta; // poc delta between two pictures
|
||||
int next_output_poc; // next poc, for reorder display picture
|
||||
|
||||
int has_b_frames; //
|
||||
int b_frames_max_num;
|
||||
int has_b_frames; //
|
||||
int b_frames_max_num;
|
||||
|
||||
int long_ref_count; // number of actual long term references
|
||||
int short_ref_count; // number of actual short term references
|
||||
int long_ref_count; // number of actual long term references
|
||||
int short_ref_count; // number of actual short term references
|
||||
|
||||
int bit_offset; // bit offset of slice data this NALU
|
||||
int bit_offset; // bit offset of slice data this NALU
|
||||
|
||||
int slice_offset; // slice offset in packet, in byte unit
|
||||
int slice_offset; // slice offset in packet, in byte unit
|
||||
|
||||
FILE* fp_reg;
|
||||
FILE* fp_reg;
|
||||
|
||||
int error;
|
||||
};
|
||||
|
||||
|
||||
/**************** h264_refs *********************/
|
||||
//* init ref list
|
||||
// init ref list
|
||||
int init_ref_list(struct h264_dec_ctx *s);
|
||||
|
||||
//* ref list reordering
|
||||
// ref list reordering
|
||||
int ref_pic_list_reordering(struct h264_dec_ctx *s);
|
||||
|
||||
int execute_ref_pic_marking(struct h264_dec_ctx *s);
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Artinchip Technology Co. Ltd
|
||||
*
|
||||
* author: <qi.xu@artinchip.com>
|
||||
* Desc: h264 register config
|
||||
*
|
||||
*/
|
||||
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* author: <qi.xu@artinchip.com>
|
||||
* Desc: h264 register config
|
||||
*
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -439,8 +441,8 @@ static void config_refrence_frame_info(struct h264_dec_ctx *s)
|
||||
int cur_frame_idx = s->frame_info.cur_pic_ptr->buf_idx;
|
||||
|
||||
memset(frame_info, 0, 32*sizeof(struct frame_info));
|
||||
//* 1. find the corresponding top/bottom field,
|
||||
//* then save the info to frame_info
|
||||
// 1. find the corresponding top/bottom field,
|
||||
// then save the info to frame_info
|
||||
logd("list_count: %d, num_ref: %d", s->sh.list_count, s->sh.num_ref_idx[0]);
|
||||
for(list=0; list<s->sh.list_count; list++) {
|
||||
for(i=0; i<s->sh.num_ref_idx[list]; i++) {
|
||||
@@ -452,7 +454,7 @@ static void config_refrence_frame_info(struct h264_dec_ctx *s)
|
||||
frame_info[buf_idx].buf_idx = buf_idx;
|
||||
|
||||
if(pic->refrence == PICT_FRAME) {
|
||||
//* current picture is used for refrence
|
||||
// current picture is used for refrence
|
||||
frame_info[buf_idx].field_poc[0] = pic->field_poc[0];
|
||||
frame_info[buf_idx].field_poc[1] = pic->field_poc[1];
|
||||
frame_info[buf_idx].frame_stucture = 1;
|
||||
@@ -491,7 +493,7 @@ static void config_refrence_frame_info(struct h264_dec_ctx *s)
|
||||
}
|
||||
|
||||
logd("valid_frame_num: %d", valid_frame_num);
|
||||
//* config reference frame info register
|
||||
// config reference frame info register
|
||||
for(i=0; i<valid_frame_num; i++) {
|
||||
j = valid_frame[i];
|
||||
// top poc ( select 0 )
|
||||
@@ -560,10 +562,10 @@ static void config_framebuffer_info(struct h264_dec_ctx *s)
|
||||
if(s->fp_reg)
|
||||
fprintf(s->fp_reg, "// config framebuffer info\n");
|
||||
|
||||
//* config currrent frame info
|
||||
// config currrent frame info
|
||||
config_frame_info(s, s->frame_info.cur_pic_ptr);
|
||||
|
||||
//* config reference frame info
|
||||
// config reference frame info
|
||||
config_refrence_frame_info(s);
|
||||
}
|
||||
|
||||
@@ -595,7 +597,7 @@ static void config_picture_info(struct h264_dec_ctx *s)
|
||||
+ s->decoder.output_x;
|
||||
if ((s->pix_format == MPP_FMT_NV12) || (s->pix_format == MPP_FMT_NV21)) {
|
||||
phy_addr_offset[1] = s->decoder.output_y * cur_pic->frame->mpp_frame.buf.stride[1] /2
|
||||
+ s->decoder.output_x ;
|
||||
+ s->decoder.output_x;
|
||||
} else {
|
||||
phy_addr_offset[1] = s->decoder.output_y * cur_pic->frame->mpp_frame.buf.stride[1] /2
|
||||
+ s->decoder.output_x / 2;
|
||||
@@ -783,11 +785,11 @@ int decode_slice(struct h264_dec_ctx *s)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(s->sh.slice_type == H264_SLICE_P){
|
||||
if (s->sh.slice_type == H264_SLICE_P) {
|
||||
logi("%p, %s slice, cycle: %d", s,"P", read_reg(s->regs_base + CYCLES_REG));
|
||||
}else if(s->sh.slice_type == H264_SLICE_B){
|
||||
} else if (s->sh.slice_type == H264_SLICE_B) {
|
||||
logi("%p, %s slice, cycle: %d", s,"B", read_reg(s->regs_base + CYCLES_REG));
|
||||
}else if(s->sh.slice_type == H264_SLICE_I){
|
||||
} else if (s->sh.slice_type == H264_SLICE_I) {
|
||||
logi("%p, %s slice, cycle: %d", s,"I", read_reg(s->regs_base + CYCLES_REG));
|
||||
}
|
||||
|
||||
@@ -819,5 +821,6 @@ error:
|
||||
cur_pic->frame->mpp_frame.flags |= FRAME_FLAG_ERROR;
|
||||
ve_put_client();
|
||||
s->avc_start = 1;
|
||||
s->error = H264_DECODER_ERROR_HARD;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Artinchip Technology Co. Ltd
|
||||
*
|
||||
* author: <qi.xu@artinchip.com>
|
||||
* Desc: h264 sps/pps parse
|
||||
*
|
||||
*/
|
||||
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* author: <qi.xu@artinchip.com>
|
||||
* Desc: h264 sps/pps parse
|
||||
*
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "h264_decoder.h"
|
||||
@@ -392,6 +394,11 @@ int h264_decode_sps(struct h264_dec_ctx *s)
|
||||
int level_idc = read_bits(&s->gb, 8);
|
||||
int sps_id = read_ue_golomb(&s->gb);
|
||||
|
||||
if (sps_id > SPS_MAX_NUM - 1) {
|
||||
loge("sps_id:%d\n",sps_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// if currenct sps is not exist before, alloc buffer for it
|
||||
if(s->sps_buffers[sps_id] == NULL) {
|
||||
s->sps_buffers[sps_id] = (struct h264_sps_info*)mpp_alloc(sizeof(struct h264_sps_info));
|
||||
@@ -519,6 +526,11 @@ int h264_decode_pps(struct h264_dec_ctx *s)
|
||||
logd("pps_id: %d", pps_id);
|
||||
logd("gb index: %d", read_bits_count(&s->gb));
|
||||
|
||||
if (pps_id > PPS_MAX_NUM - 1) {
|
||||
loge("pps_id:%d\n",pps_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(s->pps_buffers[pps_id] == NULL) {
|
||||
s->pps_buffers[pps_id] = (struct h264_pps_info*)mpp_alloc(sizeof(struct h264_pps_info));
|
||||
if(s->pps_buffers[pps_id] == NULL) {
|
||||
@@ -794,18 +806,20 @@ static void set_error_from_ref_list(struct h264_dec_ctx *s)
|
||||
|
||||
static void set_frame_info(struct h264_dec_ctx *s)
|
||||
{
|
||||
struct h264_sps_info* cur_sps = s->sps_buffers[s->active_sps_id];
|
||||
struct frame* f = s->frame_info.cur_pic_ptr->frame;
|
||||
int crop_unit_y = 2 - cur_sps->frame_mbs_only_flag;
|
||||
struct h264_sps_info* cur_sps = s->sps_buffers[s->active_sps_id];
|
||||
struct frame* f = s->frame_info.cur_pic_ptr->frame;
|
||||
int sub = (cur_sps->chroma_format_idc == 1) ? 1 : 0;
|
||||
int crop_unit_y = (2 - cur_sps->frame_mbs_only_flag) << sub;
|
||||
int crop_unit_x = 1 << sub;
|
||||
|
||||
f->mpp_frame.pts = s->curr_packet->pts;
|
||||
f->mpp_frame.buf.crop_en = 1;
|
||||
f->mpp_frame.buf.crop.x = cur_sps->frame_cropping_rect_left_offset;
|
||||
f->mpp_frame.buf.crop.y = crop_unit_y * cur_sps->frame_cropping_rect_top_offset;
|
||||
f->mpp_frame.buf.crop.height = s->height - crop_unit_y * cur_sps->frame_cropping_rect_bottom_offset
|
||||
- crop_unit_y * cur_sps->frame_cropping_rect_top_offset;
|
||||
f->mpp_frame.buf.crop.width = s->width - cur_sps->frame_cropping_rect_left_offset
|
||||
- cur_sps->frame_cropping_rect_right_offset;
|
||||
f->mpp_frame.pts = s->curr_packet->pts;
|
||||
f->mpp_frame.buf.crop_en = 1;
|
||||
f->mpp_frame.buf.crop.x = cur_sps->frame_cropping_rect_left_offset * crop_unit_x;
|
||||
f->mpp_frame.buf.crop.y = crop_unit_y * cur_sps->frame_cropping_rect_top_offset;
|
||||
f->mpp_frame.buf.crop.height = s->height - crop_unit_y * cur_sps->frame_cropping_rect_bottom_offset
|
||||
- crop_unit_y * cur_sps->frame_cropping_rect_top_offset;
|
||||
f->mpp_frame.buf.crop.width = s->width - crop_unit_x * cur_sps->frame_cropping_rect_right_offset
|
||||
- crop_unit_x * cur_sps->frame_cropping_rect_left_offset;
|
||||
}
|
||||
|
||||
// check whether last frame is error
|
||||
@@ -826,8 +840,9 @@ static int check_last_frame(struct h264_dec_ctx *s)
|
||||
cur_pic->frame->mpp_frame.flags |= FRAME_FLAG_ERROR;
|
||||
loge("last picture error, decoded_mb: %d, total_mbs: %d",
|
||||
s->decode_mb_num, s->mbs_in_pic);
|
||||
|
||||
execute_ref_pic_marking(s);
|
||||
if (s->nal_ref_idc_pre) {
|
||||
execute_ref_pic_marking(s);
|
||||
}
|
||||
select_output_frame(s);
|
||||
s->frame_info.cur_pic_ptr = NULL;
|
||||
}
|
||||
@@ -859,6 +874,8 @@ int h264_decode_slice_header(struct h264_dec_ctx *s)
|
||||
if(sh->first_mb_in_slice == 0) {
|
||||
s->cur_slice_num = 0;
|
||||
} else if(s->cur_slice_num == 0) {
|
||||
s->error = H264_DECODER_ERROR_SLICENUM;
|
||||
loge("first_mb_in_slice:%d,cur_slice_num:%d\n", sh->first_mb_in_slice,s->cur_slice_num);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -867,15 +884,25 @@ int h264_decode_slice_header(struct h264_dec_ctx *s)
|
||||
sh->slice_type = read_ue_golomb(&s->gb);
|
||||
if(sh->slice_type > 9) {
|
||||
loge("slice type(%d) error", sh->slice_type);
|
||||
s->error = H264_DECODER_ERROR_SLICETYPE;
|
||||
return -1;
|
||||
}
|
||||
sh->slice_type = (sh->slice_type > 4) ? sh->slice_type-5 : sh->slice_type;
|
||||
|
||||
sh->pps_id = read_ue_golomb(&s->gb);
|
||||
if(sh->pps_id > 255 || s->pps_buffers[sh->pps_id] == NULL) {
|
||||
|
||||
if(sh->pps_id > 255) {
|
||||
s->error = H264_DECODER_ERROR_PPS;
|
||||
loge("slice header pps id(%d) error", sh->pps_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(s->pps_buffers[sh->pps_id] == NULL) {
|
||||
s->error = H264_DECODER_ERROR_PPS;
|
||||
loge("slice header pps id:%d,pps_buffers==NULL", sh->pps_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
logi("SH: slice_type: %d, pps_id: %d, bit offset: %d", sh->slice_type, sh->pps_id, read_bits_count(&s->gb));
|
||||
|
||||
s->active_pps_id = sh->pps_id;
|
||||
@@ -939,6 +966,7 @@ int h264_decode_slice_header(struct h264_dec_ctx *s)
|
||||
// last field not match
|
||||
if(s->picture_structure == PICT_FRAME || s->picture_structure == last_pic_structure) {
|
||||
s->first_field = 0;
|
||||
s->error = H264_DECODER_ERROR_PICTURESTRUCTUTE;
|
||||
loge("picture struct error");
|
||||
return -1;
|
||||
} else {
|
||||
@@ -959,9 +987,26 @@ int h264_decode_slice_header(struct h264_dec_ctx *s)
|
||||
s->picture_structure = last_pic_structure;
|
||||
s->first_field = last_first_field;
|
||||
//pm_reclaim_ready_packet(s->decoder.pm, s->curr_packet);
|
||||
s->error = H264_DECODER_ERROR_NOEMPTYFRAME;
|
||||
return DEC_NO_EMPTY_FRAME;
|
||||
}
|
||||
|
||||
// top_field_col_addr & top_field_col_addr are fixed addr.
|
||||
// s->frame_info.picture[f->mpp_frame.id].top_field_col_addr = 0;
|
||||
// s->frame_info.picture[f->mpp_frame.id].bot_field_col_addr = 0;
|
||||
s->frame_info.picture[f->mpp_frame.id].mbaff_frame = 0;
|
||||
s->frame_info.picture[f->mpp_frame.id].nal_ref_idc[0] = 0;
|
||||
s->frame_info.picture[f->mpp_frame.id].nal_ref_idc[1] = 0;
|
||||
s->frame_info.picture[f->mpp_frame.id].picture_structure = 0;
|
||||
s->frame_info.picture[f->mpp_frame.id].displayed_flag = 0;
|
||||
s->frame_info.picture[f->mpp_frame.id].field_poc[0] = 0;
|
||||
s->frame_info.picture[f->mpp_frame.id].field_poc[1] = 0;
|
||||
s->frame_info.picture[f->mpp_frame.id].poc = 0;
|
||||
s->frame_info.picture[f->mpp_frame.id].frame_num = 0;
|
||||
s->frame_info.picture[f->mpp_frame.id].pic_id = 0;
|
||||
s->frame_info.picture[f->mpp_frame.id].long_ref = 0;
|
||||
s->frame_info.picture[f->mpp_frame.id].ref_count[0] = 0;
|
||||
s->frame_info.picture[f->mpp_frame.id].ref_count[1] = 0;
|
||||
f->mpp_frame.flags = 0;
|
||||
s->frame_info.picture[f->mpp_frame.id].frame = f;
|
||||
s->frame_info.picture[f->mpp_frame.id].refrence = 0;
|
||||
s->frame_info.picture[f->mpp_frame.id].buf_idx = f->mpp_frame.id;
|
||||
@@ -1062,7 +1107,7 @@ int h264_decode_slice_header(struct h264_dec_ctx *s)
|
||||
if(s->nal_ref_idc) {
|
||||
if(dec_ref_pic_marking(s) < 0) {
|
||||
loge("dec_ref_pic_marking error");
|
||||
return -1;
|
||||
s->error = H264_DECODER_ERROR_REFPICMARKING;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1089,8 +1134,8 @@ int h264_decode_slice_header(struct h264_dec_ctx *s)
|
||||
if(cur_pps->deblocking_filter_control_present_flag) {
|
||||
sh->deblocking_filter = read_ue_golomb(&s->gb);
|
||||
if(sh->deblocking_filter > 2) {
|
||||
s->error = H264_DECODER_ERROR_DEBLOCKINGFILTER;
|
||||
loge("deblocking_filter(%d) out of range", sh->deblocking_filter);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(sh->deblocking_filter != 1) {
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Artinchip Technology Co. Ltd
|
||||
*
|
||||
* author: <qi.xu@artinchip.com>
|
||||
* Desc: jpeg decode
|
||||
*
|
||||
*/
|
||||
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* author: <qi.xu@artinchip.com>
|
||||
* Desc:jpeg decode
|
||||
*
|
||||
*/
|
||||
|
||||
#define LOG_TAG "jpeg_decoder"
|
||||
|
||||
@@ -405,6 +407,7 @@ static void set_frame_info(struct mjpeg_dec_ctx *s)
|
||||
{
|
||||
if(s->curr_packet->flag & PACKET_FLAG_EOS)
|
||||
s->curr_frame->mpp_frame.flags |= FRAME_FLAG_EOS;
|
||||
s->curr_frame->mpp_frame.buf.flags |= MPP_COLOR_SPACE_BT601_FULL_RANGE;
|
||||
s->curr_frame->mpp_frame.buf.crop_en = 1;
|
||||
s->curr_frame->mpp_frame.buf.crop.x = 0;
|
||||
s->curr_frame->mpp_frame.buf.crop.y = 0;
|
||||
@@ -494,8 +497,11 @@ int mjpeg_decode_sos(struct mjpeg_dec_ctx *s,
|
||||
|
||||
int offset = (s->raw_scan_buffer - s->curr_packet->data) + sos_size;
|
||||
logw("offste: %d", offset);
|
||||
if(ve_decode_jpeg(s, offset))
|
||||
if(ve_decode_jpeg(s, offset)) {
|
||||
s->error = JPEG_DECODER_ERROR_HARDWARE;
|
||||
printf("[%s:%d]\n",__FUNCTION__,__LINE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
set_frame_info(s);
|
||||
|
||||
@@ -567,6 +573,38 @@ static void skip_variable_marker(struct mjpeg_dec_ctx *s)
|
||||
}
|
||||
}
|
||||
|
||||
void mjpeg_print_decoder_error(struct mpp_decoder *ctx)
|
||||
{
|
||||
struct mjpeg_dec_ctx *s = (struct mjpeg_dec_ctx*)ctx;
|
||||
|
||||
switch (s->error) {
|
||||
case JPEG_DECODER_ERROR_NONE:
|
||||
loge("ok\n");
|
||||
break;
|
||||
case JPEG_DECODER_ERROR_INPUTLEN:
|
||||
loge("input packet too small\n");
|
||||
break;
|
||||
case JPEG_DECODER_ERROR_INPUTERROR:
|
||||
loge("input packet data error\n");
|
||||
break;
|
||||
case JPEG_DECODER_ERROR_INVPTR:
|
||||
loge("invalid (null) buffer pointer\n");
|
||||
break;
|
||||
case JPEG_DECODER_ERROR_NOEMPTYFRAME:
|
||||
loge("no empty frame for decoder\n");
|
||||
break;
|
||||
case JPEG_DECODER_ERROR_UNSUPPORTTYPE:
|
||||
loge("unsupport type\n");
|
||||
break;
|
||||
case JPEG_DECODER_ERROR_HARDWARE:
|
||||
loge("an error happen whlie hard decoder processing \n");
|
||||
break;
|
||||
default:
|
||||
loge("unknown error\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int __mjpeg_decode_frame(struct mpp_decoder *ctx)
|
||||
{
|
||||
struct mjpeg_dec_ctx *s = (struct mjpeg_dec_ctx*)ctx;
|
||||
@@ -577,6 +615,8 @@ int __mjpeg_decode_frame(struct mpp_decoder *ctx)
|
||||
int start_code;
|
||||
int ret = 0;
|
||||
|
||||
s->error = JPEG_DECODER_ERROR_NONE;
|
||||
s->got_picture = 0;
|
||||
s->curr_packet = pm_dequeue_ready_packet(s->decoder.pm);
|
||||
if(s->curr_packet == NULL) {
|
||||
loge("pm_dequeue_ready_packet error, ready_packet num: %d", pm_get_ready_packet_num(s->decoder.pm));
|
||||
@@ -587,9 +627,17 @@ int __mjpeg_decode_frame(struct mpp_decoder *ctx)
|
||||
buf_end = buf_ptr + buf_size;
|
||||
|
||||
start_code = 0xffd8;
|
||||
if (buf_size < 8 || !memchr(buf_ptr, start_code, 8)) {
|
||||
if (buf_size < 8) {
|
||||
s->error = JPEG_DECODER_ERROR_INPUTLEN;
|
||||
loge("data error is too short !");
|
||||
ret = -1;
|
||||
goto _exit;
|
||||
}
|
||||
if (!memchr(buf_ptr, start_code, 8)) {
|
||||
s->error = JPEG_DECODER_ERROR_INPUTERROR;
|
||||
loge("The file is not jpeg!");
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
while (buf_ptr < buf_end) {
|
||||
@@ -599,18 +647,24 @@ int __mjpeg_decode_frame(struct mpp_decoder *ctx)
|
||||
&unescaped_buf_size);
|
||||
/* EOF */
|
||||
if (start_code < 0) {
|
||||
break;
|
||||
s->error = JPEG_DECODER_ERROR_INPUTERROR;
|
||||
loge("no start_code means\n");
|
||||
ret = -1;
|
||||
goto _exit;
|
||||
} else if (unescaped_buf_size > INT_MAX / 8) {
|
||||
loge("MJPEG packet 0x%x too big (%d/%d), corrupt data?",
|
||||
start_code, unescaped_buf_size, buf_size);
|
||||
return -1;
|
||||
s->error = JPEG_DECODER_ERROR_INPUTERROR;
|
||||
ret = -1;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
ret = init_read_bits(&s->gb, unescaped_buf_ptr, unescaped_buf_size*8);
|
||||
|
||||
if (ret < 0) {
|
||||
s->error = JPEG_DECODER_ERROR_INVPTR;
|
||||
loge("invalid buffer");
|
||||
goto fail;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
s->start_code = start_code;
|
||||
@@ -628,12 +682,13 @@ int __mjpeg_decode_frame(struct mpp_decoder *ctx)
|
||||
}
|
||||
|
||||
ret = -1;
|
||||
|
||||
switch (start_code) {
|
||||
case DQT:
|
||||
ret = mjpeg_decode_dqt(s);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret < 0) {
|
||||
s->error = JPEG_DECODER_ERROR_INPUTERROR;
|
||||
goto _exit;
|
||||
}
|
||||
break;
|
||||
case SOI:
|
||||
s->restart_interval = 0;
|
||||
@@ -644,43 +699,56 @@ int __mjpeg_decode_frame(struct mpp_decoder *ctx)
|
||||
s->have_dht = 1;
|
||||
if ((ret = mjpeg_decode_dht(s)) < 0) {
|
||||
loge("huffman table decode error");
|
||||
goto fail;
|
||||
s->error = JPEG_DECODER_ERROR_INPUTERROR;
|
||||
goto _exit;
|
||||
}
|
||||
break;
|
||||
case SOF0:
|
||||
logi("baseline");
|
||||
case SOF1:
|
||||
logi("SOF1");
|
||||
if ((ret = mjpeg_decode_sof(s)) < 0)
|
||||
goto fail;
|
||||
if ((ret = mjpeg_decode_sof(s)) < 0) {
|
||||
loge("mjpeg_decode_sof");
|
||||
s->error = JPEG_DECODER_ERROR_INPUTERROR;
|
||||
goto _exit;
|
||||
}
|
||||
break;
|
||||
case SOF2:
|
||||
loge("progressive, not support");
|
||||
if ((ret = mjpeg_decode_sof(s)) < 0)
|
||||
goto fail;
|
||||
if ((ret = mjpeg_decode_sof(s)) < 0) {
|
||||
loge("mjpeg_decode_sof");
|
||||
s->error = JPEG_DECODER_ERROR_INPUTERROR;
|
||||
goto _exit;
|
||||
}
|
||||
break;
|
||||
case LSE:
|
||||
break;
|
||||
case EOI:
|
||||
if (!s->got_picture) {
|
||||
logw("Found EOI before any SOF, ignoring");
|
||||
loge("Found EOI before any SOF, skip");
|
||||
break;
|
||||
}
|
||||
ret = 0;
|
||||
s->got_picture = 0;
|
||||
|
||||
goto the_end;
|
||||
goto _exit;
|
||||
case SOS:
|
||||
s->raw_scan_buffer = buf_ptr;
|
||||
s->raw_scan_buffer_size = buf_end - buf_ptr;
|
||||
|
||||
if ((ret = mjpeg_decode_sos(s, NULL, 0)) != 0)
|
||||
goto fail;
|
||||
|
||||
pm_enqueue_empty_packet(s->decoder.pm, s->curr_packet);
|
||||
goto the_end;
|
||||
if ((ret = mjpeg_decode_sos(s, NULL, 0)) != 0) {
|
||||
if (ret == DEC_NO_EMPTY_FRAME) {
|
||||
s->error = JPEG_DECODER_ERROR_NOEMPTYFRAME;
|
||||
} else {
|
||||
loge("mjpeg_decode_sos error\n");
|
||||
}
|
||||
}
|
||||
goto _exit;
|
||||
case DRI:
|
||||
if ((ret = mjpeg_decode_dri(s)) < 0)
|
||||
return ret;
|
||||
if ((ret = mjpeg_decode_dri(s)) < 0) {
|
||||
loge("mjpeg_decode_dri error\n");
|
||||
s->error = JPEG_DECODER_ERROR_INPUTERROR;
|
||||
goto _exit;
|
||||
}
|
||||
break;
|
||||
case SOF3:
|
||||
case SOF48:
|
||||
@@ -707,13 +775,22 @@ int __mjpeg_decode_frame(struct mpp_decoder *ctx)
|
||||
//logd("marker parser used %d bytes (%d bits)", (read_bits_count(&s->gb) + 7) / 8, read_bits_count(&s->gb));
|
||||
}
|
||||
|
||||
loge("No JPEG data found in image");
|
||||
return -1;
|
||||
fail:
|
||||
_exit:
|
||||
s->got_picture = 0;
|
||||
|
||||
if (s->error == JPEG_DECODER_ERROR_HARDWARE) {
|
||||
fm_decoder_put_frame(s->decoder.fm, s->curr_frame);
|
||||
fm_decoder_frame_to_render(s->decoder.fm, s->curr_frame, 0);
|
||||
}
|
||||
|
||||
if (s->error != JPEG_DECODER_ERROR_NOEMPTYFRAME) {
|
||||
pm_enqueue_empty_packet(s->decoder.pm, s->curr_packet);
|
||||
if (s->error != JPEG_DECODER_ERROR_NONE) {
|
||||
mjpeg_print_decoder_error(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
the_end:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __mjpeg_decode_init(struct mpp_decoder *ctx, struct decode_config *config)
|
||||
@@ -742,6 +819,10 @@ int __mjpeg_decode_init(struct mpp_decoder *ctx, struct decode_config *config)
|
||||
cfg.buffer_size = config->bitstream_buffer_size;
|
||||
cfg.packet_count = config->packet_count;
|
||||
s->decoder.pm = pm_create(&cfg);
|
||||
if (!s->decoder.pm) {
|
||||
loge("pm_create error");
|
||||
return -1;
|
||||
}
|
||||
s->extra_frame_num = config->extra_frame_num;
|
||||
s->start_code = -1;
|
||||
s->first_picture = 1;
|
||||
@@ -751,8 +832,11 @@ int __mjpeg_decode_init(struct mpp_decoder *ctx, struct decode_config *config)
|
||||
logw("default pix fmt %d", MPP_FMT_YUV420P);
|
||||
|
||||
s->reg_list = mpp_alloc(sizeof(jpg_reg_list));
|
||||
if(!s->reg_list)
|
||||
if (!s->reg_list) {
|
||||
loge("mpp_alloc jpg_reg_list error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(s->reg_list, 0, sizeof(jpg_reg_list));
|
||||
|
||||
return 0;
|
||||
@@ -794,6 +878,7 @@ int __mjpeg_decode_reset(struct mpp_decoder *ctx)
|
||||
{
|
||||
// TODO
|
||||
struct mjpeg_dec_ctx *s = (struct mjpeg_dec_ctx *)ctx;
|
||||
fm_decoder_reclaim_all_used_frame(s->decoder.fm);
|
||||
fm_reset(s->decoder.fm);
|
||||
pm_reset(s->decoder.pm);
|
||||
return 0;
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Artinchip Technology Co. Ltd
|
||||
*
|
||||
* author: <qi.xu@artinchip.com>
|
||||
* Desc: jpeg decode context define
|
||||
*
|
||||
*/
|
||||
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* author: <qi.xu@artinchip.com>
|
||||
* Desc: jpeg decode context define
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MJPEG_DECODER_H
|
||||
#define MJPEG_DECODER_H
|
||||
@@ -26,6 +28,16 @@
|
||||
#define JPEG400 5
|
||||
#define JPEGERR 6
|
||||
|
||||
enum decoder_err{
|
||||
JPEG_DECODER_ERROR_NONE = 0, /* ok */
|
||||
JPEG_DECODER_ERROR_INPUTLEN, /* input packet too small */
|
||||
JPEG_DECODER_ERROR_INPUTERROR, /* input packet data error */
|
||||
JPEG_DECODER_ERROR_INVPTR, /* invalid (null) buffer pointer */
|
||||
JPEG_DECODER_ERROR_NOEMPTYFRAME, /* no empty frame for decoder */
|
||||
JPEG_DECODER_ERROR_UNSUPPORTTYPE, /* unsupport type */
|
||||
JPEG_DECODER_ERROR_HARDWARE, /* an error happen whlie hard decoder processing */
|
||||
};
|
||||
|
||||
struct jpeg_huffman_table {
|
||||
unsigned short start_code[16]; // start_code[i], the minimum code of huffman code length i
|
||||
unsigned short max_code[16]; // max_code[i], the max code of huffman code length i
|
||||
@@ -91,6 +103,7 @@ struct mjpeg_dec_ctx {
|
||||
int h_offset[MAX_COMPONENTS]; // hor crop offset after post-process
|
||||
int v_offset[MAX_COMPONENTS]; // ver crop offset after post-process
|
||||
int extra_frame_num;
|
||||
int error;
|
||||
};
|
||||
|
||||
#endif /* MJPEG_DECODER_H */
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Artinchip Technology Co. Ltd
|
||||
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* author: <qi.xu@artinchip.com>
|
||||
* Desc: png decode
|
||||
*
|
||||
@@ -347,6 +348,20 @@ static int decode_fctl_chunk(struct png_dec_ctx *s, uint32_t length)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef AIC_VE_DRV_V10
|
||||
static int memset_last_row_data(struct png_dec_ctx *s)
|
||||
{
|
||||
// if filter type of first line > 1.
|
||||
// memset the last row buffer
|
||||
unsigned char* addr = (unsigned char*)(unsigned long)s->curr_frame->mpp_frame.buf.phy_addr[0] + s->stride*(s->height-2);
|
||||
memset(addr, 0, s->stride*2);
|
||||
aicos_dcache_clean_range(addr, s->stride*2);
|
||||
// ----- end ----------
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int decode_frame_common(struct png_dec_ctx *s)
|
||||
{
|
||||
uint32_t tag, length;
|
||||
@@ -449,7 +464,9 @@ exit_loop:
|
||||
pm_reclaim_ready_packet(s->decoder.pm, s->curr_packet);
|
||||
return DEC_NO_EMPTY_FRAME;
|
||||
}
|
||||
|
||||
#ifdef AIC_VE_DRV_V10
|
||||
memset_last_row_data(s);
|
||||
#endif
|
||||
logd("png_hardware_decode vir:%p phy: %lx %d", s->idat_mpp_buf->vir_addr,
|
||||
s->idat_mpp_buf->phy_addr,s->idat_mpp_buf->size);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Artinchip Technology Co. Ltd
|
||||
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* author: <qi.xu@artinchip.com>
|
||||
* Desc: png register configure
|
||||
*
|
||||
@@ -116,103 +117,106 @@ static void png_set_clip_info(struct png_dec_ctx *s)
|
||||
|
||||
int png_hardware_decode(struct png_dec_ctx *s, unsigned char *buf, int length)
|
||||
{
|
||||
struct png_register_list *reg_list = (struct png_register_list *)s->reg_list;
|
||||
u32 *pval;
|
||||
u32 val;
|
||||
struct png_register_list *reg_list = (struct png_register_list *)s->reg_list;
|
||||
u32 *pval;
|
||||
u32 val;
|
||||
|
||||
memset(reg_list, 0, sizeof(struct png_register_list));
|
||||
s->hw_size = s->stride * s->height;
|
||||
memset(reg_list, 0, sizeof(struct png_register_list));
|
||||
s->hw_size = s->stride * s->height;
|
||||
|
||||
ve_get_client();
|
||||
ve_get_client();
|
||||
|
||||
//* 1. reset ve
|
||||
config_ve_top_reg(s);
|
||||
png_reset(s);
|
||||
// 1. reset ve
|
||||
config_ve_top_reg(s);
|
||||
png_reset(s);
|
||||
|
||||
//* 2.set png info
|
||||
pval = (u32 *)®_list->_10_png_ctrl;
|
||||
reg_list->_10_png_ctrl.bit_depth = s->bit_depth;
|
||||
reg_list->_10_png_ctrl.color_type = s->color_type;
|
||||
reg_list->_10_png_ctrl.dec_type = 1;
|
||||
write_reg_u32(s->regs_base + PNG_CTRL_REG, *pval);
|
||||
// 2.set png info
|
||||
pval = (u32 *)®_list->_10_png_ctrl;
|
||||
reg_list->_10_png_ctrl.bit_depth = s->bit_depth;
|
||||
reg_list->_10_png_ctrl.color_type = s->color_type;
|
||||
reg_list->_10_png_ctrl.dec_type = 1;
|
||||
write_reg_u32(s->regs_base + PNG_CTRL_REG, *pval);
|
||||
|
||||
//* 3. set picture size
|
||||
pval = (u32 *)®_list->_14_png_size;
|
||||
reg_list->_14_png_size.width = s->width;
|
||||
reg_list->_14_png_size.height = s->height;
|
||||
write_reg_u32(s->regs_base + PNG_SIZE_REG, *pval);
|
||||
// 3. set picture size
|
||||
pval = (u32 *)®_list->_14_png_size;
|
||||
reg_list->_14_png_size.width = s->width;
|
||||
reg_list->_14_png_size.height = s->height;
|
||||
write_reg_u32(s->regs_base + PNG_SIZE_REG, *pval);
|
||||
|
||||
write_reg_u32(s->regs_base + PNG_STRIDE_REG, s->curr_frame->mpp_frame.buf.stride[0]);
|
||||
write_reg_u32(s->regs_base + PNG_STRIDE_REG, s->curr_frame->mpp_frame.buf.stride[0]);
|
||||
|
||||
int format = 0;
|
||||
if(s->pix_fmt == MPP_FMT_RGBA_8888)
|
||||
format = RGBA8888;
|
||||
else if(s->pix_fmt == MPP_FMT_BGRA_8888)
|
||||
format = BGRA8888;
|
||||
else if(s->pix_fmt == MPP_FMT_ABGR_8888)
|
||||
format = ABGR8888;
|
||||
else if(s->pix_fmt == MPP_FMT_ARGB_8888)
|
||||
format = ARGB8888;
|
||||
else if(s->pix_fmt == MPP_FMT_BGR_888)
|
||||
format = BGR888;
|
||||
else if(s->pix_fmt == MPP_FMT_RGB_888)
|
||||
format = RGB888;
|
||||
else if(s->pix_fmt == MPP_FMT_BGR_565)
|
||||
format = BGR565;
|
||||
else if(s->pix_fmt == MPP_FMT_RGB_565)
|
||||
format = RGB565;
|
||||
int format = 0;
|
||||
if(s->pix_fmt == MPP_FMT_RGBA_8888)
|
||||
format = RGBA8888;
|
||||
else if(s->pix_fmt == MPP_FMT_BGRA_8888)
|
||||
format = BGRA8888;
|
||||
else if(s->pix_fmt == MPP_FMT_ABGR_8888)
|
||||
format = ABGR8888;
|
||||
else if(s->pix_fmt == MPP_FMT_ARGB_8888)
|
||||
format = ARGB8888;
|
||||
else if(s->pix_fmt == MPP_FMT_BGR_888)
|
||||
format = BGR888;
|
||||
else if(s->pix_fmt == MPP_FMT_RGB_888)
|
||||
format = RGB888;
|
||||
else if(s->pix_fmt == MPP_FMT_BGR_565)
|
||||
format = BGR565;
|
||||
else if(s->pix_fmt == MPP_FMT_RGB_565)
|
||||
format = RGB565;
|
||||
|
||||
write_reg_u32(s->regs_base + PNG_FORMAT_REG, format);
|
||||
write_reg_u32(s->regs_base + PNG_FORMAT_REG, format);
|
||||
|
||||
//* 4. set output buffer
|
||||
// 4. set output buffer
|
||||
int channel = (s->pix_fmt == MPP_FMT_BGR_888 || s->pix_fmt == MPP_FMT_RGB_888) ? 3 : 4;
|
||||
int stride = s->curr_frame->mpp_frame.buf.stride[0];
|
||||
int out_offset = s->decoder.output_y * stride + s->decoder.output_x * channel;
|
||||
val = s->curr_frame->phy_addr[0] + out_offset;
|
||||
write_reg_u32(s->regs_base + OUTPUT_BUFFER_ADDR_REG, val);
|
||||
val = s->curr_frame->phy_addr[0] + out_offset;
|
||||
write_reg_u32(s->regs_base + OUTPUT_BUFFER_ADDR_REG, val);
|
||||
|
||||
val = s->curr_frame->phy_addr[0] + s->height * stride;
|
||||
write_reg_u32(s->regs_base + OUTPUT_BUFFER_LENGTH_REG, val);
|
||||
#ifdef AIC_VE_DRV_V10
|
||||
write_reg_u32(s->regs_base + OUTPUT_BUFFER_LENGTH_REG, s->height * stride);
|
||||
#else
|
||||
write_reg_u32(s->regs_base + OUTPUT_BUFFER_LENGTH_REG, s->curr_frame->phy_addr[0] + s->height * stride);
|
||||
#endif
|
||||
|
||||
//* 5. set LZ77 buffer 32K
|
||||
val = s->lz77_mpp_buf->phy_addr;
|
||||
write_reg_u32(s->regs_base + INFLATE_WINDOW_BUFFER_ADDR_REG, val);
|
||||
// 5. set LZ77 buffer 32K
|
||||
val = s->lz77_mpp_buf->phy_addr;
|
||||
write_reg_u32(s->regs_base + INFLATE_WINDOW_BUFFER_ADDR_REG, val);
|
||||
|
||||
//* PNG filter line buffer address
|
||||
// PNG filter line buffer address
|
||||
val = s->filter_mpp_buf->phy_addr;
|
||||
write_reg_u32(s->regs_base + PNG_FILTER_LINE_BUF_ADDR_REG, val);
|
||||
|
||||
//* 6. set memory register for palette
|
||||
if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||
unsigned char* palette_buf = (unsigned char*)&s->palette;
|
||||
memcpy(s->palette_mpp_buf->vir_addr, palette_buf, 256 * 4);
|
||||
ve_buffer_sync(s->palette_mpp_buf, CACHE_CLEAN);
|
||||
// 6. set memory register for palette
|
||||
if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||
unsigned char* palette_buf = (unsigned char*)&s->palette;
|
||||
memcpy(s->palette_mpp_buf->vir_addr, palette_buf, 256 * 4);
|
||||
ve_buffer_sync(s->palette_mpp_buf, CACHE_CLEAN);
|
||||
|
||||
val = s->palette_mpp_buf->phy_addr;
|
||||
write_reg_u32(s->regs_base + PNG_PNG_PALETTE_ADDR_REG, val);
|
||||
}
|
||||
val = s->palette_mpp_buf->phy_addr;
|
||||
write_reg_u32(s->regs_base + PNG_PNG_PALETTE_ADDR_REG, val);
|
||||
}
|
||||
|
||||
//* 7. set clip info
|
||||
// 7. set clip info
|
||||
png_set_clip_info(s);
|
||||
|
||||
//* 8. decode start
|
||||
logd("config start");
|
||||
write_reg_u32(s->regs_base + INFLATE_INTERRUPT_REG, 15);
|
||||
write_reg_u32(s->regs_base + INFLATE_STATUS_REG, 15);
|
||||
write_reg_u32(s->regs_base + INFLATE_START_REG, 7);
|
||||
// 8. decode start
|
||||
logd("config start");
|
||||
write_reg_u32(s->regs_base + INFLATE_INTERRUPT_REG, 15);
|
||||
write_reg_u32(s->regs_base + INFLATE_STATUS_REG, 15);
|
||||
write_reg_u32(s->regs_base + INFLATE_START_REG, 7);
|
||||
|
||||
//* 9.set bitstream
|
||||
if (set_bitstream_and_wait(s, buf, length)) {
|
||||
ve_put_client();
|
||||
return -1;
|
||||
}
|
||||
// 9.set bitstream
|
||||
if (set_bitstream_and_wait(s, buf, length)) {
|
||||
ve_put_client();
|
||||
return -1;
|
||||
}
|
||||
|
||||
val = read_reg_u32(s->regs_base + PNG_COUNT_REG);
|
||||
logi("png clock: %d", val);
|
||||
val = read_reg_u32(s->regs_base + PNG_COUNT_REG);
|
||||
logi("png clock: %d", val);
|
||||
|
||||
// disable png module
|
||||
write_reg_u32(s->regs_base + VE_PNG_EN_REG, 0);
|
||||
ve_put_client();
|
||||
// disable png module
|
||||
write_reg_u32(s->regs_base + VE_PNG_EN_REG, 0);
|
||||
ve_put_client();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
360
packages/artinchip/mpp/ve/encoder/jpeg/jpeg_enc.c
Normal file
360
packages/artinchip/mpp/ve/encoder/jpeg/jpeg_enc.c
Normal file
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Author: <qi.xu@artinchip.com>
|
||||
* Desc: jpeg encoder
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "ve.h"
|
||||
#include "ve_buffer.h"
|
||||
#include "put_bits.h"
|
||||
#include "jpeg_tables.h"
|
||||
#include "jpeg_enc_ctx.h"
|
||||
#include "mpp_mem.h"
|
||||
#include "mpp_log.h"
|
||||
|
||||
static s32 __mjpeg_encode_init(struct mpp_encoder *ctx, struct encode_config *config)
|
||||
{
|
||||
if (!ctx || !config)
|
||||
return -1;
|
||||
|
||||
struct jpeg_ctx *impl = (struct jpeg_ctx *)ctx;
|
||||
|
||||
impl->ve_fd = ve_open_device();
|
||||
if (impl->ve_fd < 0) {
|
||||
loge("ve open failed");
|
||||
return -1;
|
||||
}
|
||||
impl->config.quality = config->quality;
|
||||
impl->regs_base = ve_get_reg_base();
|
||||
impl->alloc = ve_buffer_allocator_create(VE_BUFFER_TYPE_DMA);
|
||||
|
||||
mjpeg_build_huffman_codes(impl->huff_size_dc_luminance,
|
||||
impl->huff_code_dc_luminance,
|
||||
avpriv_mjpeg_bits_dc_luminance,
|
||||
avpriv_mjpeg_val_dc);
|
||||
mjpeg_build_huffman_codes(impl->huff_size_dc_chrominance,
|
||||
impl->huff_code_dc_chrominance,
|
||||
avpriv_mjpeg_bits_dc_chrominance,
|
||||
avpriv_mjpeg_val_dc);
|
||||
mjpeg_build_huffman_codes(impl->huff_size_ac_luminance,
|
||||
impl->huff_code_ac_luminance,
|
||||
avpriv_mjpeg_bits_ac_luminance,
|
||||
avpriv_mjpeg_val_ac_luminance);
|
||||
mjpeg_build_huffman_codes(impl->huff_size_ac_chrominance,
|
||||
impl->huff_code_ac_chrominance,
|
||||
avpriv_mjpeg_bits_ac_chrominance,
|
||||
avpriv_mjpeg_val_ac_chrominance);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 __mjpeg_encode_destroy(struct mpp_encoder *ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return -1;
|
||||
|
||||
struct jpeg_ctx *impl = (struct jpeg_ctx *)ctx;
|
||||
|
||||
ve_close_device();
|
||||
ve_buffer_allocator_destroy(impl->alloc);
|
||||
mpp_free(impl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* table_class: 0 = DC coef, 1 = AC coefs */
|
||||
static int put_huffman_table(struct put_bit_ctx *p, int table_class, int table_id,
|
||||
const uint8_t *bits_table, const uint8_t *value_table)
|
||||
{
|
||||
int n, i;
|
||||
|
||||
put_bits(p, 4, table_class);
|
||||
put_bits(p, 4, table_id);
|
||||
|
||||
n = 0;
|
||||
for (i = 1; i <= 16; i++) {
|
||||
n += bits_table[i];
|
||||
put_bits(p, 8, bits_table[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
put_bits(p, 8, value_table[i]);
|
||||
|
||||
return n + 17;
|
||||
}
|
||||
|
||||
static inline void put_marker(struct put_bit_ctx *p, enum JpegMarker code)
|
||||
{
|
||||
put_bits(p, 8, 0xff);
|
||||
put_bits(p, 8, code);
|
||||
}
|
||||
|
||||
static void jpeg_table_header(struct jpeg_ctx* s, struct put_bit_ctx *p)
|
||||
{
|
||||
int i, j, size;
|
||||
uint8_t *ptr;
|
||||
|
||||
/* quant matrixes */
|
||||
put_marker(p, DQT);
|
||||
put_bits(p, 16, 2 + 2 * (1 + 64));
|
||||
put_bits(p, 4, 0); /* 8 bit precision */
|
||||
put_bits(p, 4, 0); /* table 0 */
|
||||
for (i = 0; i < 64; i++) {
|
||||
j = zigzag_direct[i];
|
||||
put_bits(p, 8, s->luma_quant_table[j]);
|
||||
}
|
||||
|
||||
put_bits(p, 4, 0); /* 8 bit precision */
|
||||
put_bits(p, 4, 1); /* table 1 */
|
||||
for (i = 0; i < 64; i++) {
|
||||
j = zigzag_direct[i];
|
||||
put_bits(p, 8, s->chroma_quant_table[j]);
|
||||
}
|
||||
|
||||
/* huffman table */
|
||||
put_marker(p, DHT);
|
||||
flush_put_bits(p);
|
||||
ptr = put_bits_ptr(p);
|
||||
put_bits(p, 16, 0); /* patched later */
|
||||
size = 2;
|
||||
|
||||
size += put_huffman_table(p, 0, 0, avpriv_mjpeg_bits_dc_luminance,
|
||||
avpriv_mjpeg_val_dc);
|
||||
size += put_huffman_table(p, 0, 1, avpriv_mjpeg_bits_dc_chrominance,
|
||||
avpriv_mjpeg_val_dc);
|
||||
|
||||
size += put_huffman_table(p, 1, 0, avpriv_mjpeg_bits_ac_luminance,
|
||||
avpriv_mjpeg_val_ac_luminance);
|
||||
size += put_huffman_table(p, 1, 1, avpriv_mjpeg_bits_ac_chrominance,
|
||||
avpriv_mjpeg_val_ac_chrominance);
|
||||
|
||||
ptr[0] = (size >> 8) & 0xff;
|
||||
ptr[1] = (size) & 0xff;
|
||||
}
|
||||
|
||||
static void jpeg_encode_pic_header(struct jpeg_ctx* s)
|
||||
{
|
||||
put_marker(&s->pb, SOI);
|
||||
jpeg_table_header(s, &s->pb);
|
||||
|
||||
put_marker(&s->pb, SOF0);
|
||||
int len = 2 + 1 + 2 + 2 + 1 + 3 * s->comp_num;
|
||||
put_bits(&s->pb, 16, len);
|
||||
put_bits(&s->pb, 8, 8); /* precision 8 bits/component */
|
||||
|
||||
if (s->cur_frame->buf.crop_en) {
|
||||
put_bits(&s->pb, 16, s->cur_frame->buf.crop.height);
|
||||
put_bits(&s->pb, 16, s->cur_frame->buf.crop.width);
|
||||
} else {
|
||||
put_bits(&s->pb, 16, s->height);
|
||||
put_bits(&s->pb, 16, s->width);
|
||||
}
|
||||
put_bits(&s->pb, 8, s->comp_num); /* 3 or 4 components */
|
||||
|
||||
/* Y component */
|
||||
put_bits(&s->pb, 8, 1); /* component number */
|
||||
put_bits(&s->pb, 4, s->h_count[0]); /* H factor */
|
||||
put_bits(&s->pb, 4, s->v_count[0]); /* V factor */
|
||||
put_bits(&s->pb, 8, 0); /* select quant table */
|
||||
|
||||
if (s->comp_num > 1) {
|
||||
/* Cb */
|
||||
put_bits(&s->pb, 8, 2); /* component number */
|
||||
put_bits(&s->pb, 4, s->h_count[1]); /* H factor */
|
||||
put_bits(&s->pb, 4, s->v_count[1]); /* V factor */
|
||||
put_bits(&s->pb, 8, 1); /* select quant table */
|
||||
|
||||
/* Cr */
|
||||
put_bits(&s->pb, 8, 3); /* component number */
|
||||
put_bits(&s->pb, 4, s->h_count[2]); /* H factor */
|
||||
put_bits(&s->pb, 4, s->v_count[2]); /* V factor */
|
||||
put_bits(&s->pb, 8, 1); /* select quant table */
|
||||
}
|
||||
|
||||
logi("offset: %d", put_bits_count(&s->pb) / 8);
|
||||
// the start address of VE must be 8 bytes aligned,
|
||||
// we cannot pad 0x00 here, because some customer app
|
||||
// cannot compatible this case.
|
||||
// So we use COM marker.
|
||||
int pad = (put_bits_count(&s->pb) / 8) % 8;
|
||||
if (pad) {
|
||||
pad = 8 - pad;
|
||||
if (pad < 4) {
|
||||
pad += 8;
|
||||
}
|
||||
|
||||
put_marker(&s->pb, COM);
|
||||
put_bits(&s->pb, 16, pad-2); // length
|
||||
|
||||
pad -= 4;
|
||||
while (pad--) {
|
||||
put_bits(&s->pb, 8, 0);
|
||||
}
|
||||
}
|
||||
flush_put_bits(&s->pb);
|
||||
|
||||
s->header_offset = put_bits_count(&s->pb) / 8;
|
||||
}
|
||||
|
||||
static void jpeg_init_hvcount(struct jpeg_ctx* s)
|
||||
{
|
||||
s->h_count[1] = s->h_count[2] = 1;
|
||||
s->v_count[1] = s->v_count[2] = 1;
|
||||
s->comp_num = 3;
|
||||
s->uv_interleave = 0;
|
||||
if (s->cur_frame->buf.format == MPP_FMT_YUV400) {
|
||||
s->h_count[0] = s->v_count[0] = 1;
|
||||
s->comp_num = 1;
|
||||
} else if (s->cur_frame->buf.format == MPP_FMT_YUV444P) {
|
||||
s->h_count[0] = s->v_count[0] = 1;
|
||||
} else if (s->cur_frame->buf.format == MPP_FMT_YUV420P ||
|
||||
s->cur_frame->buf.format == MPP_FMT_NV12) {
|
||||
s->h_count[0] = s->v_count[0] = 2;
|
||||
s->uv_interleave = s->cur_frame->buf.format != MPP_FMT_YUV420P;
|
||||
} else if (s->cur_frame->buf.format == MPP_FMT_YUV422P) {
|
||||
s->h_count[0] = 2;
|
||||
s->v_count[0] = 1;
|
||||
} else {
|
||||
loge("not supprt this format: %d", s->cur_frame->buf.format);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_quality(struct jpeg_ctx* s)
|
||||
{
|
||||
int i;
|
||||
if (s->quality <= 0)
|
||||
s->quality = 1;
|
||||
if (s->quality > 100)
|
||||
s->quality = 100;
|
||||
|
||||
// 1. quality = 1, produce "worst" quality, 5000*std_quant_table
|
||||
// 2. quality = 50, produce "good" quality, std_quant_table
|
||||
// 3. quality =100, produce "best" quality, the value of table are all 1
|
||||
if (s->quality < 50) {
|
||||
s->quality = 5000 / s->quality;
|
||||
} else {
|
||||
s->quality = 200 - s->quality * 2;
|
||||
}
|
||||
|
||||
for (i=0; i<64; i++) {
|
||||
s->luma_quant_table[i] = (std_luminance_quant_tbl[i] * s->quality + 50) / 100;
|
||||
if (s->luma_quant_table[i] <= 0)
|
||||
s->luma_quant_table[i] = 1;
|
||||
if (s->luma_quant_table[i] > 255)
|
||||
s->luma_quant_table[i] = 255;
|
||||
|
||||
s->chroma_quant_table[i] = (std_chrominance_quant_tbl[i] * s->quality + 50) / 100;
|
||||
if (s->chroma_quant_table[i] <= 0)
|
||||
s->chroma_quant_table[i] = 1;
|
||||
if (s->chroma_quant_table[i] > 255)
|
||||
s->chroma_quant_table[i] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
int __mpp_encode_jpeg(struct mpp_encoder *ctx, struct mpp_frame* frame, struct mpp_packet* packet)
|
||||
{
|
||||
if (!ctx)
|
||||
return -1;
|
||||
|
||||
struct jpeg_ctx *s = (struct jpeg_ctx *)ctx;
|
||||
|
||||
int ret = 0;
|
||||
int i;
|
||||
int comp = 3;
|
||||
|
||||
if (frame->buf.format == MPP_FMT_NV12) {
|
||||
comp = 2;
|
||||
} else if (frame->buf.format == MPP_FMT_YUV420P
|
||||
|| frame->buf.format == MPP_FMT_YUV422P) {
|
||||
comp = 3;
|
||||
} else if (frame->buf.format == MPP_FMT_YUV400) {
|
||||
comp = 1;
|
||||
} else {
|
||||
loge("unsupport format, %d", frame->buf.format);
|
||||
return -1;
|
||||
}
|
||||
|
||||
s->width = frame->buf.size.width;
|
||||
s->height = frame->buf.size.height;
|
||||
s->quality = s->config.quality;
|
||||
s->y_stride = frame->buf.stride[0];
|
||||
|
||||
set_quality(s);
|
||||
|
||||
s->stream_num = packet->size / 256;
|
||||
s->bitstream_vir_addr = (unsigned char *)(unsigned long)packet->phy_addr;
|
||||
s->bitstream_phy_addr = packet->phy_addr;
|
||||
|
||||
s->cur_frame = frame;
|
||||
|
||||
init_put_bits(&s->pb, s->bitstream_vir_addr, packet->size);
|
||||
for (i=0; i<comp; i++) {
|
||||
s->phy_addr[i] = frame->buf.phy_addr[i];
|
||||
}
|
||||
|
||||
jpeg_init_hvcount(s);
|
||||
jpeg_encode_pic_header(s);
|
||||
// we should flush (s->header_offset + 64) bytes, because
|
||||
// flush_put_bits will write some data of SOS
|
||||
ve_buffer_sync_range(NULL, s->bitstream_vir_addr, s->header_offset + 64, CACHE_CLEAN);
|
||||
|
||||
if (jpeg_hw_encode(s) < 0) {
|
||||
loge("encode failed");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (s->encode_data_len > packet->size) {
|
||||
loge("buf len(%d) is too small, we need (%d) bytes",
|
||||
packet->size, s->encode_data_len + s->header_offset);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
packet->len = s->encode_data_len;
|
||||
ve_buffer_sync_range(NULL, s->bitstream_vir_addr, s->encode_data_len, CACHE_INVALID);
|
||||
|
||||
out:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int __mjpeg_encode_control(struct mpp_encoder *ctx, int cmd, void *param)
|
||||
{
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __mjpeg_encode_reset(struct mpp_encoder *ctx)
|
||||
{
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct enc_ops mjpeg_encoder = {
|
||||
.name = "mjpeg",
|
||||
.init = __mjpeg_encode_init,
|
||||
.destory = __mjpeg_encode_destroy,
|
||||
.encode = __mpp_encode_jpeg,
|
||||
.control = __mjpeg_encode_control,
|
||||
.reset = __mjpeg_encode_reset,
|
||||
};
|
||||
|
||||
struct mpp_encoder* create_jpeg_encoder()
|
||||
{
|
||||
struct jpeg_ctx *s = (struct jpeg_ctx*)mpp_alloc(sizeof(struct jpeg_ctx));
|
||||
if(s == NULL) {
|
||||
loge("malloc jpeg_ctx failed");
|
||||
return NULL;
|
||||
}
|
||||
memset(s, 0, sizeof(struct jpeg_ctx));
|
||||
|
||||
s->encoder.ops = &mjpeg_encoder;
|
||||
|
||||
return &s->encoder;
|
||||
}
|
||||
145
packages/artinchip/mpp/ve/encoder/jpeg/jpeg_enc_ctx.h
Normal file
145
packages/artinchip/mpp/ve/encoder/jpeg/jpeg_enc_ctx.h
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Author: <qi.xu@artinchip.com>
|
||||
* Desc: jpeg enc context
|
||||
*/
|
||||
|
||||
#ifndef JPEG_ENC_CTX_H
|
||||
#define JPEG_ENC_CTX_H
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "put_bits.h"
|
||||
#include "jpeg_tables.h"
|
||||
#include "mpp_codec.h"
|
||||
|
||||
#define QUANT_FIXED_POINT_BITS 19
|
||||
#define ALIGN_4K(x) (((x) + 4095) & ~(4095))
|
||||
|
||||
/* JPEG marker codes */
|
||||
enum JpegMarker {
|
||||
/* start of frame */
|
||||
SOF0 = 0xc0, /* baseline */
|
||||
SOF1 = 0xc1, /* extended sequential, huffman */
|
||||
SOF2 = 0xc2, /* progressive, huffman */
|
||||
SOF3 = 0xc3, /* lossless, huffman */
|
||||
|
||||
SOF5 = 0xc5, /* differential sequential, huffman */
|
||||
SOF6 = 0xc6, /* differential progressive, huffman */
|
||||
SOF7 = 0xc7, /* differential lossless, huffman */
|
||||
JPG = 0xc8, /* reserved for JPEG extension */
|
||||
SOF9 = 0xc9, /* extended sequential, arithmetic */
|
||||
SOF10 = 0xca, /* progressive, arithmetic */
|
||||
SOF11 = 0xcb, /* lossless, arithmetic */
|
||||
|
||||
SOF13 = 0xcd, /* differential sequential, arithmetic */
|
||||
SOF14 = 0xce, /* differential progressive, arithmetic */
|
||||
SOF15 = 0xcf, /* differential lossless, arithmetic */
|
||||
|
||||
DHT = 0xc4, /* define huffman tables */
|
||||
|
||||
DAC = 0xcc, /* define arithmetic-coding conditioning */
|
||||
|
||||
/* restart with modulo 8 count "m" */
|
||||
RST0 = 0xd0,
|
||||
RST1 = 0xd1,
|
||||
RST2 = 0xd2,
|
||||
RST3 = 0xd3,
|
||||
RST4 = 0xd4,
|
||||
RST5 = 0xd5,
|
||||
RST6 = 0xd6,
|
||||
RST7 = 0xd7,
|
||||
|
||||
SOI = 0xd8, /* start of image */
|
||||
EOI = 0xd9, /* end of image */
|
||||
SOS = 0xda, /* start of scan */
|
||||
DQT = 0xdb, /* define quantization tables */
|
||||
DNL = 0xdc, /* define number of lines */
|
||||
DRI = 0xdd, /* define restart interval */
|
||||
DHP = 0xde, /* define hierarchical progression */
|
||||
EXP = 0xdf, /* expand reference components */
|
||||
|
||||
APP0 = 0xe0,
|
||||
APP1 = 0xe1,
|
||||
APP2 = 0xe2,
|
||||
APP3 = 0xe3,
|
||||
APP4 = 0xe4,
|
||||
APP5 = 0xe5,
|
||||
APP6 = 0xe6,
|
||||
APP7 = 0xe7,
|
||||
APP8 = 0xe8,
|
||||
APP9 = 0xe9,
|
||||
APP10 = 0xea,
|
||||
APP11 = 0xeb,
|
||||
APP12 = 0xec,
|
||||
APP13 = 0xed,
|
||||
APP14 = 0xee,
|
||||
APP15 = 0xef,
|
||||
|
||||
JPG0 = 0xf0,
|
||||
JPG1 = 0xf1,
|
||||
JPG2 = 0xf2,
|
||||
JPG3 = 0xf3,
|
||||
JPG4 = 0xf4,
|
||||
JPG5 = 0xf5,
|
||||
JPG6 = 0xf6,
|
||||
SOF48 = 0xf7, ///< JPEG-LS
|
||||
LSE = 0xf8, ///< JPEG-LS extension parameters
|
||||
JPG9 = 0xf9,
|
||||
JPG10 = 0xfa,
|
||||
JPG11 = 0xfb,
|
||||
JPG12 = 0xfc,
|
||||
JPG13 = 0xfd,
|
||||
|
||||
COM = 0xfe, /* comment */
|
||||
|
||||
TEM = 0x01, /* temporary private use for arithmetic coding */
|
||||
/* 0x02 -> 0xbf reserved */
|
||||
};
|
||||
|
||||
struct jpeg_ctx {
|
||||
struct mpp_encoder encoder;
|
||||
unsigned int luma_quant_table[64];
|
||||
unsigned int chroma_quant_table[64];
|
||||
uint8_t huff_size_dc_luminance[12]; ///< DC luminance Huffman table size.
|
||||
uint16_t huff_code_dc_luminance[12]; ///< DC luminance Huffman table codes.
|
||||
uint8_t huff_size_dc_chrominance[12]; ///< DC chrominance Huffman table size.
|
||||
uint16_t huff_code_dc_chrominance[12]; ///< DC chrominance Huffman table codes.
|
||||
uint8_t huff_size_ac_luminance[256]; ///< AC luminance Huffman table size.
|
||||
uint16_t huff_code_ac_luminance[256]; ///< AC luminance Huffman table codes.
|
||||
uint8_t huff_size_ac_chrominance[256]; ///< AC chrominance Huffman table size.
|
||||
uint16_t huff_code_ac_chrominance[256]; ///< AC chrominance Huffman table codes.
|
||||
|
||||
int uv_interleave;
|
||||
int h_count[4];
|
||||
int v_count[4];
|
||||
int comp_num;
|
||||
int width;
|
||||
int height;
|
||||
int y_stride;
|
||||
int quality;
|
||||
int header_offset;
|
||||
|
||||
struct mpp_frame* cur_frame;
|
||||
|
||||
unsigned int phy_addr[3];
|
||||
|
||||
int encode_data_len;
|
||||
|
||||
int ve_fd;
|
||||
unsigned long regs_base;
|
||||
struct ve_buffer_allocator *alloc;
|
||||
|
||||
unsigned char* bitstream_vir_addr;
|
||||
unsigned int bitstream_phy_addr;
|
||||
int stream_num;
|
||||
struct put_bit_ctx pb;
|
||||
struct encode_config config;
|
||||
};
|
||||
|
||||
int jpeg_hw_encode(struct jpeg_ctx *s);
|
||||
|
||||
#endif
|
||||
244
packages/artinchip/mpp/ve/encoder/jpeg/jpeg_enc_hal.c
Normal file
244
packages/artinchip/mpp/ve/encoder/jpeg/jpeg_enc_hal.c
Normal file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Author: <qi.xu@artinchip.com>
|
||||
* Desc: jpeg encoder hal
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "ve_top_register.h"
|
||||
#include "jpeg_register.h"
|
||||
#include "mpp_log.h"
|
||||
#include "ve_buffer.h"
|
||||
#include "ve.h"
|
||||
#include "jpeg_enc_ctx.h"
|
||||
|
||||
static void config_ve_top_reg(struct jpeg_ctx *s)
|
||||
{
|
||||
logd("config mjpeg reg");
|
||||
write_reg_u32(s->regs_base + VE_CLK_REG, 1);
|
||||
write_reg_u32(s->regs_base + VE_RST_REG, RST_JPG_PIC_MODULE);
|
||||
|
||||
while (1) {
|
||||
uint32_t val = read_reg_u32(s->regs_base + VE_RST_REG);
|
||||
if ((val >> 16) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
write_reg_u32(s->regs_base + VE_INIT_REG, 1);
|
||||
write_reg_u32(s->regs_base + VE_IRQ_REG, 1);
|
||||
write_reg_u32(s->regs_base + VE_JPG_EN_REG, 1);
|
||||
}
|
||||
|
||||
static void config_header_info(struct jpeg_ctx *s)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
write_reg_u32(s->regs_base + JPG_START_POS_REG, 0);
|
||||
|
||||
write_reg_u32(s->regs_base + JPG_CTRL_REG, (3 << 12) | (3 << 8) | (3 << 3));
|
||||
|
||||
int width_align = (s->width + 15) & (~15);
|
||||
val = s->height | (width_align << 16);
|
||||
write_reg_u32(s->regs_base + JPG_SIZE_REG, val);
|
||||
|
||||
int total_blks = s->h_count[0] * s->v_count[0] +
|
||||
s->h_count[1] * s->v_count[1] + s->h_count[2] * s->v_count[2];
|
||||
val = s->v_count[2] | (s->h_count[2] << 2) |
|
||||
(s->v_count[1] << 4) | (s->h_count[1] << 6) |
|
||||
(s->v_count[0] << 8) | (s->h_count[0] << 10) |
|
||||
(s->comp_num << 12) | (total_blks << 16);
|
||||
write_reg_u32(s->regs_base + JPG_MCU_INFO_REG, val);
|
||||
|
||||
val = 12 / total_blks;
|
||||
write_reg_u32(s->regs_base + JPG_HANDLE_NUM_REG, val);
|
||||
|
||||
write_reg_u32(s->regs_base + JPG_UV_REG, s->uv_interleave);
|
||||
write_reg_u32(s->regs_base + JPG_FRAME_IDX_REG, 0);
|
||||
write_reg_u32(s->regs_base + JPG_RST_INTERVAL_REG, 0);
|
||||
write_reg_u32(s->regs_base + JPG_INTRRUPT_EN_REG, 0);
|
||||
}
|
||||
|
||||
static void config_picture_info_register(struct jpeg_ctx *s)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
uint32_t color_mode = 0;
|
||||
|
||||
if (s->cur_frame->buf.format == MPP_FMT_YUV420P || s->cur_frame->buf.format == MPP_FMT_NV12) {
|
||||
color_mode = 0;
|
||||
} else if (s->cur_frame->buf.format == MPP_FMT_YUV444P) {
|
||||
color_mode = 3;
|
||||
} else if (s->cur_frame->buf.format == MPP_FMT_YUV400) {
|
||||
color_mode = 4;
|
||||
} else if (s->cur_frame->buf.format == MPP_FMT_YUV422P) {
|
||||
color_mode = 1;
|
||||
} else {
|
||||
loge("not supprt this format(%d)", s->cur_frame->buf.format);
|
||||
}
|
||||
|
||||
val = s->y_stride | (s->uv_interleave << 16) | (color_mode << 17);
|
||||
write_reg_u32(s->regs_base + PIC_INFO_START_REG, val);
|
||||
|
||||
val = s->height | (s->y_stride << 16);
|
||||
write_reg_u32(s->regs_base + PIC_INFO_START_REG + 4, val);
|
||||
write_reg_u32(s->regs_base + PIC_INFO_START_REG + 8, s->phy_addr[0]);
|
||||
write_reg_u32(s->regs_base + PIC_INFO_START_REG + 12, s->phy_addr[1]);
|
||||
write_reg_u32(s->regs_base + PIC_INFO_START_REG + 16, s->phy_addr[2]);
|
||||
}
|
||||
|
||||
/*
|
||||
quant matrix store in zigzag order
|
||||
*/
|
||||
static void ve_config_quant_matrix(struct jpeg_ctx *s)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
uint32_t val;
|
||||
unsigned int* quant_tab[3] = { s->luma_quant_table, s->chroma_quant_table, s->chroma_quant_table };
|
||||
for (int comp = 0; comp < 3; comp++) {
|
||||
write_reg_u32(s->regs_base + JPG_QMAT_INFO_REG, (comp << 6) | 3);
|
||||
write_reg_u32(s->regs_base + JPG_QMAT_ADDR_REG, comp << 6);
|
||||
for (i = 0; i < 64; i++) {
|
||||
j = zigzag_direct[i];
|
||||
// qmatrix should be (1<<19)/q
|
||||
val = (1 << QUANT_FIXED_POINT_BITS) / quant_tab[comp][j];
|
||||
write_reg_u32(s->regs_base + JPG_QMAT_VAL_REG, val);
|
||||
}
|
||||
}
|
||||
|
||||
write_reg_u32(s->regs_base + JPG_QMAT_INFO_REG, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
huffman table include 4 tables: DC_Luma\DC_Chroma\AC_LUMA\AC_Chroma
|
||||
internal SRAM in VE is 544x20bit
|
||||
20bit data: [19:16]: code_length-1; [15:0]: code word
|
||||
address of the 4 tables:
|
||||
Luma_AC: 0-255
|
||||
Chroma_AC: 256-511
|
||||
Luma_DC: 512-528
|
||||
Chroma_DC: 528-544
|
||||
*/
|
||||
static void ve_config_huffman_table(struct jpeg_ctx *s)
|
||||
{
|
||||
int i;
|
||||
uint32_t val;
|
||||
|
||||
write_reg_u32(s->regs_base + JPG_HUFF_INFO_REG, 3);
|
||||
write_reg_u32(s->regs_base + JPG_HUFF_ADDR_REG, 0);
|
||||
|
||||
// luma ac
|
||||
for (i = 0; i < 256; i++) {
|
||||
val = ((s->huff_size_ac_luminance[i] - 1) << 16) | s->huff_code_ac_luminance[i];
|
||||
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
|
||||
}
|
||||
|
||||
// chroma ac
|
||||
for (i = 0; i < 256; i++) {
|
||||
val = ((s->huff_size_ac_chrominance[i] - 1) << 16) | s->huff_code_ac_chrominance[i];
|
||||
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
|
||||
}
|
||||
|
||||
// luma dc
|
||||
for (i = 0; i < 12; i++) {
|
||||
val = ((s->huff_size_dc_luminance[i] - 1) << 16) | s->huff_code_dc_luminance[i];
|
||||
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
|
||||
}
|
||||
|
||||
// chroma dc
|
||||
write_reg_u32(s->regs_base + JPG_HUFF_INFO_REG, 3);
|
||||
write_reg_u32(s->regs_base + JPG_HUFF_ADDR_REG, 528);
|
||||
for (i = 0; i < 12; i++) {
|
||||
val = ((s->huff_size_dc_chrominance[i] - 1) << 16) | s->huff_code_dc_chrominance[i];
|
||||
write_reg_u32(s->regs_base + JPG_HUFF_VAL_REG, val);
|
||||
}
|
||||
|
||||
// clear
|
||||
write_reg_u32(s->regs_base + JPG_HUFF_INFO_REG, 0);
|
||||
}
|
||||
|
||||
static void ve_config_stream_register(struct jpeg_ctx *s)
|
||||
{
|
||||
int head_offset = s->header_offset;
|
||||
int stream_num = s->stream_num;
|
||||
// end addr of output stream
|
||||
unsigned int align_256_addr = s->bitstream_phy_addr + stream_num * 256;
|
||||
write_reg_u32(s->regs_base + JPG_STREAM_END_ADDR_REG, align_256_addr);
|
||||
// base addr of output stream
|
||||
write_reg_u32(s->regs_base + JPG_BAS_ADDR_REG, s->bitstream_phy_addr + head_offset);
|
||||
// start addr of output stream
|
||||
write_reg_u32(s->regs_base + JPG_STREAM_START_ADDR_REG, s->bitstream_phy_addr + head_offset);
|
||||
|
||||
write_reg_u32(s->regs_base + JPG_STREAM_WRITE_PTR_REG, s->bitstream_phy_addr + head_offset);
|
||||
write_reg_u32(s->regs_base + JPG_STREAM_READ_PTR_REG, s->bitstream_phy_addr + head_offset);
|
||||
|
||||
// current stream pos
|
||||
write_reg_u32(s->regs_base + JPG_CUR_POS_REG, 0);
|
||||
write_reg_u32(s->regs_base + JPG_DATA_CNT_REG, 64);
|
||||
|
||||
write_reg_u32(s->regs_base + JPG_MEM_EA_REG, 0x7f);
|
||||
write_reg_u32(s->regs_base + JPG_MEM_IA_REG, 0x40);
|
||||
write_reg_u32(s->regs_base + JPG_MEM_HA_REG, 0x40);
|
||||
|
||||
write_reg_u32(s->regs_base + JPG_BITREQ_EN_REG, 1);
|
||||
}
|
||||
|
||||
int jpeg_hw_encode(struct jpeg_ctx *s)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t status;
|
||||
|
||||
ve_get_client();
|
||||
|
||||
// 1. config ve top
|
||||
config_ve_top_reg(s);
|
||||
|
||||
// 2. config jpeg header
|
||||
config_header_info(s);
|
||||
|
||||
// 3. config picture info
|
||||
config_picture_info_register(s);
|
||||
|
||||
// 4. config quant/huffman table
|
||||
ve_config_quant_matrix(s);
|
||||
ve_config_huffman_table(s);
|
||||
|
||||
// 5. config bitstream
|
||||
ve_config_stream_register(s);
|
||||
|
||||
write_reg_u32(s->regs_base + JPG_STATUS_REG, 0xf);
|
||||
write_reg_u32(s->regs_base + JPG_START_REG, 1);
|
||||
|
||||
if (ve_wait((unsigned int*)&status) < 0) {
|
||||
loge("ve wait irq timeout");
|
||||
logi("read JPG_STATUS_REG %x", read_reg_u32(s->regs_base + JPG_STATUS_REG));
|
||||
|
||||
ve_reset();
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(status > 1) {
|
||||
loge("status error");
|
||||
ve_reset();
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
uint32_t cycles = 0;
|
||||
cycles = read_reg_u32(s->regs_base + JPG_CYCLES_REG);
|
||||
|
||||
uint32_t end_addr = 0;
|
||||
end_addr = read_reg_u32(s->regs_base + JPG_STREAM_WRITE_PTR_REG);
|
||||
s->encode_data_len = end_addr - s->bitstream_phy_addr;
|
||||
|
||||
logi("cycles: %"PRIu32", data len: %d", cycles, s->encode_data_len);
|
||||
|
||||
// disable jpeg module
|
||||
write_reg_u32(s->regs_base + VE_JPG_EN_REG, 0);
|
||||
|
||||
out:
|
||||
ve_put_client();
|
||||
return ret;
|
||||
}
|
||||
145
packages/artinchip/mpp/ve/encoder/jpeg/jpeg_tables.c
Normal file
145
packages/artinchip/mpp/ve/encoder/jpeg/jpeg_tables.c
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Author: <qi.xu@artinchip.com>
|
||||
* Desc: jpeg tables
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/****************** Quant Table *************************/
|
||||
/* These are the sample quantization tables given in JPEG spec section K.1.
|
||||
* The spec says that the values given produce "good" quality, and
|
||||
* when divided by 2, "very good" quality.
|
||||
*/
|
||||
const unsigned char std_luminance_quant_tbl[64] = {
|
||||
16, 11, 10, 16, 24, 40, 51, 61,
|
||||
12, 12, 14, 19, 26, 58, 60, 55,
|
||||
14, 13, 16, 24, 40, 57, 69, 56,
|
||||
14, 17, 22, 29, 51, 87, 80, 62,
|
||||
18, 22, 37, 56, 68, 109, 103, 77,
|
||||
24, 35, 55, 64, 81, 104, 113, 92,
|
||||
49, 64, 78, 87, 103, 121, 120, 101,
|
||||
72, 92, 95, 98, 112, 100, 103, 99
|
||||
};
|
||||
const unsigned char std_chrominance_quant_tbl[64] = {
|
||||
17, 18, 24, 47, 99, 99, 99, 99,
|
||||
18, 21, 26, 66, 99, 99, 99, 99,
|
||||
24, 26, 56, 99, 99, 99, 99, 99,
|
||||
47, 66, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99
|
||||
};
|
||||
|
||||
uint8_t zigzag_direct[64] = {
|
||||
0, 1, 8, 16, 9, 2, 3, 10,
|
||||
17, 24, 32, 25, 18, 11, 4, 5,
|
||||
12, 19, 26, 33, 40, 48, 41, 34,
|
||||
27, 20, 13, 6, 7, 14, 21, 28,
|
||||
35, 42, 49, 56, 57, 50, 43, 36,
|
||||
29, 22, 15, 23, 30, 37, 44, 51,
|
||||
58, 59, 52, 45, 38, 31, 39, 46,
|
||||
53, 60, 61, 54, 47, 55, 62, 63
|
||||
};
|
||||
|
||||
/****************** Huffman Table *************************/
|
||||
/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
|
||||
/* IMPORTANT: these are only valid for 8-bit data precision! */
|
||||
const uint8_t avpriv_mjpeg_bits_dc_luminance[17] =
|
||||
{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
|
||||
const uint8_t avpriv_mjpeg_val_dc[12] =
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
|
||||
|
||||
const uint8_t avpriv_mjpeg_bits_dc_chrominance[17] =
|
||||
{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
|
||||
|
||||
const uint8_t avpriv_mjpeg_bits_ac_luminance[17] =
|
||||
{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
|
||||
const uint8_t avpriv_mjpeg_val_ac_luminance[] =
|
||||
{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
|
||||
0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
|
||||
0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
|
||||
0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
|
||||
0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
|
||||
0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
|
||||
0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
|
||||
0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
|
||||
0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
|
||||
0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
|
||||
0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
|
||||
0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
|
||||
0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
|
||||
0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||
0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
|
||||
0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
|
||||
0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
|
||||
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
|
||||
0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
|
||||
0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
|
||||
0xf9, 0xfa
|
||||
};
|
||||
|
||||
const uint8_t avpriv_mjpeg_bits_ac_chrominance[17] =
|
||||
{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
|
||||
|
||||
const uint8_t avpriv_mjpeg_val_ac_chrominance[] =
|
||||
{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
|
||||
0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
|
||||
0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
|
||||
0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
|
||||
0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
|
||||
0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
|
||||
0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
|
||||
0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
|
||||
0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
|
||||
0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
|
||||
0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
|
||||
0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||||
0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
|
||||
0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
|
||||
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
|
||||
0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
|
||||
0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
|
||||
0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
|
||||
0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
|
||||
0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
|
||||
0xf9, 0xfa
|
||||
};
|
||||
|
||||
/* isn't this function nicer than the one in the libjpeg ? */
|
||||
void mjpeg_build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code,
|
||||
const uint8_t *bits_table,
|
||||
const uint8_t *val_table)
|
||||
{
|
||||
int i, j, k,nb, code, sym;
|
||||
|
||||
/* Some badly encoded files [1] map 2 different codes to symbol 0.
|
||||
Only the first one is valid, so we zero-initialize this here and
|
||||
make sure we only set it once (the first time) in the loop below.
|
||||
|
||||
[1]: Embedded JPEGs in "X7 RAW" and "X7 CinemaDNG" samples here:
|
||||
https://www.dji.com/gr/zenmuse-x7/info#downloads
|
||||
*/
|
||||
|
||||
huff_size[0] = 0;
|
||||
k = 0;
|
||||
code = 0;
|
||||
for(i=1;i<=16;i++) {
|
||||
nb = bits_table[i];
|
||||
for(j=0;j<nb;j++) {
|
||||
sym = val_table[k++];
|
||||
if (sym != 0 || huff_size[sym] == 0) { /* see comment above */
|
||||
huff_size[sym] = i;
|
||||
huff_code[sym] = code;
|
||||
}
|
||||
|
||||
code++;
|
||||
}
|
||||
code <<= 1;
|
||||
}
|
||||
}
|
||||
35
packages/artinchip/mpp/ve/encoder/jpeg/jpeg_tables.h
Normal file
35
packages/artinchip/mpp/ve/encoder/jpeg/jpeg_tables.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Author: <qi.xu@artinchip.com>
|
||||
* Desc: jpeg tables
|
||||
*/
|
||||
|
||||
#ifndef JPEG_TABLES_H
|
||||
#define JPEG_TABLES_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern const unsigned char std_luminance_quant_tbl[];
|
||||
extern const unsigned char std_chrominance_quant_tbl[];
|
||||
|
||||
extern const uint8_t avpriv_mjpeg_bits_dc_luminance[];
|
||||
extern const uint8_t avpriv_mjpeg_val_dc[];
|
||||
|
||||
extern const uint8_t avpriv_mjpeg_bits_dc_chrominance[];
|
||||
|
||||
extern const uint8_t avpriv_mjpeg_bits_ac_luminance[];
|
||||
extern const uint8_t avpriv_mjpeg_val_ac_luminance[];
|
||||
|
||||
extern const uint8_t avpriv_mjpeg_bits_ac_chrominance[];
|
||||
extern const uint8_t avpriv_mjpeg_val_ac_chrominance[];
|
||||
|
||||
extern uint8_t zigzag_direct[64];
|
||||
|
||||
void mjpeg_build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code,
|
||||
const uint8_t *bits_table,
|
||||
const uint8_t *val_table);
|
||||
|
||||
#endif
|
||||
143
packages/artinchip/mpp/ve/encoder/jpeg/put_bits.h
Normal file
143
packages/artinchip/mpp/ve/encoder/jpeg/put_bits.h
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Author: <qi.xu@artinchip.com>
|
||||
* Desc: put bits
|
||||
*/
|
||||
|
||||
#ifndef __PUT_BITS_H_
|
||||
#define __PUT_BITS_H_
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
#include "mpp_log.h"
|
||||
|
||||
static const int BUF_BITS = 8 * sizeof(uint32_t);
|
||||
|
||||
struct put_bit_ctx {
|
||||
uint32_t bit_buf;
|
||||
int bit_left;
|
||||
uint8_t *buf, *buf_ptr, *buf_end;
|
||||
int size_in_bits;
|
||||
};
|
||||
|
||||
static inline void init_put_bits(struct put_bit_ctx *s, uint8_t *buffer, int buffer_size)
|
||||
{
|
||||
if (buffer_size < 0) {
|
||||
buffer_size = 0;
|
||||
buffer = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
s->size_in_bits = 8 * buffer_size;
|
||||
s->buf = buffer;
|
||||
s->buf_end = s->buf + buffer_size;
|
||||
s->buf_ptr = s->buf;
|
||||
s->bit_left = BUF_BITS;
|
||||
s->bit_buf = 0;
|
||||
}
|
||||
|
||||
static inline int put_bits_count(struct put_bit_ctx *s)
|
||||
{
|
||||
return (s->buf_ptr - s->buf) * 8 + BUF_BITS - s->bit_left;
|
||||
}
|
||||
|
||||
static inline int put_bits_left(struct put_bit_ctx* s)
|
||||
{
|
||||
return (s->buf_end - s->buf_ptr) * 8 - BUF_BITS + s->bit_left;
|
||||
}
|
||||
|
||||
#define AV_BSWAP16C(x) (((x) << 8 & 0xff00) | ((x) >> 8 & 0x00ff))
|
||||
#define AV_BSWAP32C(x) (AV_BSWAP16C(x) << 16 | AV_BSWAP16C((x) >> 16))
|
||||
#define AV_WLBUF(p, v) (*((uint64_t *)(p)) = (v))
|
||||
#define AV_WBBUF(p, v) (*((uint64_t *)(p)) = (v))
|
||||
static inline void put_bits_no_assert(struct put_bit_ctx* s, int n, uint32_t value)
|
||||
{
|
||||
uint32_t bit_buf;
|
||||
int bit_left;
|
||||
|
||||
bit_buf = s->bit_buf;
|
||||
bit_left = s->bit_left;
|
||||
|
||||
if (n < bit_left) {
|
||||
bit_buf = (bit_buf << n) | value;
|
||||
bit_left -= n;
|
||||
} else {
|
||||
bit_buf <<= bit_left;
|
||||
bit_buf |= value >> (n - bit_left);
|
||||
if (s->buf_end - s->buf_ptr >= sizeof(uint32_t)) {
|
||||
AV_WBBUF(s->buf_ptr, AV_BSWAP32C(bit_buf));
|
||||
s->buf_ptr += sizeof(uint32_t);
|
||||
} else {
|
||||
loge("Internal error, put_bits buffer too small\n");
|
||||
mpp_assert(0);
|
||||
}
|
||||
bit_left += BUF_BITS - n;
|
||||
bit_buf = value;
|
||||
}
|
||||
|
||||
s->bit_buf = bit_buf;
|
||||
s->bit_left = bit_left;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write up to 31 bits into a bitstream.
|
||||
* Use put_bits32 to write 32 bits.
|
||||
*/
|
||||
static inline void put_bits(struct put_bit_ctx *s, int n, uint32_t value)
|
||||
{
|
||||
if(n <= 31 && value < (1UL << n)) {
|
||||
put_bits_no_assert(s, n, value);
|
||||
} else {
|
||||
loge("put bits fail, n: %d, val: 0x%"PRIx32"", n, value);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned av_mod_uintp2_c(unsigned a, unsigned p)
|
||||
{
|
||||
return a & ((1U << p) - 1);
|
||||
}
|
||||
|
||||
static inline void put_sbits(struct put_bit_ctx *pb, int n, int32_t value)
|
||||
{
|
||||
if (n < 0 || n > 31) {
|
||||
loge("put_sbits error");
|
||||
return;
|
||||
}
|
||||
|
||||
put_bits(pb, n, av_mod_uintp2_c(value, n));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pad the end of the output stream with zeros.
|
||||
*/
|
||||
static inline void flush_put_bits(struct put_bit_ctx *s)
|
||||
{
|
||||
if (s->bit_left < BUF_BITS)
|
||||
s->bit_buf <<= s->bit_left;
|
||||
while (s->bit_left < BUF_BITS) {
|
||||
mpp_assert(s->buf_ptr < s->buf_end);
|
||||
*s->buf_ptr++ = s->bit_buf >> (BUF_BITS - 8);
|
||||
s->bit_buf <<= 8;
|
||||
s->bit_left += 8;
|
||||
}
|
||||
s->bit_left = BUF_BITS;
|
||||
s->bit_buf = 0;
|
||||
}
|
||||
|
||||
static inline uint8_t *put_bits_ptr(struct put_bit_ctx *s)
|
||||
{
|
||||
return s->buf_ptr;
|
||||
}
|
||||
|
||||
static inline void skip_put_bytes(struct put_bit_ctx *s, int n)
|
||||
{
|
||||
mpp_assert((put_bits_count(s) & 7) == 0);
|
||||
mpp_assert(s->bit_left == BUF_BITS);
|
||||
mpp_assert(n <= s->buf_end - s->buf_ptr);
|
||||
s->buf_ptr += n;
|
||||
}
|
||||
|
||||
#endif
|
||||
56
packages/artinchip/mpp/ve/encoder/mpp_encoder.c
Normal file
56
packages/artinchip/mpp/ve/encoder/mpp_encoder.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2024 ArtInChip Technology Co. Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Author: <che.jiang@artinchip.com>
|
||||
* Desc: mpp_encoder interface
|
||||
*/
|
||||
|
||||
#include "mpp_codec.h"
|
||||
#include "frame_allocator.h"
|
||||
#include "mpp_log.h"
|
||||
|
||||
extern struct mpp_encoder *create_jpeg_encoder();
|
||||
|
||||
struct mpp_encoder *mpp_encoder_create(enum mpp_codec_type type)
|
||||
{
|
||||
if (type == MPP_CODEC_VIDEO_ENCODER_MJPEG)
|
||||
return create_jpeg_encoder();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void mpp_encoder_destory(struct mpp_encoder *encoder)
|
||||
{
|
||||
if (encoder == NULL)
|
||||
return;
|
||||
|
||||
encoder->ops->destory(encoder);
|
||||
}
|
||||
|
||||
int mpp_encoder_init(struct mpp_encoder *encoder, struct encode_config *config)
|
||||
{
|
||||
if (encoder == NULL || config == NULL)
|
||||
return ENC_ERR_NULL_PTR;
|
||||
|
||||
return encoder->ops->init(encoder, config);
|
||||
}
|
||||
|
||||
int mpp_encoder_encode(struct mpp_encoder *encoder, struct mpp_frame *frame, struct mpp_packet *packet)
|
||||
{
|
||||
if (encoder == NULL || frame == NULL || packet == NULL)
|
||||
return ENC_ERR_NULL_PTR;
|
||||
|
||||
return encoder->ops->encode(encoder, frame, packet);
|
||||
}
|
||||
|
||||
int mpp_encoder_control(struct mpp_encoder *encoder, int cmd, void *param)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mpp_encoder_reset(struct mpp_encoder *encoder)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -65,6 +65,11 @@ int fm_render_put_frame(struct frame_manager* fm, struct mpp_frame *frame);
|
||||
*/
|
||||
int fm_decoder_put_frame(struct frame_manager* fm, struct frame *frame);
|
||||
|
||||
/*
|
||||
decoder reclaim all used frame to frame_manager.the frame will not used by decoder any more.
|
||||
*/
|
||||
int fm_decoder_reclaim_all_used_frame(struct frame_manager* fm);
|
||||
|
||||
/*
|
||||
get a empty frame for decoder.
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Artinchip Technology Co. Ltd
|
||||
*
|
||||
* author: <qi.xu@artinchip.com>
|
||||
* Desc: interface of decode libs
|
||||
*/
|
||||
* Copyright (C) 2020-2024 Artinchip Technology Co. Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Author: <qi.xu@artinchip.com>
|
||||
* Desc: interface of decode and encoder libs
|
||||
*/
|
||||
|
||||
#ifndef MPP_CODEC_H
|
||||
#define MPP_CODEC_H
|
||||
@@ -12,6 +14,7 @@
|
||||
#include "frame_manager.h"
|
||||
#include "packet_manager.h"
|
||||
#include "mpp_decoder.h"
|
||||
#include "mpp_encoder.h"
|
||||
#include "frame_allocator.h"
|
||||
|
||||
#define ALIGN_8B(x) (((x) + (7)) & ~(7))
|
||||
@@ -22,16 +25,20 @@ struct mpp_decoder {
|
||||
struct packet_manager* pm;
|
||||
struct frame_manager* fm;
|
||||
struct frame_allocator* allocator;
|
||||
int rotmir_flag; // only used for jpeg
|
||||
int hor_scale; // only used for jpeg
|
||||
int ver_scale; // only used for jpeg
|
||||
int crop_en;
|
||||
int crop_x;
|
||||
int crop_y;
|
||||
int crop_width;
|
||||
int crop_height;
|
||||
int output_x;
|
||||
int output_y;
|
||||
int rotmir_flag; // only used for jpeg
|
||||
int hor_scale; // only used for jpeg
|
||||
int ver_scale; // only used for jpeg
|
||||
int crop_en;
|
||||
int crop_x;
|
||||
int crop_y;
|
||||
int crop_width;
|
||||
int crop_height;
|
||||
int output_x;
|
||||
int output_y;
|
||||
};
|
||||
|
||||
struct mpp_encoder {
|
||||
struct enc_ops *ops;
|
||||
};
|
||||
|
||||
struct dec_ops {
|
||||
@@ -44,4 +51,13 @@ struct dec_ops {
|
||||
int (*reset)(struct mpp_decoder *ctx);
|
||||
};
|
||||
|
||||
struct enc_ops {
|
||||
const char *name;
|
||||
|
||||
int (*init)(struct mpp_encoder *ctx, struct encode_config *config);
|
||||
int (*destory)(struct mpp_encoder *ctx);
|
||||
int (*encode)(struct mpp_encoder *ctx, struct mpp_frame *frame, struct mpp_packet *packet);
|
||||
int (*control)(struct mpp_encoder *ctx, int cmd, void *param);
|
||||
int (*reset)(struct mpp_encoder *ctx);
|
||||
};
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user