/* * 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 #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; }