diff --git a/mpp/base/inc/mpp_meta.h b/mpp/base/inc/mpp_meta.h new file mode 100644 index 00000000..791c4af0 --- /dev/null +++ b/mpp/base/inc/mpp_meta.h @@ -0,0 +1,100 @@ +/* + * Copyright 2015 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. + */ + +#ifndef __MPP_META_H__ +#define __MPP_META_H__ + +#include +#include "rk_type.h" + +#include "mpp_frame.h" +#include "mpp_packet.h" + +/* + * Mpp Metadata definition + * + * Metadata is for information transmision in mpp. + * Mpp task will contain two meta data: + * + * 1. Data flow metadata + * This metadata contains information of input / output data flow. For example + * A. decoder input side task the input packet must be defined and output frame + * may not be defined. Then decoder will try malloc or use committed buffer to + * complete decoding. + * B. decoder output side task + * + * + * 2. Flow control metadata + * + */ +typedef enum MppMetaDataType_e { + /* + * mpp meta data of data flow + * reference counter will be used for these meta data type + */ + MPP_META_TYPE_FRAME = 'mfrm', + MPP_META_TYPE_PACKET = 'mpkt', + MPP_META_TYPE_BUFFER = 'mbuf', + + /* mpp meta data of normal data type */ + MPP_META_TYPE_S32 = 's32 ', + MPP_META_TYPE_S64 = 's64 ', + MPP_META_TYPE_PTR = 'ptr ', +} MppMetaType; + +typedef enum MppMetaKey_e { + MPP_META_KEY_INPUT_FRM = 'ifrm', + MPP_META_KEY_INPUT_PKT = 'ipkt', + MPP_META_KEY_OUTPUT_FRM = 'ofrm', + MPP_META_KEY_OUTPUT_PKT = 'opkt', + MPP_META_KEY_MOTION_INFO = 'mvif', /* output motion information for motion detection */ + + MPP_META_KEY_INPUT_BLOCK = 'iblk', + MPP_META_KEY_OUTPUT_BLOCK = 'oblk', + MPP_META_KEY_INPUT_IDR_REQ = 'iidr', /* input idr frame request flag */ + MPP_META_KEY_OUTPUT_INTRA = 'oidr', /* output intra frame indicator */ +} MppMetaKey; + +typedef void* MppMeta; + +#define mpp_meta_get(meta) mpp_meta_get_with_tag(meta, MODULE_TAG, __FUNCTION__) + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_meta_get_with_tag(MppMeta *meta, const char *tag, const char *caller); +MPP_RET mpp_meta_put(MppMeta meta); + +MPP_RET mpp_meta_set_s32(MppMeta meta, MppMetaKey key, RK_S32 val); +MPP_RET mpp_meta_set_s64(MppMeta meta, MppMetaKey key, RK_S64 val); +MPP_RET mpp_meta_set_ptr(MppMeta meta, MppMetaKey key, void *val); +MPP_RET mpp_meta_get_s32(MppMeta meta, MppMetaKey key, RK_S32 *val); +MPP_RET mpp_meta_get_s64(MppMeta meta, MppMetaKey key, RK_S64 *val); +MPP_RET mpp_meta_get_ptr(MppMeta meta, MppMetaKey key, void **val); + +MPP_RET mpp_meta_set_frame (MppMeta meta, MppMetaKey key, MppFrame *frame); +MPP_RET mpp_meta_set_packet(MppMeta meta, MppMetaKey key, MppPacket *packet); +MPP_RET mpp_meta_set_buffer(MppMeta meta, MppMetaKey key, MppBuffer *buffer); +MPP_RET mpp_meta_get_frame (MppMeta meta, MppMetaKey key, MppFrame *frame); +MPP_RET mpp_meta_get_packet(MppMeta meta, MppMetaKey key, MppPacket *packet); +MPP_RET mpp_meta_get_buffer(MppMeta meta, MppMetaKey key, MppBuffer *buffer); + +#ifdef __cplusplus +} +#endif + +#endif /*__MPP_META_H__*/ diff --git a/mpp/base/mpp_meta.cpp b/mpp/base/mpp_meta.cpp new file mode 100644 index 00000000..4ed8be47 --- /dev/null +++ b/mpp/base/mpp_meta.cpp @@ -0,0 +1,372 @@ +/* + * Copyright 2015 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 "mpp_meta" + +#include + +#include "mpp_mem.h" +#include "mpp_list.h" +#include "mpp_frame.h" +#include "mpp_packet.h" +#include "mpp_common.h" + +#include "mpp_meta.h" + +typedef struct MppMetaDef_t { + MppMetaKey key; + MppMetaType type; +} MppMetaDef; + +typedef struct MppMetaImpl_t { + char tag[MPP_TAG_SIZE]; + const char *caller; + RK_S32 meta_id; + + struct list_head list_meta; + struct list_head list_node; + RK_S32 node_count; +} MppMetaImpl; + +typedef union MppMetaVal_u { + RK_S32 val_s32; + RK_S64 val_s64; + void *val_ptr; + MppFrame frame; + MppPacket packet; + MppBuffer buffer; +} MppMetaVal; + +typedef struct MppMetaNode_t { + struct list_head list_meta; + struct list_head list_node; + MppMetaImpl *meta; + RK_S32 node_id; + + RK_S32 type_id; + MppMetaVal val; +} MppMetaNode; + +static MppMetaDef meta_defs[] = { + /* categorized by type */ + /* data flow type */ + { MPP_META_KEY_INPUT_FRM, MPP_META_TYPE_FRAME, }, + { MPP_META_KEY_OUTPUT_FRM, MPP_META_TYPE_FRAME, }, + { MPP_META_KEY_INPUT_PKT, MPP_META_TYPE_PACKET, }, + { MPP_META_KEY_OUTPUT_PKT, MPP_META_TYPE_PACKET, }, + { MPP_META_KEY_MOTION_INFO, MPP_META_TYPE_BUFFER, }, /* buffer for motion detection */ + + { MPP_META_KEY_INPUT_BLOCK, MPP_META_TYPE_S32, }, + { MPP_META_KEY_OUTPUT_BLOCK, MPP_META_TYPE_S32, }, +}; + +class MppMetaService +{ +private: + // avoid any unwanted function + MppMetaService(); + ~MppMetaService(); + MppMetaService(const MppMetaService &); + MppMetaService &operator=(const MppMetaService &); + + struct list_head mlist_meta; + struct list_head mlist_node; + + RK_U32 meta_id; + RK_U32 meta_count; + RK_U32 node_count; + +public: + static MppMetaService *get_instance() + { + static MppMetaService instance; + return &instance; + } + static Mutex *get_lock() + { + static Mutex lock; + return &lock; + } + + /* + * get_index_of_key does two things: + * 1. Check the key / type pair is correct or not. + * If failed on check return negative value + * 2. Compare all exsisting meta data defines to find the non-negative index + */ + RK_S32 get_index_of_key(MppMetaKey key, MppMetaType type); + + MppMetaImpl *get_meta(const char *tag, const char *caller); + void put_meta(MppMetaImpl *meta); + + MppMetaNode *get_node(MppMetaImpl *meta, RK_S32 index); + void put_node(MppMetaNode *node); +}; + +RK_S32 get_index_of_key(MppMetaKey key, MppMetaKey type) +{ + RK_S32 i = 0; + RK_S32 num = MPP_ARRAY_ELEMS(meta_defs); + + for (i = 0; i < num; i++) { + if ((meta_defs[i].key == key) && (meta_defs[i].type == type)) + break; + } + + return (i < num) ? (i) : (-1); +} + +MppMetaImpl *MppMetaService::get_meta(const char *tag, const char *caller) +{ + MppMetaImpl *impl = mpp_malloc(MppMetaImpl, 1); + if (impl) { + const char *tag_src = (tag) ? (tag) : (MODULE_TAG); + strncpy(impl->tag, tag_src, sizeof(impl->tag)); + impl->caller = caller; + impl->meta_id = meta_id++; + INIT_LIST_HEAD(&impl->list_meta); + INIT_LIST_HEAD(&impl->list_node); + impl->node_count = 0; + + list_add_tail(&impl->list_meta, &mlist_meta); + meta_count++; + } else { + mpp_err_f("failed to malloc meta data\n"); + } + return impl; +} + +void MppMetaService::put_meta(MppMetaImpl *meta) +{ + while (meta->node_count) { + MppMetaNode *node = list_entry(meta->list_node.next, MppMetaNode, list_meta); + put_node(node); + meta->node_count--; + } + list_del_init(&meta->list_meta); + meta_count--; + mpp_free(meta); +} + +MppMetaNode *MppMetaService::get_node(MppMetaImpl *meta, RK_S32 type_id) +{ + MppMetaNode *node = NULL; + if (meta->node_count) { + MppMetaNode *n, *pos; + + list_for_each_entry_safe(pos, n, &meta->list_node, MppMetaNode, list_node) { + if (pos->type_id == type_id) { + node = pos; + break; + } + } + } else { + node = mpp_malloc(MppMetaNode, 1); + if (node) { + INIT_LIST_HEAD(&node->list_meta); + INIT_LIST_HEAD(&node->list_node); + node->meta = meta; + node->node_id = meta->meta_id++; + node->type_id = type_id; + memset(&node->val, 0, sizeof(node->val)); + + meta->node_count++; + list_add_tail(&node->list_meta, &meta->list_node); + list_add_tail(&node->list_node, &mlist_node); + node_count++; + } else { + mpp_err_f("failed to malloc meta data node\n"); + } + } + + return node; +} + +void MppMetaService::put_node(MppMetaNode *node) +{ + MppMetaImpl *meta = node->meta; + list_del_init(&node->list_meta); + list_del_init(&node->list_node); + meta->node_count--; + node_count--; + // TODO: may be we need to release MppFrame / MppPacket / MppBuffer here + switch (meta_defs[node->type_id].type) { + case MPP_META_TYPE_FRAME : { + mpp_frame_deinit(&node->val.frame); + } break; + case MPP_META_TYPE_PACKET : { + mpp_packet_deinit(node->val.packet); + } break; + case MPP_META_TYPE_BUFFER : { + mpp_buffer_put(node->val.buffer); + } break; + default : { + } break; + } + mpp_free(node); +} + +MPP_RET mpp_meta_get_with_tag(MppMeta *meta, const char *tag, const char *caller) +{ + if (NULL == meta) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MppMetaService *service = MppMetaService::get_instance(); + AutoMutex auto_lock(service->get_lock()); + MppMetaImpl *impl = service->get_meta(tag, caller); + *meta = (MppMeta) impl; + return (impl) ? (MPP_OK) : (MPP_NOK); +} + +MPP_RET mpp_meta_put(MppMeta meta) +{ + if (NULL == meta) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MppMetaService *service = MppMetaService::get_instance(); + AutoMutex auto_lock(service->get_lock()); + MppMetaImpl *impl = (MppMetaImpl *)meta; + service->put_meta(impl); + return MPP_OK; +} + +static MPP_RET set_val_by_key(MppMetaImpl *meta, MppMetaKey key, MppMetaType type, MppMetaVal *val) +{ + MPP_RET ret = MPP_NOK; + MppMetaService *service = MppMetaService::get_instance(); + AutoMutex auto_lock(service->get_lock()); + RK_S32 index = service->get_index_of_key(key, type); + if (index < 0) + return ret; + + MppMetaNode *node = service->get_node(meta, index); + if (node) { + node->val = *val; + ret = MPP_OK; + } + return ret; +} + +static MPP_RET get_val_by_key(MppMetaImpl *meta, MppMetaKey key, MppMetaType type, MppMetaVal *val) +{ + MPP_RET ret = MPP_NOK; + MppMetaService *service = MppMetaService::get_instance(); + AutoMutex auto_lock(service->get_lock()); + RK_S32 index = service->get_index_of_key(key, type); + if (index < 0) + return ret; + + MppMetaNode *node = service->get_node(meta, index); + if (node) { + *val = node->val; + ret = MPP_OK; + } + return ret; +} + +MPP_RET mpp_meta_set_s32(MppMeta meta, MppMetaKey key, RK_S32 val) +{ + if (NULL == meta) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MppMetaImpl *impl = (MppMetaImpl *)meta; + MppMetaVal meta_val; + meta_val.val_s32 = val; + return set_val_by_key(impl, key, MPP_META_TYPE_S32, &meta_val); +} + +MPP_RET mpp_meta_set_s64(MppMeta meta, MppMetaKey key, RK_S64 val) +{ + if (NULL == meta) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MppMetaImpl *impl = (MppMetaImpl *)meta; + MppMetaVal meta_val; + meta_val.val_s64 = val; + return set_val_by_key(impl, key, MPP_META_TYPE_S64, &meta_val); +} + +MPP_RET mpp_meta_set_ptr(MppMeta meta, MppMetaKey key, void *val) +{ + if (NULL == meta) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MppMetaImpl *impl = (MppMetaImpl *)meta; + MppMetaVal meta_val; + meta_val.val_ptr = val; + return set_val_by_key(impl, key, MPP_META_TYPE_PTR, &meta_val); +} + +MPP_RET mpp_meta_get_u32(MppMeta meta, MppMetaKey key, RK_S32 *val) +{ + if (NULL == meta) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MppMetaImpl *impl = (MppMetaImpl *)meta; + MppMetaVal meta_val; + MPP_RET ret = get_val_by_key(impl, key, MPP_META_TYPE_S32, &meta_val); + if (MPP_OK == ret) + *val = meta_val.val_s32; + + return ret; +} + +MPP_RET mpp_meta_get_u64(MppMeta meta, MppMetaKey key, RK_S64 *val) +{ + if (NULL == meta) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MppMetaImpl *impl = (MppMetaImpl *)meta; + MppMetaVal meta_val; + MPP_RET ret = get_val_by_key(impl, key, MPP_META_TYPE_S64, &meta_val); + if (MPP_OK == ret) + *val = meta_val.val_s64; + + return ret; +} + +MPP_RET mpp_meta_get_ptr(MppMeta meta, MppMetaKey key, void **val) +{ + if (NULL == meta) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MppMetaImpl *impl = (MppMetaImpl *)meta; + MppMetaVal meta_val; + MPP_RET ret = get_val_by_key(impl, key, MPP_META_TYPE_PTR, &meta_val); + if (MPP_OK == ret) + *val = meta_val.val_ptr; + + return ret; +} + + +