#include "pipe/p_video_codec.h"
#include "util/u_memory.h"
+#include "util/u_video.h"
#include "vl/vl_rbsp.h"
+#include "vl/vl_zscan.h"
#include "entrypoint.h"
#include "vid_dec.h"
struct dpb_list {
struct list_head list;
struct pipe_video_buffer *buffer;
- unsigned poc;
+ OMX_TICKS timestamp;
+ int poc;
};
static const uint8_t Default_4x4_Intra[16] = {
- 6, 13, 13, 20, 20, 20, 28, 28,
- 28, 28, 32, 32, 32, 37, 37, 42
+ 6, 13, 20, 28, 13, 20, 28, 32,
+ 20, 28, 32, 37, 28, 32, 37, 42
};
static const uint8_t Default_4x4_Inter[16] = {
- 10, 14, 14, 20, 20, 20, 24, 24,
- 24, 24, 27, 27, 27, 30, 30, 34
+ 10, 14, 20, 24, 14, 20, 24, 27,
+ 20, 24, 27, 30, 24, 27, 30, 34
};
static const uint8_t Default_8x8_Intra[64] = {
- 6, 10, 10, 13, 11, 13, 16, 16,
- 16, 16, 18, 18, 18, 18, 18, 23,
- 23, 23, 23, 23, 23, 25, 25, 25,
- 25, 25, 25, 25, 27, 27, 27, 27,
- 27, 27, 27, 27, 29, 29, 29, 29,
- 29, 29, 29, 31, 31, 31, 31, 31,
- 31, 33, 33, 33, 33, 33, 36, 36,
- 36, 36, 38, 38, 38, 40, 40, 42
+ 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
};
static const uint8_t Default_8x8_Inter[64] = {
- 9, 13, 13, 15, 13, 15, 17, 17,
- 17, 17, 19, 19, 19, 19, 19, 21,
- 21, 21, 21, 21, 21, 22, 22, 22,
- 22, 22, 22, 22, 24, 24, 24, 24,
- 24, 24, 24, 24, 25, 25, 25, 25,
- 25, 25, 25, 27, 27, 27, 27, 27,
- 27, 28, 28, 28, 28, 28, 30, 30,
- 30, 30, 32, 32, 32, 33, 33, 35
+ 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 void vid_dec_h264_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left);
static void vid_dec_h264_EndFrame(vid_dec_PrivateType *priv);
-static struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv);
+static struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv, OMX_TICKS *timestamp);
void vid_dec_h264_Init(vid_dec_PrivateType *priv)
{
priv->Decode = vid_dec_h264_Decode;
priv->EndFrame = vid_dec_h264_EndFrame;
priv->Flush = vid_dec_h264_Flush;
-
+
LIST_INITHEAD(&priv->codec_data.h264.dpb_list);
priv->picture.h264.field_order_cnt[0] = priv->picture.h264.field_order_cnt[1] = INT_MAX;
+ priv->first_buf_in_frame = true;
}
static void vid_dec_h264_BeginFrame(vid_dec_PrivateType *priv)
if (priv->frame_started)
return;
+ if (!priv->codec) {
+ struct pipe_video_codec templat = {};
+ omx_base_video_PortType *port;
+
+ port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX];
+ templat.profile = priv->profile;
+ templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM;
+ templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
+ templat.max_references = priv->picture.h264.num_ref_frames;
+ templat.expect_chunked_decode = true;
+ templat.width = port->sPortParam.format.video.nFrameWidth;
+ templat.height = port->sPortParam.format.video.nFrameHeight;
+ templat.level = priv->picture.h264.pps->sps->level_idc;
+
+ priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat);
+ }
+
vid_dec_NeedTarget(priv);
+ if (priv->first_buf_in_frame)
+ priv->timestamp = priv->timestamps[0];
+ priv->first_buf_in_frame = false;
+
priv->picture.h264.num_ref_frames = priv->picture.h264.pps->sps->max_num_ref_frames;
+ priv->picture.h264.slice_count = 0;
priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base);
priv->frame_started = true;
}
-static struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv)
+static struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv,
+ OMX_TICKS *timestamp)
{
struct dpb_list *entry, *result = NULL;
struct pipe_video_buffer *buf;
return NULL;
buf = result->buffer;
+ if (timestamp)
+ *timestamp = result->timestamp;
--priv->codec_data.h264.dpb_num;
LIST_DEL(&result->list);
struct dpb_list *entry;
struct pipe_video_buffer *tmp;
bool top_field_first;
+ OMX_TICKS timestamp;
if (!priv->frame_started)
return;
if (!entry)
return;
+ priv->first_buf_in_frame = true;
entry->buffer = priv->target;
+ entry->timestamp = priv->timestamp;
entry->poc = MIN2(priv->picture.h264.field_order_cnt[0], priv->picture.h264.field_order_cnt[1]);
LIST_ADDTAIL(&entry->list, &priv->codec_data.h264.dpb_list);
++priv->codec_data.h264.dpb_num;
return;
tmp = priv->in_buffers[0]->pInputPortPrivate;
- priv->in_buffers[0]->pInputPortPrivate = vid_dec_h264_Flush(priv);
+ priv->in_buffers[0]->pInputPortPrivate = vid_dec_h264_Flush(priv, ×tamp);
+ priv->in_buffers[0]->nTimeStamp = timestamp;
priv->target = tmp;
priv->frame_finished = priv->in_buffers[0]->pInputPortPrivate != NULL;
}
const uint8_t *defaultList, const uint8_t *fallbackList)
{
unsigned lastScale = 8, nextScale = 8;
+ const int *list;
unsigned i;
/* (pic|seq)_scaling_list_present_flag[i] */
return;
}
+ list = (sizeOfScalingList == 16) ? vl_zscan_normal_16 : vl_zscan_normal;
for (i = 0; i < sizeOfScalingList; ++i ) {
if (nextScale != 0) {
return;
}
}
- scalingList[i] = nextScale == 0 ? lastScale : nextScale;
- lastScale = scalingList[i];
+ scalingList[list[i]] = nextScale == 0 ? lastScale : nextScale;
+ lastScale = scalingList[list[i]];
}
}
static struct pipe_h264_sps *seq_parameter_set_id(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp)
{
unsigned id = vl_rbsp_ue(rbsp);
- if (id >= Elements(priv->codec_data.h264.sps))
+ if (id >= ARRAY_SIZE(priv->codec_data.h264.sps))
return NULL; /* invalid seq_parameter_set_id */
return &priv->codec_data.h264.sps[id];
static void seq_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp)
{
struct pipe_h264_sps *sps;
- unsigned profile_idc;
+ unsigned profile_idc, level_idc;
unsigned i;
/* Sequence parameter set */
vl_rbsp_u(rbsp, 2);
/* level_idc */
- vl_rbsp_u(rbsp, 8);
+ level_idc = vl_rbsp_u(rbsp, 8);
sps = seq_parameter_set_id(priv, rbsp);
if (!sps)
memset(sps->ScalingList4x4, 16, sizeof(sps->ScalingList4x4));
memset(sps->ScalingList8x8, 16, sizeof(sps->ScalingList8x8));
+ sps->level_idc = level_idc;
+
if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 244 ||
profile_idc == 44 || profile_idc == 83 || profile_idc == 86 || profile_idc == 118 ||
profile_idc == 128 || profile_idc == 138) {
static struct pipe_h264_pps *pic_parameter_set_id(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp)
{
unsigned id = vl_rbsp_ue(rbsp);
- if (id >= Elements(priv->codec_data.h264.pps))
+ if (id >= ARRAY_SIZE(priv->codec_data.h264.pps))
return NULL; /* invalid pic_parameter_set_id */
return &priv->codec_data.h264.pps[id];
if (priv->picture.h264.field_pic_flag) {
unsigned bottom_field_flag = vl_rbsp_u(rbsp, 1);
- if (bottom_field_flag != priv->picture.h264.bottom_field_flag);
+ if (bottom_field_flag != priv->picture.h264.bottom_field_flag)
vid_dec_h264_EndFrame(priv);
priv->picture.h264.bottom_field_flag = bottom_field_flag;
if (sps->pic_order_cnt_type == 0) {
unsigned log2_max_pic_order_cnt_lsb = sps->log2_max_pic_order_cnt_lsb_minus4 + 4;
unsigned max_pic_order_cnt_lsb = 1 << log2_max_pic_order_cnt_lsb;
- unsigned pic_order_cnt_lsb = vl_rbsp_u(rbsp, log2_max_pic_order_cnt_lsb);
- unsigned pic_order_cnt_msb;
+ int pic_order_cnt_lsb = vl_rbsp_u(rbsp, log2_max_pic_order_cnt_lsb);
+ int pic_order_cnt_msb;
if (pic_order_cnt_lsb != priv->codec_data.h264.pic_order_cnt_lsb)
vid_dec_h264_EndFrame(priv);
+ if (IdrPicFlag) {
+ priv->codec_data.h264.pic_order_cnt_msb = 0;
+ priv->codec_data.h264.pic_order_cnt_lsb = 0;
+ }
+
if ((pic_order_cnt_lsb < priv->codec_data.h264.pic_order_cnt_lsb) &&
(priv->codec_data.h264.pic_order_cnt_lsb - pic_order_cnt_lsb) >= (max_pic_order_cnt_lsb / 2))
pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb + max_pic_order_cnt_lsb;
priv->codec_data.h264.delta_pic_order_cnt_bottom = delta_pic_order_cnt_bottom;
}
- priv->picture.h264.field_order_cnt[0] = pic_order_cnt_msb + pic_order_cnt_lsb;
- priv->picture.h264.field_order_cnt[1] = pic_order_cnt_msb + pic_order_cnt_lsb;
- if (!priv->picture.h264.field_pic_flag)
- priv->picture.h264.field_order_cnt[1] += priv->codec_data.h264.delta_pic_order_cnt_bottom;
+ if (!priv->picture.h264.field_pic_flag) {
+ priv->picture.h264.field_order_cnt[0] = pic_order_cnt_msb + pic_order_cnt_lsb;
+ priv->picture.h264.field_order_cnt[1] = priv->picture.h264.field_order_cnt [0] +
+ priv->codec_data.h264.delta_pic_order_cnt_bottom;
+ } else if (!priv->picture.h264.bottom_field_flag)
+ priv->picture.h264.field_order_cnt[0] = pic_order_cnt_msb + pic_order_cnt_lsb;
+ else
+ priv->picture.h264.field_order_cnt[1] = pic_order_cnt_msb + pic_order_cnt_lsb;
} else if (sps->pic_order_cnt_type == 1) {
unsigned MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4);
else
FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset;
+ priv->codec_data.h264.prevFrameNumOffset = FrameNumOffset;
+
if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0)
absFrameNum = FrameNumOffset + frame_num;
else
priv->picture.h264.field_order_cnt[0] = expectedPicOrderCnt + priv->codec_data.h264.delta_pic_order_cnt[0];
priv->picture.h264.field_order_cnt[1] = priv->picture.h264.field_order_cnt[0] +
sps->offset_for_top_to_bottom_field + priv->codec_data.h264.delta_pic_order_cnt[1];
-
+
} else if (!priv->picture.h264.bottom_field_flag)
priv->picture.h264.field_order_cnt[0] = expectedPicOrderCnt + priv->codec_data.h264.delta_pic_order_cnt[0];
else
else
FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset;
+ priv->codec_data.h264.prevFrameNumOffset = FrameNumOffset;
+
if (IdrPicFlag)
tempPicOrderCnt = 0;
else if (nal_ref_idc == 0)
if (!priv->picture.h264.field_pic_flag) {
priv->picture.h264.field_order_cnt[0] = tempPicOrderCnt;
priv->picture.h264.field_order_cnt[1] = tempPicOrderCnt;
-
+
} else if (!priv->picture.h264.bottom_field_flag)
priv->picture.h264.field_order_cnt[0] = tempPicOrderCnt;
else
priv->picture.h264.num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_default_active_minus1;
priv->picture.h264.num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_default_active_minus1;
-
+
if (slice_type == PIPE_H264_SLICE_TYPE_P ||
slice_type == PIPE_H264_SLICE_TYPE_SP ||
slice_type == PIPE_H264_SLICE_TYPE_B) {
if (priv->slice) {
unsigned bytes = priv->bytes_left - (vl_vlc_bits_left(vlc) / 8);
+ ++priv->picture.h264.slice_count;
priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base,
1, &priv->slice, &bytes);
priv->slice = NULL;
vid_dec_h264_BeginFrame(priv);
+ ++priv->picture.h264.slice_count;
priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base,
1, &ptr, &bytes);
}