Blame src/bin/mj2/opj_mj2_extract.c

Packit caffb5
/*
Packit caffb5
 * The copyright in this software is being made available under the 2-clauses
Packit caffb5
 * BSD License, included below. This software may be subject to other third
Packit caffb5
 * party and contributor rights, including patent rights, and no such rights
Packit caffb5
 * are granted under this license.
Packit caffb5
 *
Packit caffb5
 * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
Packit caffb5
 * Copyright (c) 2002-2014, Professor Benoit Macq
Packit caffb5
 * Copyright (c) 2003-2007, Francois-Olivier Devaux
Packit caffb5
 * All rights reserved.
Packit caffb5
 *
Packit caffb5
 * Redistribution and use in source and binary forms, with or without
Packit caffb5
 * modification, are permitted provided that the following conditions
Packit caffb5
 * are met:
Packit caffb5
 * 1. Redistributions of source code must retain the above copyright
Packit caffb5
 *    notice, this list of conditions and the following disclaimer.
Packit caffb5
 * 2. Redistributions in binary form must reproduce the above copyright
Packit caffb5
 *    notice, this list of conditions and the following disclaimer in the
Packit caffb5
 *    documentation and/or other materials provided with the distribution.
Packit caffb5
 *
Packit caffb5
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
Packit caffb5
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit caffb5
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit caffb5
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
Packit caffb5
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
Packit caffb5
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
Packit caffb5
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Packit caffb5
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
Packit caffb5
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
Packit caffb5
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
Packit caffb5
 * POSSIBILITY OF SUCH DAMAGE.
Packit caffb5
 */
