This commit is contained in:
刘可亮
2024-09-03 11:16:08 +08:00
parent cf270df8d6
commit 803cac77d5
2931 changed files with 614364 additions and 31222 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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 *)&reg_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 *)&reg_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 *)&reg_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 *)&reg_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;
}

View 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;
}

View 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

View 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;
}

View 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;
}
}

View 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

View 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

View 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;
}

View File

@@ -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.

View File

@@ -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