Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4758 right-hear 1
/*
2
 * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
3
 * Copyright (c) 2002-2007, Professor Benoit Macq
4
 * Copyright (c) 2003-2007, Francois-Olivier Devaux
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
17
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
 * POSSIBILITY OF SUCH DAMAGE.
27
 */
28
 
29
#include 
30
#include 
31
#include 
32
 
33
#include "openjpeg.h"
34
#include "../libopenjpeg/j2k.h"
35
#include "../libopenjpeg/jp2.h"
36
#include "../libopenjpeg/cio.h"
37
#include "mj2.h"
38
 
39
static int int_ceildiv(int a, int b) {
40
	return (a + b - 1) / b;
41
}
42
 
43
/**
44
Size of memory first allocated for MOOV box
45
*/
46
#define TEMP_BUF 10000
47
 
48
 
49
/* -------------------------------------------------------------------------- */
50
 
51
/**
52
sample error callback expecting a FILE* client object
53
*/
54
void error_callback(const char *msg, void *client_data) {
55
	FILE *stream = (FILE*)client_data;
56
	fprintf(stream, "[ERROR] %s", msg);
57
}
58
/**
59
sample warning callback expecting a FILE* client object
60
*/
61
void warning_callback(const char *msg, void *client_data) {
62
	FILE *stream = (FILE*)client_data;
63
	fprintf(stream, "[WARNING] %s", msg);
64
}
65
/**
66
sample debug callback expecting a FILE* client object
67
*/
68
void info_callback(const char *msg, void *client_data) {
69
	FILE *stream = (FILE*)client_data;
70
	fprintf(stream, "[INFO] %s", msg);
71
}
72
 
73
/* -------------------------------------------------------------------------- */
74
 
75
 
76
 
77
static void read_siz_marker(FILE *file, opj_image_t *image)
78
{
79
  int len,i;
80
  char buf, buf2[2];
81
  unsigned char *siz_buffer;
82
	opj_cio_t *cio;
83
 
84
  fseek(file, 0, SEEK_SET);
85
  do {
86
    fread(&buf,1,1, file);
87
    if (buf==(char)0xff)
88
      fread(&buf,1,1, file);
89
  }
90
  while (!(buf==(char)0x51));
91
 
92
  fread(buf2,2,1,file);		/* Lsiz                */
93
  len = ((buf2[0])<<8) + buf2[1];
94
 
95
  siz_buffer = (unsigned char*) malloc(len * sizeof(unsigned char));
96
  fread(siz_buffer,len, 1, file);
97
	cio = opj_cio_open(NULL, siz_buffer, len);
98
 
99
  cio_read(cio, 2);			/* Rsiz (capabilities) */
100
  image->x1 = cio_read(cio, 4);	/* Xsiz                */
101
  image->y1 = cio_read(cio, 4);	/* Ysiz                */
102
  image->x0 = cio_read(cio, 4);	/* X0siz               */
103
  image->y0 = cio_read(cio, 4);	/* Y0siz               */
104
  cio_skip(cio, 16);			/* XTsiz, YTsiz, XT0siz, YT0siz        */
105
 
106
  image->numcomps = cio_read(cio,2);	/* Csiz                */
107
  image->comps =
108
    (opj_image_comp_t *) malloc(image->numcomps * sizeof(opj_image_comp_t));
109
 
110
  for (i = 0; i < image->numcomps; i++) {
111
    int tmp;
112
    tmp = cio_read(cio,1);		/* Ssiz_i          */
113
    image->comps[i].prec = (tmp & 0x7f) + 1;
114
    image->comps[i].sgnd = tmp >> 7;
115
    image->comps[i].dx = cio_read(cio,1);	/* XRsiz_i         */
116
    image->comps[i].dy = cio_read(cio,1);	/* YRsiz_i         */
117
    image->comps[i].resno_decoded = 0;	/* number of resolution decoded */
118
    image->comps[i].factor = 0;	/* reducing factor by component */
119
  }
120
  fseek(file, 0, SEEK_SET);
121
	opj_cio_close(cio);
122
  free(siz_buffer);
123
}
124
 