Packit caffb5
Packit caffb5
#include <stdio.h>
Packit caffb5
#include <stdlib.h>
Packit caffb5
#include <string.h>
Packit caffb5
Packit caffb5
#include "openjpeg.h"
Packit caffb5
#include "cio.h"
Packit caffb5
#include "j2k.h"
Packit caffb5
#include "jp2.h"
Packit caffb5
#include "mj2.h"
Packit caffb5
Packit caffb5
/* -------------------------------------------------------------------------- */
Packit caffb5
Packit caffb5
/**
Packit caffb5
sample error callback expecting a FILE* client object
Packit caffb5
*/
Packit caffb5
void error_callback(const char *msg, void *client_data)
Packit caffb5
{
Packit caffb5
    FILE *stream = (FILE*)client_data;
Packit caffb5
    fprintf(stream, "[ERROR] %s", msg);
Packit caffb5
}
Packit caffb5
/**
Packit caffb5
sample warning callback expecting a FILE* client object
Packit caffb5
*/
Packit caffb5
void warning_callback(const char *msg, void *client_data)
Packit caffb5
{
Packit caffb5
    FILE *stream = (FILE*)client_data;
Packit caffb5
    fprintf(stream, "[WARNING] %s", msg);
Packit caffb5
}
Packit caffb5
/**
Packit caffb5
sample debug callback expecting a FILE* client object
Packit caffb5
*/
Packit caffb5
void info_callback(const char *msg, void *client_data)
Packit caffb5
{
Packit caffb5
    FILE *stream = (FILE*)client_data;
Packit caffb5
    fprintf(stream, "[INFO] %s", msg);
Packit caffb5
}
Packit caffb5
Packit caffb5
/* -------------------------------------------------------------------------- */
Packit caffb5
Packit caffb5
Packit caffb5
int main(int argc, char *argv[])
Packit caffb5
{
Packit caffb5
    opj_dinfo_t* dinfo;
Packit caffb5
    opj_event_mgr_t event_mgr;      /* event manager */
Packit caffb5
    int tnum;
Packit caffb5
    unsigned int snum;
Packit caffb5
    opj_mj2_t *movie;
Packit caffb5
    mj2_tk_t *track;
Packit caffb5
    mj2_sample_t *sample;
Packit caffb5
    unsigned char* frame_codestream;
Packit caffb5
    FILE *file, *outfile;
Packit caffb5
    char outfilename[FILENAME_MAX];
Packit caffb5
    mj2_dparameters_t parameters;
Packit caffb5
Packit caffb5
    if (argc != 3) {
Packit caffb5
        printf("Usage: %s mj2filename output_prefix\n", argv[0]);
Packit caffb5
        printf("Example: %s foreman.mj2 output/foreman\n", argv[0]);
Packit caffb5
        return 1;
Packit caffb5
    }
Packit caffb5
Packit caffb5
    if (strlen(argv[2]) + 11 > sizeof(outfilename)) {
Packit caffb5
        fprintf(stderr, "filename %d too long\n", strlen(argv[2]) + 11);
Packit caffb5
        return 1;
Packit caffb5
    }
Packit caffb5
Packit caffb5
    file = fopen(argv[1], "rb");
Packit caffb5
Packit caffb5
    if (!file) {
Packit caffb5
        fprintf(stderr, "failed to open %s for reading\n", argv[1]);
Packit caffb5
        return 1;
Packit caffb5
    }
Packit caffb5
Packit caffb5
    /*
Packit caffb5
    configure the event callbacks (not required)
Packit caffb5
    setting of each callback is optional
Packit caffb5
    */
Packit caffb5
    memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
Packit caffb5
    event_mgr.error_handler = error_callback;
Packit caffb5
    event_mgr.warning_handler = warning_callback;
Packit caffb5
    event_mgr.info_handler = info_callback;
Packit caffb5
Packit caffb5
    /* get a MJ2 decompressor handle */
Packit caffb5
    dinfo = mj2_create_decompress();
Packit caffb5
Packit caffb5
    /* catch events using our callbacks and give a local context */
Packit caffb5
    opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
Packit caffb5
Packit caffb5
    /* setup the decoder decoding parameters using user parameters */
Packit caffb5
    memset(&parameters, 0, sizeof(mj2_dparameters_t));
Packit caffb5
    movie = (opj_mj2_t*) dinfo->mj2_handle;
Packit caffb5
    mj2_setup_decoder(movie, &parameters);
Packit caffb5
Packit caffb5
    if (mj2_read_struct(file, movie)) { /* Creating the movie structure*/
Packit caffb5
        return 1;
Packit caffb5
    }
Packit caffb5
Packit caffb5
    /* Decode first video track */
Packit caffb5
    tnum = 0;
Packit caffb5
    while (movie->tk[tnum].track_type != 0) {
Packit caffb5
        tnum ++;
Packit caffb5
    }
Packit caffb5
Packit caffb5
    track = &movie->tk[tnum];
Packit caffb5
Packit caffb5
    fprintf(stdout, "Extracting %d frames from file...\n", track->num_samples);
Packit caffb5
Packit caffb5
    for (snum = 0; snum < track->num_samples; snum++) {
Packit caffb5
        sample = &track->sample[snum];
Packit caffb5
        frame_codestream = (unsigned char*) malloc(sample->sample_size -
Packit caffb5
                           8); /* Skipping JP2C marker*/
Packit caffb5
        fseek(file, sample->offset + 8, SEEK_SET);
Packit caffb5
        fread(frame_codestream, sample->sample_size - 8, 1,
Packit caffb5
              file); /* Assuming that jp and ftyp markers size do*/
Packit caffb5
Packit caffb5
        {
Packit caffb5
            int num = snprintf(outfilename, sizeof(outfilename),
Packit caffb5
                               "%s_%05d.j2k", argv[2],
Packit caffb5
                               snum);
Packit caffb5
            if (num >= sizeof(outfilename)) {
Packit caffb5
                fprintf(stderr, "maximum length of output prefix exceeded\n");
Packit caffb5
                free(frame_codestream);
Packit caffb5
                return 1;
Packit caffb5
            }
Packit caffb5
        }
Packit caffb5
Packit caffb5
        outfile = fopen(outfilename, "wb");
Packit caffb5
        if (!outfile) {
Packit caffb5
            fprintf(stderr, "failed to open %s for writing\n", outfilename);
Packit caffb5
            free(frame_codestream);
Packit caffb5
            return 1;
Packit caffb5
        }
Packit caffb5
        fwrite(frame_codestream, sample->sample_size - 8, 1, outfile);
Packit caffb5
        fclose(outfile);
Packit caffb5
        free(frame_codestream);
Packit caffb5
    }
Packit caffb5
    fclose(file);
Packit caffb5
    fprintf(stdout, "%d frames correctly extracted\n", snum);
Packit caffb5
Packit caffb5
    /* free remaining structures */
Packit caffb5
    if (dinfo) {
Packit caffb5
        mj2_destroy_decompress((opj_mj2_t*)dinfo->mj2_handle);
Packit caffb5
    }
Packit caffb5
Packit caffb5
    return 0;
Packit caffb5
}