blob: dae2e9abf6a63d11061f225a89181542cee62dcf [file] [log] [blame]
/**
* Copyright (C) 2019 The Android Open Source Project
*
* 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.
*/
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <stdio.h>
#include <dirent.h>
#include <dlfcn.h>
#include <signal.h>
#include <SoftOMXPlugin.h>
#include <SoftOMXComponent.h>
#include "ihevc_typedefs.h"
#include "iv.h"
#include "ivd.h"
#include "SoftHEVC.h"
#include "ihevc_buf_mgr.h"
#define LIBNAME "/system/lib/libstagefright_soft_hevcdec.so"
#define LIBNAME_VNDK "/system/lib/vndk-28/libstagefright_soft_hevcdec.so"
#define MAX_ENTRIES (1024)
#define DISABLE_MEM_ACCESS(mem, size)\
mprotect((char *) mem, size, PROT_NONE);
#define ENABLE_MEM_ACCESS(mem, size)\
mprotect((char *) mem, size, PROT_READ | PROT_WRITE);
typedef struct _map_struct_t {
void *start_ptr;
void *mem_ptr;
int num_pages;
size_t mem_size;
} map_struct_t;
static void* (*real_memalign)(size_t, size_t) = NULL;
static void (*real_free)(void *) = NULL;
static int s_memutils_initialized = 0;
static int s_mem_map_index = 0;
static int s_free_write_index = 0;
static int s_free_read_index = 0;
static int s_free_list_size = 0;
static struct sigaction new_sa, old_sa;
map_struct_t s_mem_map[MAX_ENTRIES];
map_struct_t s_free_list[MAX_ENTRIES];
void exit_handler(void) {
size_t page_size = getpagesize();
for (int i = 0; i < s_mem_map_index; i++) {
if (NULL != s_mem_map[i].start_ptr) {
ENABLE_MEM_ACCESS(s_mem_map[i].start_ptr,
(s_mem_map[i].num_pages * page_size));
}
}
for (int i = 0; i < MAX_ENTRIES; i++) {
if (NULL != s_free_list[i].start_ptr) {
ENABLE_MEM_ACCESS(s_free_list[i].start_ptr,
(s_free_list[i].num_pages * page_size));
real_free(s_free_list[i].start_ptr);
memset(&s_free_list[i], 0, sizeof(map_struct_t));
}
}
}
void sigsegv_handler(int signum, siginfo_t *info, void* context) {
exit_handler();
(*old_sa.sa_sigaction)(signum, info, context);
}
void sighandler_init(void) {
sigemptyset(&new_sa.sa_mask);
new_sa.sa_flags = SA_SIGINFO;
new_sa.sa_sigaction = sigsegv_handler;
sigaction(SIGSEGV, &new_sa, &old_sa);
}
void memutils_init(void) {
real_memalign = (void *(*)(size_t, size_t))dlsym(RTLD_NEXT, "memalign");
if (NULL == real_memalign) {
return;
}
real_free = (void (*)(void *))dlsym(RTLD_NEXT, "free");
if (NULL == real_free) {
return;
}
memset(&s_mem_map, 0, MAX_ENTRIES * sizeof(map_struct_t));
sighandler_init();
atexit(exit_handler);
s_memutils_initialized = 1;
}
void *memalign(size_t alignment, size_t size) {
if (s_memutils_initialized == 0) {
memutils_init();
}
if (size == sizeof(buf_mgr_t)) {
return NULL;
}
char* start_ptr;
char* mem_ptr;
size_t total_size;
size_t aligned_size = size;
size_t new_alignment = sizeof(size_t);
size_t no_of_pages;
size_t page_size = getpagesize();
if (s_mem_map_index == MAX_ENTRIES) {
return real_memalign(alignment, size);
}
if (alignment > page_size) {
return real_memalign(alignment, size);
}
if ((0 == page_size) || (0 == alignment) || (0 == size)
|| (0 == new_alignment)) {
return real_memalign(alignment, size);
}
if (0 != (size % new_alignment)) {
aligned_size = size + (new_alignment - (size % new_alignment));
}
if (0 != (aligned_size % page_size)) {
no_of_pages = (aligned_size / page_size) + 2;
} else {
no_of_pages = (aligned_size / page_size) + 1;
}
total_size = (no_of_pages * page_size);
start_ptr = (char *) real_memalign(page_size, total_size);
mem_ptr = (char *) start_ptr + ((no_of_pages - 1) * page_size)
- aligned_size;
DISABLE_MEM_ACCESS((start_ptr + ((no_of_pages - 1) * page_size)), page_size);
s_mem_map[s_mem_map_index].start_ptr = start_ptr;
s_mem_map[s_mem_map_index].mem_ptr = mem_ptr;
s_mem_map[s_mem_map_index].num_pages = no_of_pages;
s_mem_map[s_mem_map_index].mem_size = size;
s_mem_map_index++;
return mem_ptr;
}
void free(void *ptr) {
if (s_memutils_initialized == 0) {
memutils_init();
}
if (ptr != NULL) {
int i = 0;
size_t page_size = getpagesize();
for (i = 0; i < s_mem_map_index; i++) {
if (ptr == s_mem_map[i].mem_ptr) {
s_free_list[s_free_write_index].start_ptr = s_mem_map[i]
.start_ptr;
s_free_list[s_free_write_index].mem_ptr = s_mem_map[i].mem_ptr;
s_free_list[s_free_write_index].num_pages = s_mem_map[i]
.num_pages;
s_free_list[s_free_write_index].mem_size =
s_mem_map[i].mem_size;
s_free_write_index++;
s_free_list_size += s_mem_map[i].mem_size;
DISABLE_MEM_ACCESS(s_mem_map[i].start_ptr,
(s_mem_map[i].num_pages * page_size));
memset(&s_mem_map[i], 0, sizeof(map_struct_t));
while (s_free_list_size > MAX_WINDOW_SIZE) {
ENABLE_MEM_ACCESS(
s_free_list[s_free_read_index].start_ptr,
(s_free_list[s_free_read_index].num_pages
* page_size));
real_free(s_free_list[s_free_read_index].start_ptr);
s_free_list_size -= s_free_list[s_free_read_index].mem_size;
memset(&s_free_list[s_free_read_index], 0,
sizeof(map_struct_t));
s_free_read_index++;
if ((s_free_read_index == MAX_ENTRIES)
|| (s_free_read_index >= s_free_write_index)) {
break;
}
}
return;
}
}
}
real_free(ptr);
return;
}
using namespace android;
typedef SoftOMXComponent *(*CreateSoftOMXComponentFunc)(
const char *, const OMX_CALLBACKTYPE *, OMX_PTR, OMX_COMPONENTTYPE **);
int main(void) {
void *libHandle = dlopen(LIBNAME, RTLD_NOW | RTLD_LOCAL);
if (libHandle == NULL) {
return EXIT_FAILURE;
}
CreateSoftOMXComponentFunc createSoftOMXComponent =
(CreateSoftOMXComponentFunc) dlsym(
libHandle,
"_Z22createSoftOMXComponentPKcPK16OMX_CALLBACKTYPE"
"PvPP17OMX_COMPONENTTYPE");
if (createSoftOMXComponent == NULL) {
dlclose(libHandle);
return EXIT_FAILURE;
}
OMX_COMPONENTTYPE *component = NULL;
SoftHEVC* codec = (SoftHEVC*) (*createSoftOMXComponent)(
"OMX.google.hevc.decoder", NULL, NULL, &component);
dlclose(libHandle);
return EXIT_SUCCESS;
}