125
static void setparams(opj_mj2_t *movie, opj_image_t *image) {
126
  int i, depth_0, depth, sign;
127
 
128
  movie->tk[0].sample_rate = 25;
129
  movie->tk[0].w = int_ceildiv(image->x1 - image->x0, image->comps[0].dx);
130
  movie->tk[0].h = int_ceildiv(image->y1 - image->y0, image->comps[0].dy);
131
  mj2_init_stdmovie(movie);
132
 
133
  movie->tk[0].depth = image->comps[0].prec;
134
 
135
  if (image->numcomps==3) {
136
    if ((image->comps[0].dx == 1)
137
	&& (image->comps[1].dx == 1)
138
	&& (image->comps[2].dx == 1))
139
      movie->tk[0].CbCr_subsampling_dx = 1;
140
    else
141
	if ((image->comps[0].dx == 1)
142
	&& (image->comps[1].dx == 2)
143
	&& (image->comps[2].dx == 2))
144
      movie->tk[0].CbCr_subsampling_dx = 2;
145
    else
146
      fprintf(stderr,"Image component sizes are incoherent\n");
147
 
148
    if ((image->comps[0].dy == 1)
149
	&& (image->comps[1].dy == 1)
150
	&& (image->comps[2].dy == 1))
151
      movie->tk[0].CbCr_subsampling_dy = 1;
152
    else
153
	if ((image->comps[0].dy == 1)
154
	&& (image->comps[1].dy == 2)
155
	&& (image->comps[2].dy == 2))
156
      movie->tk[0].CbCr_subsampling_dy = 2;
157
    else
158
      fprintf(stderr,"Image component sizes are incoherent\n");
159
  }
160
 
161
  movie->tk[0].sample_rate = 25;
162
 
163
  movie->tk[0].jp2_struct.numcomps = image->numcomps;	// NC
164
 
165
	/* Init Standard jp2 structure */
166
 
167
	movie->tk[0].jp2_struct.comps =
168
    (opj_jp2_comps_t *) malloc(movie->tk[0].jp2_struct.numcomps * sizeof(opj_jp2_comps_t));
169
  movie->tk[0].jp2_struct.precedence = 0;   /* PRECEDENCE*/
170
  movie->tk[0].jp2_struct.approx = 0;   /* APPROX*/
171
  movie->tk[0].jp2_struct.brand = JP2_JP2;	/* BR         */
172
  movie->tk[0].jp2_struct.minversion = 0;	/* MinV       */
173
  movie->tk[0].jp2_struct.numcl = 1;
174
  movie->tk[0].jp2_struct.cl = (unsigned int *) malloc(movie->tk[0].jp2_struct.numcl * sizeof(int));
175
  movie->tk[0].jp2_struct.cl[0] = JP2_JP2;	/* CL0 : JP2  */
176
  movie->tk[0].jp2_struct.C = 7;      /* C : Always 7*/
177
  movie->tk[0].jp2_struct.UnkC = 0;      /* UnkC, colorspace specified in colr box*/
178
  movie->tk[0].jp2_struct.IPR = 0;      /* IPR, no intellectual property*/
179
  movie->tk[0].jp2_struct.w = int_ceildiv(image->x1 - image->x0, image->comps[0].dx);
180
  movie->tk[0].jp2_struct.h = int_ceildiv(image->y1 - image->y0, image->comps[0].dy);
181
 
182
  depth_0 = image->comps[0].prec - 1;
183
  sign = image->comps[0].sgnd;
184
  movie->tk[0].jp2_struct.bpc = depth_0 + (sign << 7);
185
 
186
  for (i = 1; i < image->numcomps; i++) {
187
    depth = image->comps[i].prec - 1;
188
    sign = image->comps[i].sgnd;
189
    if (depth_0 != depth)
190
      movie->tk[0].jp2_struct.bpc = 255;
191
  }
192
 
193
  for (i = 0; i < image->numcomps; i++)
194
    movie->tk[0].jp2_struct.comps[i].bpcc =
195
    image->comps[i].prec - 1 + (image->comps[i].sgnd << 7);
196
 
197
  if ((image->numcomps == 1 || image->numcomps == 3)
198
    && (movie->tk[0].jp2_struct.bpc != 255))
199
    movie->tk[0].jp2_struct.meth = 1;
200
  else
201
    movie->tk[0].jp2_struct.meth = 2;
202
 
203
    if (image->numcomps == 1)
204
     movie->tk[0].jp2_struct.enumcs = 17;  // Grayscale
205
 
206
    else
207
	if ((image->comps[0].dx == 1)
208
	&& (image->comps[1].dx == 1)
209
	&& (image->comps[2].dx == 1)
210
    && (image->comps[0].dy == 1)
211
	&& (image->comps[1].dy == 1)
212
	&& (image->comps[2].dy == 1))
213
     movie->tk[0].jp2_struct.enumcs = 16;    // RGB
214
 
215
    else
216
	if ((image->comps[0].dx == 1)
217
	&& (image->comps[1].dx == 2)
218
	&& (image->comps[2].dx == 2)
219
    && (image->comps[0].dy == 1)
220
	&& (image->comps[1].dy == 2)
221
	&& (image->comps[2].dy == 2))
222
     movie->tk[0].jp2_struct.enumcs = 18;  // YUV
223
 
224
  else
225
    movie->tk[0].jp2_struct.enumcs = 0;	// Unkown profile */
226
}
227
 
