1 /**
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #define _GNU_SOURCE
17 #include <sys/types.h>
18 #include <sys/wait.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include "openjpeg.h"
22 #include "opj_includes.h"
23 
24 #define REPEATVALUES    100000
25 
26 unsigned char gStartValues[] = { 0xFF, 0x4F, 0xFF, 0x51, 0x00, 0x2F, 0x00, 0x00,
27         0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x00,
28         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x2E,
29         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x01,
30         0x01, 0x07, 0x01, 0x01, 0x07, 0x01, 0x01, 0xFF, 0x64, 0x00, 0x23, 0x00,
31         0x01, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6F, 0x72, 0x3A, 0x20, 0x4A, 0x61,
32         0x73, 0x50, 0x65, 0x72, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E,
33         0x20, 0x31, 0x2E, 0x37, 0x30, 0x30, 0x2E, 0x31, 0xFF, 0x52, 0x00, 0x0C,
34         0x00, 0x00, 0x00, 0x01, 0x01, 0x05, 0x04, 0x04, 0x00, 0x01, 0xFF, 0x5C,
35         0x00, 0x13, 0x40, 0x40, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48, 0x48,
36         0x50, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0xFF, 0x5D, 0x00, 0x14, 0x01,
37         0x40, 0x40, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48,
38         0x48, 0x50, 0x48, 0x48, 0x50, 0xFF, 0x5D, 0x00, 0x14, 0x02, 0x40, 0x40,
39         0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50,
40         0x48, 0x48, 0x50 };
41 unsigned int gNumStartValues = sizeof(gStartValues) / sizeof(gStartValues[0]);
42 
43 unsigned char gRepeatValues[] = { 0xFF, 0x75, 0x00, 0x09, 0x00, 0x00, 0x00,
44         0x00, 0x00, 0x00, 0x00 };
45 unsigned int gNumRepeatValues = sizeof(gRepeatValues)
46         / sizeof(gRepeatValues[0]);
47 
48 unsigned char gLastValues[] = { 0xFF, 0x75, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00,
49         0x00, 0x00, 0x00 };
50 unsigned int gNumLastValues = sizeof(gLastValues) / sizeof(gLastValues[0]);
51 
52 typedef struct {
53     char* blob;
54     ssize_t blobSize;
55     ssize_t readPos;
56 } applicationContext;
57 
allocate_stream(void)58 opj_stream_t* allocate_stream(void) {
59     opj_stream_private_t * stream = NULL;
60 
61     stream = (opj_stream_private_t*) opj_calloc(1, sizeof(opj_stream_private_t));
62     if (!stream) {
63         return NULL;
64     }
65 
66     stream->m_buffer_size = OPJ_J2K_STREAM_CHUNK_SIZE;
67     stream->m_stored_data = (OPJ_BYTE *) opj_malloc(OPJ_J2K_STREAM_CHUNK_SIZE);
68     if (!stream->m_stored_data) {
69         opj_free(stream);
70         return NULL;
71     }
72 
73     stream->m_current_data = stream->m_stored_data;
74     stream->m_status |= OPJ_STREAM_STATUS_INPUT;
75     stream->m_opj_skip = opj_stream_read_skip;
76     stream->m_opj_seek = opj_stream_read_seek;
77     stream->m_read_fn = opj_stream_default_read;
78     stream->m_write_fn = opj_stream_default_write;
79     stream->m_skip_fn = opj_stream_default_skip;
80     stream->m_seek_fn = opj_stream_default_seek;
81 
82     return (opj_stream_t *) stream;
83 }
84 
ReadHandler(void * buffer,OPJ_SIZE_T length,void * context)85 static OPJ_SIZE_T ReadHandler(void *buffer, OPJ_SIZE_T length, void *context) {
86     applicationContext* appContext = (applicationContext*) context;
87     ssize_t count = 0;
88     ssize_t rem = 0;
89     if (!appContext) {
90         return ((OPJ_SIZE_T) - 1);
91     }
92     rem = appContext->blobSize - appContext->readPos;
93     if ((ssize_t) length <= rem) {
94         count = length;
95     } else {
96         count = rem;
97     }
98     memcpy(buffer, &appContext->blob[appContext->readPos], count);
99     appContext->readPos += count;
100     return ((OPJ_SIZE_T) length);
101 }
102 
main(void)103 int main(void) {
104     ssize_t offset = 0;
105     unsigned int count = 0;
106     applicationContext sContext;
107     opj_j2k_t* codec = NULL;
108     opj_stream_t* stream = NULL;
109     opj_image_t* image = NULL;
110     opj_stream_private_t* private = NULL;
111     opj_event_mgr_t eventMgr;
112     stream = allocate_stream();
113     private = (opj_stream_private_t*)stream;
114 
115     sContext.blobSize = gNumStartValues + REPEATVALUES * gNumRepeatValues
116             + gNumLastValues;
117     sContext.blob = (char*) opj_malloc(sContext.blobSize);
118     if (!sContext.blob) {
119         return EXIT_FAILURE;
120     }
121     memset(sContext.blob, 0, sContext.blobSize);
122 
123     memcpy(&sContext.blob[offset], gStartValues, gNumStartValues);
124     offset += gNumStartValues;
125     for (count = 0; count < REPEATVALUES; ++count) {
126         memcpy(&sContext.blob[offset], gRepeatValues, gNumRepeatValues);
127         offset += gNumRepeatValues;
128     }
129     memcpy(&sContext.blob[offset], gLastValues, gNumLastValues);
130     offset += gNumLastValues;
131     sContext.readPos = 0;
132     private->m_read_fn = ReadHandler;
133     private->m_user_data = (void*)&sContext;
134     private->m_user_data_length = sContext.blobSize;
135     private->m_free_user_data_fn = NULL;
136     codec = opj_j2k_create_decompress();
137     opj_set_default_event_handler(&eventMgr);
138     opj_j2k_read_header(private,codec,&image,&eventMgr);
139     opj_free(sContext.blob);
140     return EXIT_SUCCESS;
141 }
142