blob: f7d8a9219e0ca9595dc61eb48102fe8e9ba00b3a [file] [log] [blame]
/*
* Copyright (c) 2010-2012,2014-2016 Freescale Semiconductor, Inc. All rights reserved.
*
*/
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Module Name: aiurregistry.c
*
* Description: Implementation of utils functions for registry for
* unified parser core functions
*
* Portability: This code is written for Linux OS and Gstreamer
*/
/*
* Changelog:
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include "aiurregistry.h"
#define CORE_QUERY_INTERFACE_API_NAME "FslParserQueryInterface"
#ifdef _ARM11
#define AIUR_REGISTRY_FILE_DEFAULT "/usr/share/aiur_registry_1.0.arm11.cf"
#elif defined (_ARM9)
#define AIUR_REGISTRY_FILE_DEFAULT "/usr/share/aiur_registry1.0.arm9.cf"
#else
#define AIUR_REGISTRY_FILE_DEFAULT "/usr/share/aiur_registry_1.0.arm.cf"
#endif
#define AIUR_REGISTRY_FILE_ENV_NAME "AIUR_REGISTRY"
static GstsutilsEntry *g_aiur_caps_entry = NULL;
/* id table for all core apis, the same order with AiurCoreInterface */
uint32 aiur_core_interface_id_table[] = {
PARSER_API_GET_VERSION_INFO,
PARSER_API_CREATE_PARSER,
PARSER_API_DELETE_PARSER,
PARSER_API_CREATE_PARSER2,
PARSER_API_INITIALIZE_INDEX,
PARSER_API_IMPORT_INDEX,
PARSER_API_EXPORT_INDEX,
PARSER_API_IS_MOVIE_SEEKABLE,
PARSER_API_GET_MOVIE_DURATION,
PARSER_API_GET_USER_DATA,
PARSER_API_GET_META_DATA,
PARSER_API_GET_NUM_TRACKS,
PARSER_API_GET_NUM_PROGRAMS,
PARSER_API_GET_PROGRAM_TRACKS,
PARSER_API_GET_TRACK_TYPE,
PARSER_API_GET_DECODER_SPECIFIC_INFO,
PARSER_API_GET_TRACK_DURATION,
PARSER_API_GET_LANGUAGE,
PARSER_API_GET_BITRATE,
PARSER_API_GET_VIDEO_FRAME_WIDTH,
PARSER_API_GET_VIDEO_FRAME_HEIGHT,
PARSER_API_GET_VIDEO_FRAME_RATE,
PARSER_API_GET_VIDEO_FRAME_ROTATION,
PARSER_API_GET_AUDIO_NUM_CHANNELS,
PARSER_API_GET_AUDIO_SAMPLE_RATE,
PARSER_API_GET_AUDIO_BITS_PER_SAMPLE,
PARSER_API_GET_AUDIO_BLOCK_ALIGN,
PARSER_API_GET_AUDIO_CHANNEL_MASK,
PARSER_API_GET_AUDIO_BITS_PER_FRAME,
PARSER_API_GET_TEXT_TRACK_WIDTH,
PARSER_API_GET_TEXT_TRACK_HEIGHT,
PARSER_API_GET_READ_MODE,
PARSER_API_SET_READ_MODE,
PARSER_API_ENABLE_TRACK,
PARSER_API_GET_NEXT_SAMPLE,
PARSER_API_GET_NEXT_SYNC_SAMPLE,
PARSER_API_GET_FILE_NEXT_SAMPLE,
PARSER_API_GET_FILE_NEXT_SYNC_SAMPLE,
PARSER_API_SEEK,
};
static AiurCoreInterface *
_aiur_core_create_interface_from_entry (gchar * dl_name)
{
AiurCoreInterface *inf = NULL;
void *dl_handle = NULL;
int i;
int32 err;
int total = G_N_ELEMENTS (aiur_core_interface_id_table);
void **papi;
tFslParserQueryInterface query_interface;
dl_handle = dlopen (dl_name, RTLD_LAZY);
if (!dl_handle) {
g_print ("Demux core %s error or missed! \n(Err: %s)\n",
dl_name, dlerror ());
goto fail;
}
query_interface = dlsym (dl_handle, CORE_QUERY_INTERFACE_API_NAME);
if (query_interface == NULL) {
g_print ("can not find symbol %s\n", CORE_QUERY_INTERFACE_API_NAME);
goto fail;
}
inf = g_new0 (AiurCoreInterface, 1);
if (inf == NULL)
goto fail;
papi = (void **) inf;
for (i = 0; i < total; i++) {
err = query_interface (aiur_core_interface_id_table[i], papi);
if (err) {
*papi = NULL;
}
papi++;
}
inf->dl_handle = dl_handle;
if (inf->getVersionInfo) {
inf->coreid = (inf->getVersionInfo) ();
if (inf->coreid) {
g_print ("\n====== AIUR: %s build on %s %s. ======\n\tCore: %s\n file: %s\n",
VERSION, __DATE__,__TIME__, inf->coreid, dl_name);
}
}
//inf->dlentry = g_aiur_caps_entry;
return inf;
fail:
if (dl_handle) {
dlclose (dl_handle);
}
return inf;
}
static GstCaps * aiur_get_caps_from_entry(GstsutilsEntry * entry)
{
int group_count=0;
int index = 0;
char* mime = NULL;
char* libname = NULL;
GstsutilsGroup *group=NULL;
void *dlhandle = NULL;
GstCaps * caps = NULL;
group_count = gstsutils_get_group_count(entry);
for(index = 1; index <= group_count; index++){
if(!gstsutils_get_group_by_index(entry,index,&group))
continue;
if(!gstsutils_get_value_by_key(group,FSL_KEY_MIME,&mime)){
continue;
}
if(!gstsutils_get_value_by_key(group,FSL_KEY_LIB,&libname)){
g_free(mime);
continue;
}
dlhandle = dlopen (libname, RTLD_LAZY);
if (!dlhandle) {
g_free(mime);
g_free(libname);
continue;
}
if (caps) {
GstCaps *newcaps = gst_caps_from_string (mime);
if (newcaps) {
if (!gst_caps_is_subset (newcaps, caps)) {
gst_caps_append (caps, newcaps);
} else {
gst_caps_unref (newcaps);
}
}
} else {
caps = gst_caps_from_string (mime);
}
dlclose (dlhandle);
g_free(mime);
g_free(libname);
}
return caps;
}
static GstsutilsGroup * aiur_core_find_caps_group(GstsutilsEntry *entry,GstCaps * caps)
{
int group_count=0;
int index = 0;
char* mime = NULL;
GstsutilsGroup *group=NULL;
void *dlhandle = NULL;
GstCaps * super_caps = NULL;
gboolean found = FALSE;
group_count = gstsutils_get_group_count(entry);
for(index = 1; index <= group_count; index++){
if(found)
break;
if(!gstsutils_get_group_by_index(entry,index,&group))
continue;
if(!gstsutils_get_value_by_key(group,FSL_KEY_MIME,&mime)){
continue;
}
super_caps = gst_caps_from_string (mime);
if ((super_caps) && (gst_caps_is_subset (caps, super_caps))) {
found = TRUE;
}
if(super_caps)
gst_caps_unref (super_caps);
g_free(mime);
}
return group;
}
GstCaps *
aiur_core_get_caps ()
{
GstCaps *caps = NULL;
if(g_aiur_caps_entry == NULL){
char *aiurenv = getenv (AIUR_REGISTRY_FILE_ENV_NAME);
if (aiurenv == NULL) {
aiurenv = AIUR_REGISTRY_FILE_DEFAULT;
}
g_aiur_caps_entry = gstsutils_init_entry(aiurenv);
}
caps = aiur_get_caps_from_entry(g_aiur_caps_entry);
return caps;
}
AiurCoreInterface *
aiur_core_create_interface_from_caps (GstCaps * caps)
{
AiurCoreInterface *inf = NULL;
GstsutilsGroup * group;
gchar * libname = NULL;
gchar * libname2 = NULL;
gchar * temp_name;
gboolean find = TRUE;
void *dlhandle = NULL;
group = aiur_core_find_caps_group(g_aiur_caps_entry,caps);
if (group) {
if(gstsutils_get_value_by_key(group,FSL_KEY_LIB2,&libname2)){
dlhandle = dlopen (libname2, RTLD_LAZY);
if(dlhandle){
libname = libname2;
dlclose (dlhandle);
}else{
g_free(libname2);
}
}
if(libname == NULL)
find = gstsutils_get_value_by_key(group,FSL_KEY_LIB,&libname);
if (find)
inf = _aiur_core_create_interface_from_entry (libname);
else
return inf;
if(libname)
g_free(libname);
inf->name = gstsutils_get_group_name(group);
}
return inf;
}
void
aiur_core_destroy_interface (AiurCoreInterface * inf)
{
if (inf == NULL)
return;
if (inf->dl_handle) {
dlclose (inf->dl_handle);
}
g_free(inf->name);
g_free (inf);
}
void __attribute__ ((destructor)) aiur_free_dll_entry (void);
void
aiur_free_dll_entry ()
{
gstsutils_deinit_entry(g_aiur_caps_entry);
}