mirror of
https://gitee.com/Vancouver2017/luban-lite-t3e-pro.git
synced 2025-12-14 18:38:55 +00:00
1169 lines
38 KiB
C
1169 lines
38 KiB
C
/*
|
|
* 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"
|
|
#include "h264_nal.h"
|
|
#include "read_bits.h"
|
|
#include "mpp_mem.h"
|
|
#include "mpp_log.h"
|
|
|
|
#define BASELINE_PROFILE 66
|
|
#define MAIN_PROFILE 77
|
|
#define EXTEND_PROFILE 88
|
|
#define HIGH_PROFILE 100
|
|
|
|
#define MAX_FRAME_NUM 18
|
|
|
|
#define MIN(a,b) ((a) > (b) ? (b) : (a))
|
|
static const u8 default_scaling4[2][16]=
|
|
{
|
|
{
|
|
6,13,20,28,
|
|
13,20,28,32,
|
|
20,28,32,37,
|
|
28,32,37,42
|
|
},
|
|
{
|
|
10,14,20,24,
|
|
14,20,24,27,
|
|
20,24,27,30,
|
|
24,27,30,34
|
|
}
|
|
};
|
|
|
|
static const u8 default_scaling8[2][64]=
|
|
{
|
|
{
|
|
6,10,13,16,18,23,25,27,
|
|
10,11,16,18,23,25,27,29,
|
|
13,16,18,23,25,27,29,31,
|
|
16,18,23,25,27,29,31,33,
|
|
18,23,25,27,29,31,33,36,
|
|
23,25,27,29,31,33,36,38,
|
|
25,27,29,31,33,36,38,40,
|
|
27,29,31,33,36,38,40,42
|
|
},
|
|
{
|
|
9,13,15,17,19,21,22,24,
|
|
13,13,17,19,21,22,24,25,
|
|
15,17,19,21,22,24,25,27,
|
|
17,19,21,22,24,25,27,28,
|
|
19,21,22,24,25,27,28,30,
|
|
21,22,24,25,27,28,30,32,
|
|
22,24,25,27,28,30,32,33,
|
|
24,25,27,28,30,32,33,35
|
|
}
|
|
};
|
|
|
|
static const u8 zigzag_scan[16]=
|
|
{
|
|
0+0*4, 1+0*4, 0+1*4, 0+2*4,
|
|
1+1*4, 2+0*4, 3+0*4, 2+1*4,
|
|
1+2*4, 0+3*4, 1+3*4, 2+2*4,
|
|
3+1*4, 3+2*4, 2+3*4, 3+3*4,
|
|
};
|
|
|
|
static const u8 zigzag_scan8x8[64]=
|
|
{
|
|
0+0*8, 1+0*8, 0+1*8, 0+2*8,
|
|
1+1*8, 2+0*8, 3+0*8, 2+1*8,
|
|
1+2*8, 0+3*8, 0+4*8, 1+3*8,
|
|
2+2*8, 3+1*8, 4+0*8, 5+0*8,
|
|
4+1*8, 3+2*8, 2+3*8, 1+4*8,
|
|
0+5*8, 0+6*8, 1+5*8, 2+4*8,
|
|
3+3*8, 4+2*8, 5+1*8, 6+0*8,
|
|
7+0*8, 6+1*8, 5+2*8, 4+3*8,
|
|
3+4*8, 2+5*8, 1+6*8, 0+7*8,
|
|
1+7*8, 2+6*8, 3+5*8, 4+4*8,
|
|
5+3*8, 6+2*8, 7+1*8, 7+2*8,
|
|
6+3*8, 5+4*8, 4+5*8, 3+6*8,
|
|
2+7*8, 3+7*8, 4+6*8, 5+5*8,
|
|
6+4*8, 7+3*8, 7+4*8, 6+5*8,
|
|
5+6*8, 4+7*8, 5+7*8, 6+6*8,
|
|
7+5*8, 7+6*8, 6+7*8, 7+7*8,
|
|
};
|
|
|
|
static int dec_ref_pic_marking(struct h264_dec_ctx *s)
|
|
{
|
|
struct h264_slice_header* sh = &s->sh;
|
|
int nb_mmco = 0;
|
|
int i;
|
|
|
|
if(s->idr_pic_flag == 1) { // NAL_IDR
|
|
read_bits(&s->gb, 1); // no_output_of_prior_pics_flag
|
|
if(read_bits(&s->gb, 1)) {
|
|
sh->mmco[0].opcode = MMCO_LONG;
|
|
sh->mmco[0].long_arg = 0;
|
|
nb_mmco = 1;
|
|
}
|
|
sh->explicit_ref_marking = 1;
|
|
} else {
|
|
sh->explicit_ref_marking = read_bits(&s->gb, 1);
|
|
if(sh->explicit_ref_marking) {
|
|
for(i=0; i<MAX_MMCO_COUNT; i++) {
|
|
enum mmco_opcode opcode = read_ue_golomb(&s->gb);
|
|
|
|
sh->mmco[i].opcode = opcode;
|
|
if(opcode == MMCO_SHORT2UNUSED || opcode == MMCO_SHORT2LONG) {
|
|
sh->mmco[i].short_pic_num = (sh->cur_pic_num - read_ue_golomb(&s->gb) -1) &
|
|
(sh->max_pic_num -1);
|
|
}
|
|
if(opcode == MMCO_SHORT2LONG || opcode == MMCO_LONG2UNUSED ||
|
|
opcode == MMCO_LONG || opcode == MMCO_SET_MAX_LONG) {
|
|
unsigned int long_arg = read_ue_golomb(&s->gb);
|
|
if (long_arg >= 32 ||
|
|
(long_arg >= 16 && !(opcode == MMCO_SET_MAX_LONG &&
|
|
long_arg == 16) &&
|
|
!(opcode == MMCO_LONG2UNUSED && s->picture_structure != PICT_FRAME))) {
|
|
loge("illegal long ref in memory management control operation %d", opcode);
|
|
sh->nb_mmco = i;
|
|
return -1;
|
|
}
|
|
sh->mmco[i].long_arg = long_arg;
|
|
}
|
|
|
|
if(opcode > (unsigned)MMCO_LONG) {
|
|
loge("illegal memory management control operation %d", opcode);
|
|
sh->nb_mmco = i;
|
|
return -1;
|
|
}
|
|
|
|
if(opcode == MMCO_END)
|
|
break;
|
|
}
|
|
nb_mmco = i;
|
|
}
|
|
}
|
|
sh->nb_mmco = nb_mmco;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int pred_weight_table(struct h264_dec_ctx *s)
|
|
{
|
|
int list, i, j;
|
|
struct h264_sps_info* cur_sps = s->sps_buffers[s->active_sps_id];
|
|
struct h264_slice_header* sh = &s->sh;
|
|
struct pred_weight_table* pwt = &sh->pwt;
|
|
int luma_def = 0, chroma_def = 0;
|
|
|
|
pwt->luma_log2_weight_denom = read_ue_golomb(&s->gb);
|
|
if(pwt->luma_log2_weight_denom > 7) {
|
|
loge("luma_log2_weight_denom(%d) out of range", pwt->luma_log2_weight_denom);
|
|
pwt->luma_log2_weight_denom = 0;
|
|
}
|
|
luma_def = 1 << pwt->luma_log2_weight_denom;
|
|
|
|
if(cur_sps->chroma_format_idc) {
|
|
pwt->chroma_log2_weight_denom = read_ue_golomb(&s->gb);
|
|
if(pwt->chroma_log2_weight_denom > 7) {
|
|
loge("chroma_log2_weight_denom(%d) out of range", pwt->chroma_log2_weight_denom);
|
|
pwt->chroma_log2_weight_denom = 0;
|
|
}
|
|
chroma_def = 1 << pwt->chroma_log2_weight_denom;
|
|
}
|
|
|
|
for(list=0; list<2; list++) {
|
|
for(i=0; i<sh->num_ref_idx[list]; i++) {
|
|
if(read_bits(&s->gb, 1)) {
|
|
pwt->wp_weight[list][i][0] = read_se_golomb(&s->gb);
|
|
pwt->wp_offset[list][i][0] = read_se_golomb(&s->gb);
|
|
} else {
|
|
pwt->wp_weight[list][i][0] = luma_def;
|
|
pwt->wp_offset[list][i][0] = 0;
|
|
}
|
|
|
|
if(cur_sps->chroma_format_idc) {
|
|
if(read_bits(&s->gb, 1)) {
|
|
for(j=1; j<3; j++) {
|
|
pwt->wp_weight[list][i][j] = read_se_golomb(&s->gb);
|
|
pwt->wp_offset[list][i][j] = read_se_golomb(&s->gb);
|
|
}
|
|
} else {
|
|
for(j=1; j<3; j++) {
|
|
pwt->wp_weight[list][i][j] = chroma_def;
|
|
pwt->wp_offset[list][i][j] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(sh->slice_type != H264_SLICE_B)
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int h264_alloc_frame_buffer(struct h264_dec_ctx *s)
|
|
{
|
|
int i;
|
|
logi("h264_alloc_frame_buffer");
|
|
int field_col_buf_size = 0;
|
|
int total_col_buf_size = 0;
|
|
int dblk_y_buf_size = 0;
|
|
int dblk_c_buf_size = 0;
|
|
int intrap_buf_size = 0;
|
|
int mb_info_buf_size = 0;
|
|
int mb_col_info_size = 0;
|
|
struct h264_sps_info* cur_sps = s->sps_buffers[s->active_sps_id];
|
|
|
|
s->frame_info.max_valid_frame_num = cur_sps->max_num_ref_frames + 1 + s->extra_frame_num;
|
|
|
|
if(s->frame_info.max_valid_frame_num > MAX_FRAME_NUM) {
|
|
s->frame_info.max_valid_frame_num = MAX_FRAME_NUM;
|
|
if(cur_sps->max_num_ref_frames > 13)
|
|
s->has_b_frames = 0;
|
|
}
|
|
|
|
logi("ref_num: %d, has_b_frame: %d, extra_num: %d",
|
|
cur_sps->max_num_ref_frames, s->has_b_frames, s->extra_frame_num);
|
|
|
|
if(cur_sps->chroma_format_idc == 0) {
|
|
s->pix_format = MPP_FMT_YUV400;
|
|
}
|
|
|
|
// 1. create frame manager, alloc frame buffer
|
|
struct frame_manager_init_cfg cfg;
|
|
cfg.frame_count = s->frame_info.max_valid_frame_num;
|
|
cfg.height = s->height;
|
|
cfg.width = s->width;
|
|
cfg.height_align = s->height;
|
|
cfg.stride = s->width;
|
|
cfg.pixel_format = s->pix_format;
|
|
cfg.allocator = s->decoder.allocator;
|
|
s->decoder.fm = fm_create(&cfg);
|
|
|
|
// 2. create physic buffer for co-located buffer
|
|
field_col_buf_size = cur_sps->pic_mb_height * (2 - cur_sps->frame_mbs_only_flag);
|
|
field_col_buf_size = (field_col_buf_size + 1) / 2;
|
|
field_col_buf_size = cur_sps->pic_mb_width * field_col_buf_size * 32;
|
|
if(cur_sps->direct_8x8_inference_flag == 0)
|
|
field_col_buf_size *= 2;
|
|
field_col_buf_size = (field_col_buf_size + 1023) & (~1023); // 1024 byte align
|
|
|
|
total_col_buf_size = field_col_buf_size * 2 * s->frame_info.max_valid_frame_num;
|
|
s->frame_info.col_buf = ve_buffer_alloc(s->ve_buf_handle, total_col_buf_size, 0);
|
|
if(s->frame_info.col_buf == NULL) {
|
|
loge("alloc col_buf failed");
|
|
return -1;
|
|
}
|
|
|
|
for(i=0; i<s->frame_info.max_valid_frame_num; i++) {
|
|
s->frame_info.picture[i].top_field_col_addr = s->frame_info.col_buf->phy_addr + i*2*field_col_buf_size;
|
|
s->frame_info.picture[i].bot_field_col_addr = s->frame_info.col_buf->phy_addr + (i*2+1)*field_col_buf_size;
|
|
s->frame_info.picture[i].frame = NULL;
|
|
}
|
|
|
|
// 3. create physic buffer used by dblk
|
|
dblk_y_buf_size = (cur_sps->pic_mb_width + 1)*16*4*(2 - cur_sps->frame_mbs_only_flag);
|
|
dblk_c_buf_size = (cur_sps->pic_mb_width + 1)*16*4*(2 - cur_sps->frame_mbs_only_flag);
|
|
s->frame_info.dblk_y_buf = ve_buffer_alloc(s->ve_buf_handle, dblk_y_buf_size, 0);
|
|
s->frame_info.dblk_c_buf = ve_buffer_alloc(s->ve_buf_handle, dblk_c_buf_size, 0);
|
|
if(s->frame_info.dblk_y_buf == NULL || s->frame_info.dblk_c_buf == NULL) {
|
|
loge("alloc dblk buffer failed");
|
|
return -1;
|
|
}
|
|
|
|
// 4. create physic buffer for intrap
|
|
intrap_buf_size = cur_sps->pic_mb_width * 16 * 2 * (2 - cur_sps->frame_mbs_only_flag);
|
|
s->frame_info.intrap_buf = ve_buffer_alloc(s->ve_buf_handle, intrap_buf_size, 0);
|
|
if(s->frame_info.intrap_buf == NULL) {
|
|
loge("alloc intrap buffer failed");
|
|
return -1;
|
|
}
|
|
|
|
// 5. create mb info buffer
|
|
mb_info_buf_size = 12*1024;
|
|
s->frame_info.mb_info_buf = ve_buffer_alloc(s->ve_buf_handle, mb_info_buf_size, 0);
|
|
if(s->frame_info.mb_info_buf == NULL) {
|
|
loge("alloc mb_info buffer failed");
|
|
return -1;
|
|
}
|
|
|
|
// 6. create mb co-located info buffer
|
|
mb_col_info_size = 68*1024;
|
|
s->frame_info.mb_col_info_buf = ve_buffer_alloc(s->ve_buf_handle, mb_col_info_size, 0);
|
|
if(s->frame_info.mb_col_info_buf == NULL) {
|
|
loge("alloc mb_col_info_buf buffer failed");
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int decode_scaling_list(struct read_bit_context *gb, uint8_t *factors, int size,
|
|
const uint8_t *jvt_list,
|
|
const uint8_t *fallback_list)
|
|
{
|
|
int i, last = 8, next = 8;
|
|
const uint8_t *scan = size == 16 ? zigzag_scan : zigzag_scan8x8;
|
|
if (!read_bits(gb, 1)) /* matrix not written, we use the predicted one */
|
|
memcpy(factors, fallback_list, size * sizeof(uint8_t));
|
|
else
|
|
for (i = 0; i < size; i++) {
|
|
if (next) {
|
|
int v = read_se_golomb(gb);
|
|
if (v < -128 || v > 127) {
|
|
loge("delta scale %d is invalid", v);
|
|
return -1;
|
|
}
|
|
next = (last + v) & 0xff;
|
|
}
|
|
if (!i && !next) { /* matrix not written, we use the preset one */
|
|
memcpy(factors, jvt_list, size * sizeof(uint8_t));
|
|
break;
|
|
}
|
|
last = factors[scan[i]] = next ? next : last;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* returns non zero if the provided SPS scaling matrix has been filled */
|
|
static int decode_scaling_matrices(struct read_bit_context *gb, struct h264_sps_info *sps,
|
|
struct h264_pps_info *pps, int is_sps,
|
|
uint8_t(*scaling_matrix4)[16],
|
|
uint8_t(*scaling_matrix8)[64])
|
|
{
|
|
// 1) if decode scaling matrix in sps, fallback_sps is defalut scaling matrix;
|
|
// 2) if decode scaling matrix in pps, fallback_sps is scaling matrix in pps
|
|
int fallback_sps = !is_sps && sps->scaling_matrix_present_flag;
|
|
const uint8_t *fallback[4] = {
|
|
fallback_sps ? sps->scaling_matrix4[0] : default_scaling4[0],
|
|
fallback_sps ? sps->scaling_matrix4[3] : default_scaling4[1],
|
|
fallback_sps ? sps->scaling_matrix8[0] : default_scaling8[0],
|
|
fallback_sps ? sps->scaling_matrix8[1] : default_scaling8[1]
|
|
};
|
|
int ret = 0;
|
|
if (read_bits(gb, 1)) {
|
|
ret |= decode_scaling_list(gb, scaling_matrix4[0], 16, default_scaling4[0], fallback[0]); // Intra, Y
|
|
ret |= decode_scaling_list(gb, scaling_matrix4[1], 16, default_scaling4[0], scaling_matrix4[0]); // Intra, Cr
|
|
ret |= decode_scaling_list(gb, scaling_matrix4[2], 16, default_scaling4[0], scaling_matrix4[1]); // Intra, Cb
|
|
ret |= decode_scaling_list(gb, scaling_matrix4[3], 16, default_scaling4[1], fallback[1]); // Inter, Y
|
|
ret |= decode_scaling_list(gb, scaling_matrix4[4], 16, default_scaling4[1], scaling_matrix4[3]); // Inter, Cr
|
|
ret |= decode_scaling_list(gb, scaling_matrix4[5], 16, default_scaling4[1], scaling_matrix4[4]); // Inter, Cb
|
|
if (is_sps || pps->transform_8x8_mode_flag) {
|
|
ret |= decode_scaling_list(gb, scaling_matrix8[0], 64, default_scaling8[0], fallback[2]); // Intra, Y
|
|
ret |= decode_scaling_list(gb, scaling_matrix8[1], 64, default_scaling8[1], fallback[3]); // Inter, Y
|
|
}
|
|
if (!ret)
|
|
ret = is_sps;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void print_sps_info(struct h264_sps_info *sps)
|
|
{
|
|
logd("====== sps info ========");
|
|
logd("profile_idc: %d", sps->profile_idc);
|
|
logd("level_idc: %d", sps->level_idc);
|
|
logd("chroma_format_idc: %d", sps->chroma_format_idc);
|
|
logd("frame_mbs_only_flag: %d", sps->frame_mbs_only_flag);
|
|
logd("direct_8x8_inference_flag: %d", sps->direct_8x8_inference_flag);
|
|
logd("max_num_ref_frames: %d", sps->max_num_ref_frames);
|
|
logd("mb_width: %d, mb_height: %d", sps->pic_mb_width, sps->pic_mb_height);
|
|
logd("poc_type: %d", sps->poc_type);
|
|
logd("scaling_matrix_present_flag: %d", sps->scaling_matrix_present_flag);
|
|
logd("crop: l: %d, r: %d, t: %d, b: %d", sps->frame_cropping_rect_left_offset,
|
|
sps->frame_cropping_rect_right_offset, sps->frame_cropping_rect_top_offset,
|
|
sps->frame_cropping_rect_bottom_offset);
|
|
}
|
|
|
|
int h264_decode_sps(struct h264_dec_ctx *s)
|
|
{
|
|
struct h264_sps_info *sps = NULL;
|
|
int ret;
|
|
int i;
|
|
int constraint_set_flags = 0;
|
|
int profile_idc = read_bits(&s->gb, 8);
|
|
constraint_set_flags |= read_bits(&s->gb, 1);
|
|
constraint_set_flags |= read_bits(&s->gb, 1) << 1;
|
|
constraint_set_flags |= read_bits(&s->gb, 1) << 2;
|
|
constraint_set_flags |= read_bits(&s->gb, 1) << 3;
|
|
constraint_set_flags |= read_bits(&s->gb, 1) << 4;
|
|
constraint_set_flags |= read_bits(&s->gb, 1) << 5;
|
|
skip_bits(&s->gb, 2); // reserved
|
|
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));
|
|
if(NULL == s->sps_buffers[sps_id]) {
|
|
loge("malloc sps info fail");
|
|
return -1;
|
|
}
|
|
memset(s->sps_buffers[sps_id], 0, sizeof(struct h264_sps_info));
|
|
}
|
|
sps = s->sps_buffers[sps_id];
|
|
|
|
if(profile_idc != BASELINE_PROFILE && profile_idc != MAIN_PROFILE &&
|
|
profile_idc != EXTEND_PROFILE && profile_idc != HIGH_PROFILE) {
|
|
loge("unsupport profile(%d)", profile_idc);
|
|
return -1;
|
|
}
|
|
sps->level_idc = level_idc;
|
|
sps->profile_idc = profile_idc;
|
|
sps->constraint_set_flags = constraint_set_flags;
|
|
|
|
memset(sps->scaling_matrix4, 16, sizeof(sps->scaling_matrix4));
|
|
memset(sps->scaling_matrix8, 16, sizeof(sps->scaling_matrix8));
|
|
if(profile_idc == HIGH_PROFILE) {
|
|
s->sps_buffers[sps_id]->chroma_format_idc = read_ue_golomb(&s->gb);
|
|
if(s->sps_buffers[sps_id]->chroma_format_idc > 1) {
|
|
loge("unsupport chroma format(%d)", s->sps_buffers[sps_id]->chroma_format_idc);
|
|
return -1;
|
|
}
|
|
|
|
// luma/chroma bit depth
|
|
if(read_ue_golomb(&s->gb) || read_ue_golomb(&s->gb)) {
|
|
loge("unsupport bitdepth");
|
|
return -1;
|
|
}
|
|
|
|
read_bits(&s->gb, 1); // transform bypass
|
|
ret = decode_scaling_matrices(&s->gb, sps, NULL, 1, sps->scaling_matrix4, sps->scaling_matrix8);
|
|
if(ret < 0) {
|
|
loge("decode scaling matrix fail");
|
|
return -1;
|
|
}
|
|
|
|
sps->scaling_matrix_present_flag |= ret;
|
|
} else {
|
|
s->sps_buffers[sps_id]->chroma_format_idc = 1;
|
|
}
|
|
|
|
sps->log2_max_frm_num = read_ue_golomb(&s->gb) + 4;
|
|
sps->poc_type = read_ue_golomb(&s->gb);
|
|
|
|
if(sps->poc_type == 0) {
|
|
sps->log2_max_poc_lsb = read_ue_golomb(&s->gb) + 4;
|
|
} else if (sps->poc_type == 1) {
|
|
sps->delta_pic_order_always_zero_flag = read_bits(&s->gb, 1);
|
|
sps->offset_for_non_ref_pic = read_se_golomb(&s->gb);
|
|
sps->offset_for_top_to_bottom_field = read_se_golomb(&s->gb);
|
|
sps->num_ref_frames_in_poc_cycle = read_ue_golomb(&s->gb);
|
|
for(i=0; i<sps->num_ref_frames_in_poc_cycle; i++)
|
|
sps->offset_for_ref_frame[i] = read_se_golomb(&s->gb);
|
|
} else if (sps->poc_type != 2) {
|
|
loge("poc type error (%d)", sps->poc_type);
|
|
return -1;
|
|
}
|
|
|
|
sps->max_num_ref_frames = read_ue_golomb(&s->gb);
|
|
sps->gaps_in_frame_num_value_allowed_flag = read_bits(&s->gb, 1);
|
|
if (sps->gaps_in_frame_num_value_allowed_flag) {
|
|
//gaps_in_frame_num_value_allowed_flag
|
|
logw("gaps_in_frame_num_value_allowed_flag ==1, careful");
|
|
}
|
|
|
|
sps->pic_mb_width = read_ue_golomb(&s->gb) + 1;
|
|
sps->pic_mb_height = read_ue_golomb(&s->gb) + 1;
|
|
sps->frame_mbs_only_flag = read_bits(&s->gb, 1);
|
|
if(!sps->frame_mbs_only_flag)
|
|
sps->mbaff = read_bits(&s->gb, 1);
|
|
sps->direct_8x8_inference_flag = read_bits(&s->gb, 1);
|
|
|
|
if(read_bits(&s->gb, 1)) {
|
|
sps->frame_cropping_rect_left_offset = read_ue_golomb(&s->gb);
|
|
sps->frame_cropping_rect_right_offset = read_ue_golomb(&s->gb);
|
|
sps->frame_cropping_rect_top_offset = read_ue_golomb(&s->gb);
|
|
sps->frame_cropping_rect_bottom_offset = read_ue_golomb(&s->gb);
|
|
} else {
|
|
sps->frame_cropping_rect_left_offset = 0;
|
|
sps->frame_cropping_rect_right_offset = 0;
|
|
sps->frame_cropping_rect_top_offset = 0;
|
|
sps->frame_cropping_rect_bottom_offset = 0;
|
|
}
|
|
|
|
// skip vui parameter
|
|
print_sps_info(sps);
|
|
return 0;
|
|
}
|
|
|
|
static int more_rbsp_data_in_pps(struct h264_sps_info *sps)
|
|
{
|
|
int profile_idc = sps->profile_idc;
|
|
|
|
if ((profile_idc == BASELINE_PROFILE || profile_idc == MAIN_PROFILE ||
|
|
profile_idc == EXTEND_PROFILE) && (sps->constraint_set_flags & 7)) {
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void print_pps(struct h264_pps_info *pps)
|
|
{
|
|
logd("======== pps info ========");
|
|
logd("PPS: sps_id: %d", pps->sps_id);
|
|
logd("PPS: entropy_coding_mode: %d", pps->entropy_coding_flag);
|
|
logd("PPS: num_ref_idx: %d, %d", pps->num_ref_idx[0], pps->num_ref_idx[1]);
|
|
logd("PPS: weighted_pred_flag: %d", pps->weighted_pred_flag);
|
|
logd("PPS: weighted_bipred_flag: %d", pps->weighted_bipred_flag);
|
|
}
|
|
|
|
int h264_decode_pps(struct h264_dec_ctx *s)
|
|
{
|
|
int ret = 0;
|
|
struct h264_pps_info *pps = NULL;
|
|
struct h264_sps_info *sps = NULL;
|
|
logd("show_bits 16: %x", show_bits(&s->gb, 16));
|
|
int pps_id = read_ue_golomb(&s->gb);
|
|
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) {
|
|
loge("malloc pps buffer failed");
|
|
return -1;
|
|
}
|
|
memset(s->pps_buffers[pps_id], 0, sizeof(struct h264_pps_info));
|
|
}
|
|
pps = s->pps_buffers[pps_id];
|
|
|
|
pps->sps_id = read_ue_golomb(&s->gb);
|
|
if(pps->sps_id >= SPS_MAX_NUM) {
|
|
loge("sps id error(%d)", pps->sps_id);
|
|
return -1;
|
|
}
|
|
sps = s->sps_buffers[pps->sps_id];
|
|
logd("PPS: sps_id: %d", pps->sps_id);
|
|
|
|
pps->entropy_coding_flag = read_bits(&s->gb, 1);
|
|
pps->bottom_field_pic_order_in_frame_flag = read_bits(&s->gb, 1);
|
|
logd("PPS: entropy_coding_mode: %d, count: %d", pps->entropy_coding_flag, read_bits_count(&s->gb));
|
|
logd("PPS: bottom_field_pic_order_in_frame_flag: %d", pps->bottom_field_pic_order_in_frame_flag);
|
|
logd("gb index: %d", read_bits_count(&s->gb));
|
|
|
|
int slice_group_num = read_ue_golomb(&s->gb) + 1;
|
|
if(slice_group_num > 1) {
|
|
loge("slice group num(%d) not support", slice_group_num);
|
|
return -1;
|
|
}
|
|
|
|
pps->num_ref_idx[0] = read_ue_golomb(&s->gb) + 1;
|
|
pps->num_ref_idx[1] = read_ue_golomb(&s->gb) + 1;
|
|
|
|
if(pps->num_ref_idx[0] > 32 || pps->num_ref_idx[1] > 32) {
|
|
loge("num ref idx > 32, error");
|
|
return -1;
|
|
}
|
|
logd("PPS: ref_num: %d %d, count: %d", pps->num_ref_idx[0], pps->num_ref_idx[1], read_bits_count(&s->gb));
|
|
|
|
pps->weighted_pred_flag = read_bits(&s->gb, 1);
|
|
pps->weighted_bipred_flag = read_bits(&s->gb, 2);
|
|
pps->pic_init_qp = read_se_golomb(&s->gb) + 26;
|
|
logd("PPS: pic_init_qp: %d, count: %d",pps->pic_init_qp, read_bits_count(&s->gb));
|
|
read_se_golomb(&s->gb); // pic_init_qs_minus26
|
|
logd("PPS:pic_init_qs_minus26, count: %d", read_bits_count(&s->gb));
|
|
pps->chroma_qp_index_offset[1] = pps->chroma_qp_index_offset[0] = read_se_golomb(&s->gb);
|
|
logd("PPS:chroma_qp_index_offset: %d, count: %d", pps->chroma_qp_index_offset[1], read_bits_count(&s->gb));
|
|
pps->deblocking_filter_control_present_flag = read_bits(&s->gb, 1);
|
|
pps->constrained_intra_pred_flag = read_bits(&s->gb, 1);
|
|
pps->redundant_pic_cnt_present_flag = read_bits(&s->gb, 1);
|
|
|
|
pps->transform_8x8_mode_flag = 0;
|
|
memcpy(pps->scaling_matrix4, sps->scaling_matrix4, sizeof(pps->scaling_matrix4));
|
|
memcpy(pps->scaling_matrix8, sps->scaling_matrix8, sizeof(pps->scaling_matrix8));
|
|
|
|
logd("PPS: redundant_pic_cnt_present_flag: %d, left bits: %d, count: %d",
|
|
pps->redundant_pic_cnt_present_flag, read_bits_left(&s->gb), read_bits_count(&s->gb));
|
|
|
|
int left_cnt = read_bits_left(&s->gb);
|
|
int more_bits = 1;
|
|
int left_cnt_7 = left_cnt & 7;
|
|
if(left_cnt <= 8 && (show_bits(&s->gb, left_cnt) == (1<<(left_cnt-1))))
|
|
more_bits = 0;
|
|
if (left_cnt > 16 && (show_bits(&s->gb, left_cnt_7+16) == (1<<(left_cnt_7+15)) )) {
|
|
// if pps and slice data in the same packet,
|
|
// judge the end of PPS with the start code.
|
|
more_bits = 0;
|
|
}
|
|
if(more_bits && more_rbsp_data_in_pps(sps)) {
|
|
pps->transform_8x8_mode_flag = read_bits(&s->gb, 1);
|
|
logd("PPS: pic_scaling_matrix_present_flag: %d, left bits: %d", show_bits(&s->gb, 1), read_bits_left(&s->gb));
|
|
ret = decode_scaling_matrices(&s->gb, sps, pps, 0,
|
|
pps->scaling_matrix4, pps->scaling_matrix8);
|
|
if(ret < 0) {
|
|
loge("decoding scaling matrix in pps fail");
|
|
return -1;
|
|
}
|
|
|
|
pps->chroma_qp_index_offset[1] = read_se_golomb(&s->gb);
|
|
if(pps->chroma_qp_index_offset[1] < -12 || pps->chroma_qp_index_offset[1] > 12) {
|
|
loge("pps->chroma_qp_index_offset[1](%d), out of range", pps->chroma_qp_index_offset[1]);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
print_pps(pps);
|
|
return 0;
|
|
}
|
|
|
|
// decode poc, see spec 8.2.1 Decoding process for picture order count
|
|
static int h264_init_poc(struct h264_dec_ctx *s)
|
|
{
|
|
int i;
|
|
int field_poc[2] = {0};
|
|
struct h264_sps_info* cur_sps = s->sps_buffers[s->active_sps_id];
|
|
struct h264_slice_header* sh = &s->sh;
|
|
int max_frame_num = 1 << cur_sps->log2_max_frm_num;
|
|
|
|
/* Shorten frame num gaps so we don't have to allocate reference
|
|
* frames just to throw them away */
|
|
if (s->frame_num != s->prev_frame_num) {
|
|
int unwrap_prev_frame_num = s->prev_frame_num;
|
|
|
|
if (unwrap_prev_frame_num > s->frame_num)
|
|
unwrap_prev_frame_num -= max_frame_num;
|
|
|
|
if ((s->frame_num - unwrap_prev_frame_num) > cur_sps->max_num_ref_frames) {
|
|
unwrap_prev_frame_num = (s->frame_num - cur_sps->max_num_ref_frames) - 1;
|
|
if (unwrap_prev_frame_num < 0)
|
|
unwrap_prev_frame_num += max_frame_num;
|
|
|
|
s->prev_frame_num = unwrap_prev_frame_num;
|
|
}
|
|
}
|
|
|
|
// gaps in frame_num
|
|
while (s->frame_num != s->prev_frame_num && !s->first_field &&
|
|
s->frame_num != (s->prev_frame_num+1) % max_frame_num) {
|
|
logw("frame gaps, frame_num: %d, prev_frame_num: %d", s->frame_num, s->prev_frame_num);
|
|
if (!cur_sps->gaps_in_frame_num_value_allowed_flag) {
|
|
// reset next_output_poc here, fix bug(PMS: 1304)
|
|
// it is not reset in ffmpeg, maybe error???
|
|
s->next_output_poc = INT_MIN;
|
|
|
|
for (i=0; i<MAX_DELAYED_PIC_COUNT; i++)
|
|
s->frame_info.last_pocs[i] = INT_MIN;
|
|
}
|
|
|
|
s->prev_frame_num++;
|
|
s->prev_frame_num %= max_frame_num;
|
|
s->frame_info.cur_pic_ptr->frame_num = s->prev_frame_num;
|
|
}
|
|
|
|
if(s->idr_pic_flag == 1)
|
|
s->frame_num_offset = 0;
|
|
else if(sh->frame_num < s->prev_frame_num)
|
|
s->frame_num_offset = s->prev_frame_num_offset + max_frame_num;
|
|
else
|
|
s->frame_num_offset = s->prev_frame_num_offset;
|
|
|
|
logd("s->frame_num_offset: %d, cur_sps->poc_type: %d", s->frame_num_offset, cur_sps->poc_type);
|
|
if(cur_sps->poc_type == 0) {
|
|
int max_poc_lsb = 1 << cur_sps->log2_max_poc_lsb;
|
|
|
|
if(s->idr_pic_flag) {
|
|
s->prev_poc_lsb = s->prev_poc_msb = 0;
|
|
}
|
|
|
|
// 1. calc poc_msb
|
|
if (sh->poc_lsb < s->prev_poc_lsb &&
|
|
s->prev_poc_lsb - sh->poc_lsb >= max_poc_lsb / 2)
|
|
sh->poc_msb = s->prev_poc_msb + max_poc_lsb;
|
|
else if (sh->poc_lsb > s->prev_poc_lsb &&
|
|
s->prev_poc_lsb - sh->poc_lsb < -max_poc_lsb / 2)
|
|
sh->poc_msb = s->prev_poc_msb - max_poc_lsb;
|
|
else
|
|
sh->poc_msb = s->prev_poc_msb;
|
|
|
|
// 2. calc top_field/bottom field poc
|
|
field_poc[0] = field_poc[1] = sh->poc_msb + sh->poc_lsb;
|
|
if (s->picture_structure == PICT_FRAME)
|
|
field_poc[1] += sh->delta_poc_bottom;
|
|
} else if(cur_sps->poc_type == 1) {
|
|
int abs_frame_num = 0;
|
|
int64_t expected_delta_per_poc_cycle, expectedpoc;
|
|
int i;
|
|
|
|
// 1. calc abs_frame_num
|
|
if(cur_sps->num_ref_frames_in_poc_cycle != 0) {
|
|
abs_frame_num = s->frame_num_offset + sh->frame_num;
|
|
}
|
|
if(s->nal_ref_idc == 0 && abs_frame_num > 0) {
|
|
abs_frame_num --;
|
|
}
|
|
|
|
// 2. calc expectedpoc
|
|
expected_delta_per_poc_cycle = 0;
|
|
for(i=0; i<cur_sps->num_ref_frames_in_poc_cycle; i++) {
|
|
expected_delta_per_poc_cycle += cur_sps->offset_for_ref_frame[i];
|
|
}
|
|
if(abs_frame_num > 0) {
|
|
int poc_cycle_cnt = (abs_frame_num - 1) / cur_sps->num_ref_frames_in_poc_cycle;
|
|
int frame_num_in_poc_cycle = (abs_frame_num - 1) % cur_sps->num_ref_frames_in_poc_cycle;
|
|
expectedpoc = poc_cycle_cnt * expected_delta_per_poc_cycle;
|
|
for (i = 0; i <= frame_num_in_poc_cycle; i++)
|
|
expectedpoc = expectedpoc + cur_sps->offset_for_ref_frame[i];
|
|
} else {
|
|
expectedpoc = 0;
|
|
}
|
|
|
|
if(s->nal_ref_idc == 0)
|
|
expectedpoc = expectedpoc + cur_sps->offset_for_non_ref_pic;
|
|
|
|
// 3. top field/bottom field poc
|
|
field_poc[0] = expectedpoc + sh->delta_poc[0];
|
|
field_poc[1] = field_poc[0] + cur_sps->offset_for_top_to_bottom_field;
|
|
if(s->picture_structure == PICT_FRAME)
|
|
field_poc[1] += sh->delta_poc[1];
|
|
} else {
|
|
int poc = 2 * (s->frame_num_offset + sh->frame_num);
|
|
|
|
if (!s->nal_ref_idc)
|
|
poc--;
|
|
|
|
field_poc[0] = poc;
|
|
field_poc[1] = poc;
|
|
}
|
|
|
|
if(s->picture_structure != PICT_BOTTOM_FIELD) {
|
|
s->poc_delta = (field_poc[0] & 1) ? 1 : 2;
|
|
|
|
s->frame_info.cur_pic_ptr->field_poc[0] = field_poc[0];
|
|
s->frame_info.cur_pic_ptr->poc = field_poc[0];
|
|
s->frame_info.cur_pic_ptr->mbaff_frame = cur_sps->mbaff && (s->picture_structure == PICT_FRAME);
|
|
}
|
|
|
|
if(s->picture_structure != PICT_TOP_FIELD) {
|
|
s->frame_info.cur_pic_ptr->field_poc[1] = field_poc[1];
|
|
s->frame_info.cur_pic_ptr->poc = field_poc[1];
|
|
}
|
|
|
|
if(s->picture_structure == PICT_FRAME) {
|
|
s->frame_info.cur_pic_ptr->poc = MIN(s->frame_info.cur_pic_ptr->field_poc[0],
|
|
s->frame_info.cur_pic_ptr->field_poc[1]);
|
|
}
|
|
|
|
logd("cur pic poc: %d field poc: %d, %d", s->frame_info.cur_pic_ptr->poc,
|
|
s->frame_info.cur_pic_ptr->field_poc[0], s->frame_info.cur_pic_ptr->field_poc[1]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void print_ref_list(struct h264_dec_ctx *s)
|
|
{
|
|
int list = 0;
|
|
int i = 0;
|
|
//struct h264_picture* pic = NULL;
|
|
|
|
for(list=0; list<s->sh.list_count; list++) {
|
|
logd("==== ref list%d, count: %d ====", list, s->sh.num_ref_idx[list]);
|
|
for(i=0; i<s->sh.num_ref_idx[list]; i++) {
|
|
//pic = s->frame_info.ref_list[list][i].parent;
|
|
if(s->frame_info.ref_list[list][i].parent) {
|
|
logd("list: %d, i: %d, buf_idx: %d, structure: %d, poc: %d", list, i,
|
|
s->frame_info.ref_list[list][i].parent->buf_idx, s->frame_info.ref_list[list][i].refrence,
|
|
s->frame_info.ref_list[list][i].poc);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* if the reference picture is error, current picture will decode error too.
|
|
*/
|
|
static void set_error_from_ref_list(struct h264_dec_ctx *s)
|
|
{
|
|
int list = 0;
|
|
int i = 0;
|
|
struct h264_picture* pic = NULL;
|
|
struct h264_picture* cur_pic = s->frame_info.cur_pic_ptr;
|
|
|
|
for (list=0; list<s->sh.list_count; list++) {
|
|
for (i=0; i<s->sh.num_ref_idx[list]; i++) {
|
|
pic = s->frame_info.ref_list[list][i].parent;
|
|
if (pic && pic->frame->mpp_frame.flags & FRAME_FLAG_ERROR) {
|
|
cur_pic->frame->mpp_frame.flags |= FRAME_FLAG_ERROR;
|
|
loge("ref error, so cur error");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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 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 * 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
|
|
// 1. frame structure: the number of last decoded mb less than total mbs,
|
|
// and first_mb_in_slice is not 0.
|
|
// 2. field structure: TODO
|
|
static int check_last_frame(struct h264_dec_ctx *s)
|
|
{
|
|
struct h264_picture* cur_pic = s->frame_info.cur_pic_ptr;
|
|
struct h264_slice_header* sh = &s->sh;
|
|
|
|
if (cur_pic == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
if (s->picture_structure == PICT_FRAME) {
|
|
if (s->decode_mb_num < s->mbs_in_pic && !sh->first_mb_in_slice) {
|
|
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);
|
|
if (s->nal_ref_idc_pre) {
|
|
execute_ref_pic_marking(s);
|
|
}
|
|
select_output_frame(s);
|
|
s->frame_info.cur_pic_ptr = NULL;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
/*
|
|
1) parse slice header syntax
|
|
2) alloc physic memory for frame buffer
|
|
3) get one frame
|
|
4) init reference list and reorder
|
|
|
|
return -1, if syntax parse error before get frame
|
|
return DEC_NO_EMPTY_FRAME, if no empty frame for decoding
|
|
*/
|
|
int h264_decode_slice_header(struct h264_dec_ctx *s)
|
|
{
|
|
int width, height;
|
|
int last_pic_structure;
|
|
int last_first_field = s->first_field;
|
|
struct h264_sps_info* cur_sps = NULL;
|
|
struct h264_pps_info* cur_pps = NULL;
|
|
struct h264_slice_header* sh = &s->sh;
|
|
|
|
last_pic_structure = s->picture_structure;
|
|
sh->first_mb_in_slice = read_ue_golomb(&s->gb);
|
|
logi("sh->first_mb_in_slice: %d", sh->first_mb_in_slice);
|
|
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;
|
|
}
|
|
|
|
check_last_frame(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->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;
|
|
s->active_sps_id = s->pps_buffers[s->active_pps_id]->sps_id;
|
|
cur_sps = s->sps_buffers[s->active_sps_id];
|
|
cur_pps = s->pps_buffers[s->active_pps_id];
|
|
|
|
width = cur_sps->pic_mb_width * 16;
|
|
height = cur_sps->pic_mb_height * (2-cur_sps->frame_mbs_only_flag) * 16;
|
|
if((s->width && s->width != width) || (s->height && s->height != height)) {
|
|
logw("resolution change");
|
|
}
|
|
|
|
s->width = width;
|
|
s->height = height;
|
|
|
|
// 1. alloc frame buffer if it is the first time
|
|
if(s->frame_info.max_valid_frame_num == 0)
|
|
h264_alloc_frame_buffer(s);
|
|
|
|
sh->frame_num = read_bits(&s->gb, cur_sps->log2_max_frm_num);
|
|
s->frame_num = sh->frame_num;
|
|
|
|
sh->mbaff_frame = 0;
|
|
sh->field_pic_flag = 0;
|
|
sh->bottom_field_flag = 0;
|
|
if(cur_sps->frame_mbs_only_flag) {
|
|
s->picture_structure = PICT_FRAME;
|
|
} else {
|
|
sh->field_pic_flag = read_bits(&s->gb, 1);
|
|
if(sh->field_pic_flag == 1) {
|
|
sh->bottom_field_flag = read_bits(&s->gb, 1);
|
|
s->picture_structure = PICT_TOP_FIELD + sh->bottom_field_flag;
|
|
} else {
|
|
// MBAFF
|
|
s->picture_structure = PICT_FRAME;
|
|
sh->mbaff_frame = cur_sps->mbaff;
|
|
}
|
|
}
|
|
|
|
if(sh->first_mb_in_slice != 0) {
|
|
// the picture structrue must be same in difference slices of a picture
|
|
// warning here, maybe sytax error
|
|
if(s->picture_structure != last_pic_structure) {
|
|
logw("picture struct different: %d %d", s->picture_structure, last_pic_structure);
|
|
s->picture_structure = last_pic_structure;
|
|
}
|
|
}
|
|
|
|
s->mbs_in_pic = cur_sps->pic_mb_width * cur_sps->pic_mb_height * (2-cur_sps->frame_mbs_only_flag);
|
|
if(s->picture_structure != PICT_FRAME)
|
|
s->mbs_in_pic >>= 1;
|
|
|
|
logi("s->picture_structure: %d", s->picture_structure);
|
|
// 2. get an empty frame for decode output
|
|
if(s->cur_slice_num == 0) {
|
|
// set first_field flag
|
|
if(s->picture_structure == PICT_FRAME) {
|
|
s->first_field = 0;
|
|
} else if(s->first_field == 1) {
|
|
// 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 {
|
|
s->first_field = 0;
|
|
}
|
|
} else {
|
|
s->first_field = (s->picture_structure != PICT_FRAME);
|
|
}
|
|
|
|
struct frame* f = NULL;
|
|
|
|
// get frame
|
|
if(sh->first_mb_in_slice == 0 && (s->picture_structure == PICT_FRAME || s->first_field == 1)) {
|
|
logi("empty number: %d", fm_get_empty_frame_num(s->decoder.fm));
|
|
|
|
f = fm_decoder_get_frame(s->decoder.fm);
|
|
if(f == NULL) {
|
|
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;
|
|
s->frame_info.picture[f->mpp_frame.id].mmco_reset = 0;
|
|
s->frame_info.picture[f->mpp_frame.id].key_frame = s->idr_pic_flag;
|
|
s->frame_info.cur_pic_ptr = &s->frame_info.picture[f->mpp_frame.id];
|
|
|
|
set_frame_info(s);
|
|
}
|
|
|
|
int cur_buf_id = s->frame_info.cur_pic_ptr->buf_idx;
|
|
if(s->picture_structure == PICT_FRAME) {
|
|
s->frame_info.picture[cur_buf_id].nal_ref_idc[0] = s->nal_ref_idc;
|
|
s->frame_info.picture[cur_buf_id].nal_ref_idc[1] = s->nal_ref_idc;
|
|
} else if(s->picture_structure == PICT_TOP_FIELD) {
|
|
s->frame_info.picture[cur_buf_id].nal_ref_idc[0] = s->nal_ref_idc;
|
|
} else { // bottom field
|
|
s->frame_info.picture[cur_buf_id].nal_ref_idc[1] = s->nal_ref_idc;
|
|
}
|
|
}
|
|
|
|
s->frame_info.cur_pic_ptr->frame_num = sh->frame_num;
|
|
if(s->picture_structure == PICT_FRAME) {
|
|
sh->cur_pic_num = sh->frame_num;
|
|
sh->max_pic_num = 1 << cur_sps->log2_max_frm_num;
|
|
} else {
|
|
sh->cur_pic_num = 2*sh->frame_num + 1;
|
|
sh->max_pic_num = 1 << (cur_sps->log2_max_frm_num + 1);
|
|
}
|
|
|
|
if(s->idr_pic_flag == 1) {
|
|
sh->idr_pic_id = read_ue_golomb(&s->gb);
|
|
}
|
|
|
|
if(cur_sps->poc_type == 0) {
|
|
sh->poc_lsb = read_bits(&s->gb, cur_sps->log2_max_poc_lsb);
|
|
if(cur_pps->bottom_field_pic_order_in_frame_flag && s->picture_structure == PICT_FRAME) {
|
|
sh->delta_poc_bottom = read_se_golomb(&s->gb);
|
|
}
|
|
logi("SH: poc_lsb: %d, offset: %d", sh->poc_lsb, read_bits_count(&s->gb));
|
|
}
|
|
|
|
if(cur_sps->poc_type == 1 && !cur_sps->delta_pic_order_always_zero_flag) {
|
|
sh->delta_poc[0] = read_se_golomb(&s->gb);
|
|
if(cur_pps->bottom_field_pic_order_in_frame_flag && s->picture_structure == PICT_FRAME) {
|
|
sh->delta_poc[1] = read_se_golomb(&s->gb);
|
|
}
|
|
}
|
|
|
|
// 3. calc the poc of current frame
|
|
if(!sh->first_mb_in_slice) {
|
|
h264_init_poc(s);
|
|
}
|
|
|
|
if(cur_pps->redundant_pic_cnt_present_flag) {
|
|
read_ue_golomb(&s->gb); // redundant_pic_cnt
|
|
}
|
|
|
|
sh->num_ref_idx[0] = cur_pps->num_ref_idx[0];
|
|
sh->num_ref_idx[1] = cur_pps->num_ref_idx[1];
|
|
sh->direct_spatial_mv_pred = 0;
|
|
sh->num_ref_idx_active_override = 0;
|
|
sh->list_count = 0;
|
|
if(sh->slice_type == H264_SLICE_B)
|
|
sh->direct_spatial_mv_pred = read_bits(&s->gb, 1);
|
|
|
|
if(sh->slice_type == H264_SLICE_B || sh->slice_type == H264_SLICE_P || sh->slice_type == H264_SLICE_SP) {
|
|
sh->num_ref_idx_active_override = read_bits(&s->gb, 1);
|
|
logi("SH: num_ref_idx_active_override: %d", sh->num_ref_idx_active_override);
|
|
if(sh->num_ref_idx_active_override) {
|
|
sh->num_ref_idx[0] = read_ue_golomb(&s->gb) + 1;
|
|
logi("SH: num_ref_idx_l0: %d", sh->num_ref_idx[0]);
|
|
if(sh->slice_type == H264_SLICE_B) {
|
|
sh->num_ref_idx[1] = read_ue_golomb(&s->gb) + 1;
|
|
}
|
|
}
|
|
sh->list_count = (sh->slice_type == H264_SLICE_B) ? 2: 1;
|
|
}
|
|
|
|
// init ref list
|
|
if(sh->slice_type != H264_SLICE_I && sh->slice_type != H264_SLICE_SI) {
|
|
init_ref_list(s);
|
|
|
|
// reorder
|
|
ref_pic_list_reordering(s);
|
|
set_error_from_ref_list(s);
|
|
|
|
print_ref_list(s);
|
|
}
|
|
|
|
// parse pred weight table
|
|
if((cur_pps->weighted_pred_flag && (sh->slice_type == H264_SLICE_P || sh->slice_type == H264_SLICE_SP))
|
|
|| (cur_pps->weighted_bipred_flag == 1 && sh->slice_type == H264_SLICE_B)) {
|
|
pred_weight_table(s);
|
|
}
|
|
|
|
// parse dec_ref_pic_marking
|
|
if(s->nal_ref_idc) {
|
|
if(dec_ref_pic_marking(s) < 0) {
|
|
loge("dec_ref_pic_marking error");
|
|
s->error = H264_DECODER_ERROR_REFPICMARKING;
|
|
}
|
|
}
|
|
|
|
if(sh->slice_type != H264_SLICE_I && sh->slice_type != H264_SLICE_SI && cur_pps->entropy_coding_flag) {
|
|
sh->cabac_init_idc = read_ue_golomb(&s->gb);
|
|
logi("sh->cabac_init_idc: %d, offset: %d", sh->cabac_init_idc, read_bits_count(&s->gb));
|
|
}
|
|
|
|
int qp_delta = read_se_golomb(&s->gb);
|
|
logi("qp_delta: %d, offset: %d", qp_delta, read_bits_count(&s->gb));
|
|
int tmp = cur_pps->pic_init_qp + qp_delta;
|
|
if(tmp > 51) {
|
|
logw("qp(%d) large than 51", tmp);
|
|
tmp = 30;
|
|
}
|
|
sh->qp_y = tmp;
|
|
logi("SH: slice_qp_delta: %d, sh->slice_type: %d", qp_delta, sh->slice_type);
|
|
|
|
if(sh->slice_type == H264_SLICE_SP)
|
|
read_bits(&s->gb, 1);
|
|
if(sh->slice_type == H264_SLICE_SI || sh->slice_type == H264_SLICE_SP)
|
|
read_se_golomb(&s->gb);
|
|
|
|
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);
|
|
}
|
|
|
|
if(sh->deblocking_filter != 1) {
|
|
sh->slice_alpha_c0_offset_div2 = read_se_golomb(&s->gb);
|
|
sh->slice_beta_offset_div2 = read_se_golomb(&s->gb);
|
|
}
|
|
} else {
|
|
sh->deblocking_filter = 0;
|
|
sh->slice_alpha_c0_offset_div2 = 0;
|
|
sh->slice_beta_offset_div2 = 0;
|
|
}
|
|
|
|
// we are not support slice group, so no need to parse slice_group_change_cycle here
|
|
s->bit_offset = read_bits_count(&s->gb);
|
|
if(cur_pps->entropy_coding_flag)
|
|
s->bit_offset = (s->bit_offset + 7) & 0x7ffffff8;
|
|
|
|
logd("s->first_eptb_offset: %d s->bit_offset: %d", s->first_eptb_offset, s->bit_offset);
|
|
// if the first_eptb_offset < bit_offset, the eptb is in slice header;
|
|
// or the eptb is in slice data, we cannot remove it
|
|
if(s->first_eptb_offset*8 <= s->bit_offset)
|
|
s->bit_offset += (s->sc_byte_offset + s->remove_bytes)*8;
|
|
else
|
|
s->bit_offset += s->sc_byte_offset*8;
|
|
s->bit_offset += s->slice_offset*8;
|
|
s->frame_info.cur_pic_ptr->picture_structure = s->picture_structure;
|
|
|
|
s->cur_slice_num ++;
|
|
return 0;
|
|
}
|