228
int main(int argc, char *argv[]) {
229
	opj_cinfo_t* cinfo;
230
	opj_event_mgr_t event_mgr;		/* event manager */
231
  unsigned int snum;
232
  opj_mj2_t *movie;
233
  mj2_sample_t *sample;
234
  unsigned char* frame_codestream;
235
  FILE *mj2file, *j2kfile;
236
  char j2kfilename[50];
237
  unsigned char *buf;
238
  int offset, mdat_initpos;
239
  opj_image_t img;
240
 	opj_cio_t *cio;
241
	mj2_cparameters_t parameters;
242
 
243
  if (argc != 3) {
244
    printf("Usage: %s source_location mj2_filename\n",argv[0]);
245
    printf("Example: %s input/input output.mj2\n",argv[0]);
246
    return 1;
247
  }
248
 
249
  mj2file = fopen(argv[2], "wb");
250
 
251
  if (!mj2file) {
252
    fprintf(stderr, "failed to open %s for writing\n", argv[2]);
253
    return 1;
254
  }
255
 
256
	/*
257
	configure the event callbacks (not required)
258
	setting of each callback is optionnal
259
	*/
260
	memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
261
	event_mgr.error_handler = error_callback;
262
	event_mgr.warning_handler = warning_callback;
263
	event_mgr.info_handler = info_callback;
264
 
265
	/* get a MJ2 decompressor handle */
266
	cinfo = mj2_create_compress();
267
 
268
	/* catch events using our callbacks and give a local context */
269
	opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
270
 
271
	/* setup the decoder encoding parameters using user parameters */
272
	movie = (opj_mj2_t*) cinfo->mj2_handle;
273
	mj2_setup_encoder((opj_mj2_t*)cinfo->mj2_handle, ¶meters);
274
 
275
 
276
	/* Writing JP, FTYP and MDAT boxes
277
	Assuming that the JP and FTYP boxes won't be longer than 300 bytes */
278
 
279
  buf = (unsigned char*) malloc (300 * sizeof(unsigned char));
280
  cio = opj_cio_open(movie->cinfo, buf, 300);
281
  mj2_write_jp(cio);
282
  mj2_write_ftyp(movie, cio);
283
  mdat_initpos = cio_tell(cio);
284
  cio_skip(cio, 4);
285
  cio_write(cio,MJ2_MDAT, 4);
286
  fwrite(buf,cio_tell(cio),1,mj2file);
287
  free(buf);
288
 
289
  // Insert each j2k codestream in a JP2C box
290
  snum=0;
291
  offset = 0;
292
  while(1)
293
  {
294
    sample = &movie->tk[0].sample[snum];
295
    sprintf(j2kfilename,"%s_%05d.j2k",argv[1],snum);
296
    j2kfile = fopen(j2kfilename, "rb");
297
    if (!j2kfile) {
298
      if (snum==0) {  // Could not open a single codestream
299
				fprintf(stderr, "failed to open %s for reading\n",j2kfilename);
300
				return 1;
301
      }
302
      else {	      // Tried to open a inexistant codestream
303
				fprintf(stdout,"%d frames are being added to the MJ2 file\n",snum);
304
				break;
305
      }
306
    }
307
 
308
    // Calculating offset for samples and chunks
309
    offset += cio_tell(cio);
310
    sample->offset = offset;
311
    movie->tk[0].chunk[snum].offset = offset;  // There will be one sample per chunk
312
 
313
    // Calculating sample size
314
    fseek(j2kfile,0,SEEK_END);
315
    sample->sample_size = ftell(j2kfile) + 8; // Sample size is codestream + JP2C box header
316
    fseek(j2kfile,0,SEEK_SET);
317
 
318
    // Reading siz marker of j2k image for the first codestream
319
    if (snum==0)
320
      read_siz_marker(j2kfile, &img);
321
 
322
    // Writing JP2C box header
323
    frame_codestream = (unsigned char*) malloc (sample->sample_size+8);
324
		cio = opj_cio_open(movie->cinfo, frame_codestream, sample->sample_size);
325
    cio_write(cio,sample->sample_size, 4);  // Sample size
326
    cio_write(cio,JP2_JP2C, 4);	// JP2C
327
 
328
    // Writing codestream from J2K file to MJ2 file
329
    fread(frame_codestream+8,sample->sample_size-8,1,j2kfile);
330
    fwrite(frame_codestream,sample->sample_size,1,mj2file);
331
    cio_skip(cio, sample->sample_size-8);
332
 
333
    // Ending loop
334
    fclose(j2kfile);
335
    snum++;
336
    movie->tk[0].sample = (mj2_sample_t*)
337
		realloc(movie->tk[0].sample, (snum+1) * sizeof(mj2_sample_t));
338
    movie->tk[0].chunk = (mj2_chunk_t*)
339
		realloc(movie->tk[0].chunk, (snum+1) * sizeof(mj2_chunk_t));
340
    free(frame_codestream);
341
  }
342
 
343
  // Writing the MDAT box length in header
344
  offset += cio_tell(cio);
345
  buf = (unsigned char*) malloc (4 * sizeof(unsigned char));
346
	cio = opj_cio_open(movie->cinfo, buf, 4);
347
  cio_write(cio,offset-mdat_initpos,4);
348
  fseek(mj2file,(long)mdat_initpos,SEEK_SET);
349
  fwrite(buf,4,1,mj2file);
350
  fseek(mj2file,0,SEEK_END);
351
  free(buf);
352
 
353
  // Setting movie parameters
354
  movie->tk[0].num_samples=snum;
355
  movie->tk[0].num_chunks=snum;
356
  setparams(movie, &img);
357
 
358
  // Writing MOOV box
359
	buf = (unsigned char*) malloc ((TEMP_BUF+snum*20) * sizeof(unsigned char));
360
	cio = opj_cio_open(movie->cinfo, buf, (TEMP_BUF+snum*20));
361
	mj2_write_moov(movie, cio);
362
  fwrite(buf,cio_tell(cio),1,mj2file);
363
 
364
  // Ending program
365
  fclose(mj2file);
366
  free(img.comps);
367
  opj_cio_close(cio);
368
  mj2_destroy_compress(movie);
369
 
370
  return 0;
371
}