/*
|
* Copyright 2016 Rockchip Electronics Co. LTD
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*/
|
|
#define MODULE_TAG "rc_data_impl"
|
|
#include <string.h>
|
|
#include "mpp_env.h"
|
#include "mpp_mem.h"
|
#include "mpp_list.h"
|
#include "mpp_debug.h"
|
#include "mpp_common.h"
|
|
#include "rc_data.h"
|
#include "rc_data_impl.h"
|
|
#define RC_LIST_HEAD 1
|
#define RC_LIST_TAIL 0
|
|
#define RC_FRM_TYPE_I 0
|
#define RC_FRM_TYPE_P 1
|
|
#define RC_FRM_STATUS_VALID (0x00000001)
|
#define RC_HAL_SET_VALID (0x00000002)
|
#define RC_HAL_RET_VALID (0x00000004)
|
|
static void rc_data_indexes_init(RcDataIndexes *sort)
|
{
|
RK_S32 i;
|
|
memset(sort, 0, sizeof(*sort));
|
|
INIT_LIST_HEAD(&sort->seq);
|
|
for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(sort->type); i++)
|
INIT_LIST_HEAD(&sort->type[i]);
|
|
for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(sort->tid); i++)
|
INIT_LIST_HEAD(&sort->tid[i]);
|
|
for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(sort->status); i++)
|
INIT_LIST_HEAD(&sort->status[i]);
|
}
|
|
static void rc_data_node_init(DataGroupImpl *p, RcDataNode *node, RK_S32 slot_idx)
|
{
|
RcDataIndexes *indexes = &p->indexes;
|
RcDataStatus status = RC_DATA_ST_UNUSED;
|
RcDataHead *head = &node->head;
|
RcDataBase *base = &node->base;
|
|
memset(node, 0, sizeof(*node));
|
|
head->node = node;
|
head->slot_id = slot_idx;
|
|
INIT_LIST_HEAD(&head->seq);
|
INIT_LIST_HEAD(&head->type);
|
INIT_LIST_HEAD(&head->tid);
|
INIT_LIST_HEAD(&head->status);
|
list_add_tail(&head->status, &indexes->status[status]);
|
indexes->status_cnt[status]++;
|
|
base->head = head;
|
|
node->extra = NULL;
|
}
|
|
MPP_RET rc_data_group_init(DataGroupImpl *p, RK_S32 base_cnt, RK_S32 extra_cnt)
|
{
|
p->lock = new Mutex();
|
|
node_group_init(&p->node, sizeof(RcDataNode), base_cnt);
|
node_group_init(&p->extra, sizeof(RcDataExtra), extra_cnt);
|
|
mpp_assert(p->lock);
|
mpp_assert(p->node);
|
mpp_assert(p->extra);
|
|
p->base_cnt = base_cnt;
|
p->extra_cnt = extra_cnt;
|
|
rc_data_group_reset(p);
|
|
return MPP_OK;
|
}
|
|
MPP_RET rc_data_group_deinit(DataGroupImpl *p)
|
{
|
mpp_assert(p->lock);
|
mpp_assert(p->node);
|
mpp_assert(p->extra);
|
|
node_group_deinit(p->node);
|
node_group_deinit(p->extra);
|
|
delete p->lock;
|
|
return MPP_OK;
|
}
|
|
MPP_RET rc_data_group_reset(DataGroupImpl *p)
|
{
|
RK_S32 i;
|
|
rc_data_indexes_init(&p->indexes);
|
|
for (i = 0; i < p->base_cnt; i++) {
|
RcDataNode *node = (RcDataNode *)node_group_get(p->node, i);
|
|
rc_data_node_init(p, node, i);
|
}
|
|
for (i = 0; i < p->extra_cnt; i++) {
|
RcDataExtra *extra = (RcDataExtra *)node_group_get(p->extra, i);
|
|
/* NOTE: node in head is NULL */
|
memset(extra, 0, sizeof(*extra));
|
}
|
|
return MPP_OK;
|
}
|
|
RcDataNode *rc_data_group_get_node_by_seq_id(DataGroupImpl *p, RK_S32 seq_id)
|
{
|
RcDataIndexes *indexes = &p->indexes;
|
|
if (list_empty(&indexes->seq))
|
return NULL;
|
|
RcDataNode *node = NULL;
|
RcDataHead *pos;
|
|
if (MPP_ABS(seq_id - indexes->seq_new) < MPP_ABS(seq_id - indexes->seq_old)) {
|
list_for_each_entry(pos, &indexes->seq, RcDataHead, seq) {
|
if (pos->seq_id == seq_id) {
|
node = pos->node;
|
break;
|
}
|
}
|
} else {
|
list_for_each_entry_reverse(pos, &indexes->seq, RcDataHead, seq) {
|
if (pos->seq_id == seq_id) {
|
node = pos->node;
|
break;
|
}
|
}
|
}
|
|
return node;
|
}
|
|
RcDataNode *rc_data_group_get_node_by_status(DataGroupImpl *p, RcDataStatus status, RK_S32 whence)
|
{
|
RcDataIndexes *indexes = &p->indexes;
|
|
mpp_assert(status >= RC_DATA_ST_UNUSED && status <= RC_DATA_ST_DONE);
|
|
struct list_head *list = &indexes->status[status];
|
|
if (list_empty(list))
|
return NULL;
|
|
list = (whence == RC_LIST_HEAD) ? (list->next) : (list->prev);
|
RcDataHead *head = list_entry(list, RcDataHead, status);
|
mpp_assert(head->data_status == status);
|
mpp_assert(head->node);
|
return head->node;
|
}
|
|
void rc_data_group_put_node(DataGroupImpl *p, RcDataNode *node)
|
{
|
RcDataIndexes *indexes = &p->indexes;
|
RcDataHead *head = &node->head;
|
|
AutoMutex auto_lock(p->lock);
|
RcDataStatus data_status = head->data_status;
|
|
list_del_init(&head->status);
|
indexes->status_cnt[data_status]--;
|
|
if (data_status == RC_DATA_ST_FILLING) {
|
// ready on filling add to indexing list by property
|
EncFrmStatus frm_status = head->frm_status;
|
RK_S32 type_id = frm_status.is_intra ? RC_FRM_TYPE_I : RC_FRM_TYPE_P;
|
RK_S32 tid = frm_status.temporal_id;
|
|
mpp_assert(list_empty(&head->seq));
|
list_add_tail(&head->seq, &indexes->seq);
|
indexes->seq_cnt++;
|
indexes->seq_new = head->seq_id;
|
|
mpp_assert(list_empty(&head->type));
|
list_add_tail(&head->type, &indexes->type[type_id]);
|
indexes->type_cnt[type_id]++;
|
|
mpp_assert(tid < 4);
|
mpp_assert(list_empty(&head->tid));
|
list_add_tail(&head->tid, &indexes->tid[type_id]);
|
indexes->tid_cnt[type_id]++;
|
}
|
|
// goto next status
|
switch (data_status) {
|
case RC_DATA_ST_UNUSED : {
|
data_status = RC_DATA_ST_FILLING;
|
} break;
|
case RC_DATA_ST_FILLING : {
|
data_status = RC_DATA_ST_DONE;
|
} break;
|
case RC_DATA_ST_DONE : {
|
data_status = RC_DATA_ST_UNUSED;
|
} break;
|
default : {
|
data_status = RC_DATA_ST_BUTT;
|
mpp_assert(data_status != RC_DATA_ST_BUTT);
|
} break;
|
}
|
|
if (data_status == RC_DATA_ST_UNUSED) {
|
// removed from indexing list
|
EncFrmStatus frm_status = head->frm_status;
|
|
if (!list_empty(&head->seq)) {
|
list_del_init(&head->seq);
|
indexes->seq_cnt--;
|
indexes->seq_old = head->seq_id;
|
}
|
|
if (!list_empty(&head->type)) {
|
RK_S32 type_id = frm_status.is_intra ? RC_FRM_TYPE_I : RC_FRM_TYPE_P;
|
|
list_del_init(&head->type);
|
indexes->type_cnt[type_id]--;
|
}
|
|
if (!list_empty(&head->tid)) {
|
RK_S32 tid = frm_status.temporal_id;
|
|
mpp_assert(tid < 4);
|
list_del_init(&head->tid);
|
indexes->tid_cnt[tid]--;
|
}
|
}
|
|
list_add_tail(&head->status, &indexes->status[data_status]);
|
indexes->status_cnt[data_status]++;
|
head->data_status = data_status;
|
}
|
|
RcData rc_data_get_next(DataGroup grp)
|
{
|
DataGroupImpl *p = (DataGroupImpl *)grp;
|
RcDataNode *node = rc_data_group_get_node_by_status(
|
p, RC_DATA_ST_UNUSED, RC_LIST_HEAD);
|
|
return (RcData)node;
|
}
|
|
RcData rc_data_get_curr_latest(DataGroup grp)
|
{
|
DataGroupImpl *p = (DataGroupImpl *)grp;
|
RcDataNode *node = rc_data_group_get_node_by_status(
|
p, RC_DATA_ST_FILLING, RC_LIST_TAIL);
|
|
return (RcData)node;
|
}
|
|
RcData rc_data_get_curr_oldest(DataGroup grp)
|
{
|
DataGroupImpl *p = (DataGroupImpl *)grp;
|
RcDataNode *node = rc_data_group_get_node_by_status(
|
p, RC_DATA_ST_FILLING, RC_LIST_HEAD);
|
|
return (RcData)node;
|
}
|
|
RcData rc_data_get_last_latest(DataGroup grp)
|
{
|
DataGroupImpl *p = (DataGroupImpl *)grp;
|
RcDataNode *node = rc_data_group_get_node_by_status(
|
p, RC_DATA_ST_DONE, RC_LIST_TAIL);
|
|
return (RcData)node;
|
}
|
|
RcData rc_data_get_last_oldest(DataGroup grp)
|
{
|
DataGroupImpl *p = (DataGroupImpl *)grp;
|
RcDataNode *node = rc_data_group_get_node_by_status(
|
p, RC_DATA_ST_DONE, RC_LIST_HEAD);
|
|
return (RcData)node;
|
}
|