Files
UltraGrid/libgpujpeg/gpujpeg_reader.c
2012-02-10 10:51:15 +01:00

687 lines
25 KiB
C

/**
* Copyright (c) 2011, CESNET z.s.p.o
* Copyright (c) 2011, Silicon Genome, LLC.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "gpujpeg_reader.h"
#include "gpujpeg_decoder.h"
#include "gpujpeg_util.h"
/** Documented at declaration */
struct gpujpeg_reader*
gpujpeg_reader_create()
{
struct gpujpeg_reader* reader = malloc(sizeof(struct gpujpeg_reader));
if ( reader == NULL )
return NULL;
return reader;
}
/** Documented at declaration */
int
gpujpeg_reader_destroy(struct gpujpeg_reader* reader)
{
assert(reader != NULL);
free(reader);
return 0;
}
/**
* Read byte from image data
*
* @param image
* @return byte
*/
#define gpujpeg_reader_read_byte(image) \
(uint8_t)(*(image)++)
/**
* Read two-bytes from image data
*
* @param image
* @return 2 bytes
*/
#define gpujpeg_reader_read_2byte(image) \
(uint16_t)(((*(image)) << 8) + (*((image) + 1))); \
image += 2;
/**
* Read marker from image data
*
* @param image
* @return marker code
*/
int
gpujpeg_reader_read_marker(uint8_t** image)
{
if( gpujpeg_reader_read_byte(*image) != 0xFF )
return -1;
int marker = gpujpeg_reader_read_byte(*image);
return marker;
}
/**
* Skip marker content (read length and that much bytes - 2)
*
* @param image
* @return void
*/
void
gpujpeg_reader_skip_marker_content(uint8_t** image)
{
int length = (int)gpujpeg_reader_read_2byte(*image);
*image += length - 2;
}
/**
* Read application ifno block from image
*
* @param image
* @return 0 if succeeds, otherwise nonzero
*/
int
gpujpeg_reader_read_app0(uint8_t** image)
{
int length = (int)gpujpeg_reader_read_2byte(*image);
if ( length != 16 ) {
fprintf(stderr, "[GPUJPEG] [Error] APP0 marker length should be 16 but %d was presented!\n", length);
return -1;
}
char jfif[4];
jfif[0] = gpujpeg_reader_read_byte(*image);
jfif[1] = gpujpeg_reader_read_byte(*image);
jfif[2] = gpujpeg_reader_read_byte(*image);
jfif[3] = gpujpeg_reader_read_byte(*image);
jfif[4] = gpujpeg_reader_read_byte(*image);
if ( strcmp(jfif, "JFIF") != 0 ) {
fprintf(stderr, "[GPUJPEG] [Error] APP0 marker identifier should be 'JFIF' but '%s' was presented!\n", jfif);
return -1;
}
int version_major = gpujpeg_reader_read_byte(*image);
int version_minor = gpujpeg_reader_read_byte(*image);
if ( version_major != 1 || version_minor != 1 ) {
fprintf(stderr, "[GPUJPEG] [Error] APP0 marker version should be 1.1 but %d.%d was presented!\n", version_major, version_minor);
return -1;
}
int pixel_units = gpujpeg_reader_read_byte(*image);
int pixel_xdpu = gpujpeg_reader_read_2byte(*image);
int pixel_ydpu = gpujpeg_reader_read_2byte(*image);
int thumbnail_width = gpujpeg_reader_read_byte(*image);
int thumbnail_height = gpujpeg_reader_read_byte(*image);
return 0;
}
/**
* Read quantization table definition block from image
*
* @param decoder
* @param image
* @return 0 if succeeds, otherwise nonzero
*/
int
gpujpeg_reader_read_dqt(struct gpujpeg_decoder* decoder, uint8_t** image)
{
int length = (int)gpujpeg_reader_read_2byte(*image);
length -= 2;
if ( length != 65 ) {
fprintf(stderr, "[GPUJPEG] [Error] DQT marker length should be 65 but %d was presented!\n", length);
return -1;
}
int index = gpujpeg_reader_read_byte(*image);
struct gpujpeg_table_quantization* table;
if( index == 0 ) {
table = &decoder->table_quantization[GPUJPEG_COMPONENT_LUMINANCE];
} else if ( index == 1 ) {
table = &decoder->table_quantization[GPUJPEG_COMPONENT_CHROMINANCE];
} else {
fprintf(stderr, "[GPUJPEG] [Error] DQT marker index should be 0 or 1 but %d was presented!\n", index);
return -1;
}
for ( int i = 0; i < 64; i++ ) {
table->table_raw[i] = gpujpeg_reader_read_byte(*image);
}
// Prepare quantization table for read raw table
gpujpeg_table_quantization_decoder_compute(table);
return 0;
}
/**
* Read start of frame block from image
*
* @param image
* @return 0 if succeeds, otherwise nonzero
*/
int
gpujpeg_reader_read_sof0(struct gpujpeg_decoder* decoder, uint8_t** image)
{
int length = (int)gpujpeg_reader_read_2byte(*image);
if ( length < 6 ) {
fprintf(stderr, "[GPUJPEG] [Error] SOF0 marker length should be greater than 6 but %d was presented!\n", length);
return -1;
}
length -= 2;
int precision = (int)gpujpeg_reader_read_byte(*image);
if ( precision != 8 ) {
fprintf(stderr, "[GPUJPEG] [Error] SOF0 marker precision should be 8 but %d was presented!\n", precision);
return -1;
}
decoder->reader->param_image.height = (int)gpujpeg_reader_read_2byte(*image);
decoder->reader->param_image.width = (int)gpujpeg_reader_read_2byte(*image);
decoder->reader->param_image.comp_count = (int)gpujpeg_reader_read_byte(*image);
length -= 6;
for ( int comp = 0; comp < decoder->reader->param_image.comp_count; comp++ ) {
int index = (int)gpujpeg_reader_read_byte(*image);
if ( index != (comp + 1) ) {
fprintf(stderr, "[GPUJPEG] [Error] SOF0 marker component %d id should be %d but %d was presented!\n", comp, comp + 1, index);
return -1;
}
int sampling = (int)gpujpeg_reader_read_byte(*image);
decoder->reader->param.sampling_factor[comp].horizontal = (sampling >> 4) & 15;
decoder->reader->param.sampling_factor[comp].vertical = (sampling) & 15;
int table_index = (int)gpujpeg_reader_read_byte(*image);
if ( comp == 0 && table_index != 0 ) {
fprintf(stderr, "[GPUJPEG] [Error] SOF0 marker component Y should have quantization table index 0 but %d was presented!\n", table_index);
return -1;
}
if ( (comp == 1 || comp == 2) && table_index != 1 ) {
fprintf(stderr, "[GPUJPEG] [Error] SOF0 marker component Cb or Cr should have quantization table index 1 but %d was presented!\n", table_index);
return -1;
}
length -= 3;
}
// Check length
if ( length > 0 ) {
fprintf(stderr, "[GPUJPEG] [Warning] SOF0 marker contains %d more bytes than needed!\n", length);
*image += length;
}
return 0;
}
/**
* Read huffman table definition block from image
*
* @param decoder
* @param image
* @return 0 if succeeds, otherwise nonzero
*/
int
gpujpeg_reader_read_dht(struct gpujpeg_decoder* decoder, uint8_t** image)
{
int length = (int)gpujpeg_reader_read_2byte(*image);
length -= 2;
int index = gpujpeg_reader_read_byte(*image);
struct gpujpeg_table_huffman_decoder* table = NULL;
struct gpujpeg_table_huffman_decoder* d_table = NULL;
switch(index) {
case 0:
table = &decoder->table_huffman[GPUJPEG_COMPONENT_LUMINANCE][GPUJPEG_HUFFMAN_DC];
d_table = decoder->d_table_huffman[GPUJPEG_COMPONENT_LUMINANCE][GPUJPEG_HUFFMAN_DC];
break;
case 16:
table = &decoder->table_huffman[GPUJPEG_COMPONENT_LUMINANCE][GPUJPEG_HUFFMAN_AC];
d_table = decoder->d_table_huffman[GPUJPEG_COMPONENT_LUMINANCE][GPUJPEG_HUFFMAN_AC];
break;
case 1:
table = &decoder->table_huffman[GPUJPEG_COMPONENT_CHROMINANCE][GPUJPEG_HUFFMAN_DC];
d_table = decoder->d_table_huffman[GPUJPEG_COMPONENT_CHROMINANCE][GPUJPEG_HUFFMAN_DC];
break;
case 17:
table = &decoder->table_huffman[GPUJPEG_COMPONENT_CHROMINANCE][GPUJPEG_HUFFMAN_AC];
d_table = decoder->d_table_huffman[GPUJPEG_COMPONENT_CHROMINANCE][GPUJPEG_HUFFMAN_AC];
break;
default:
fprintf(stderr, "[GPUJPEG] [Error] DHT marker index should be 0, 1, 16 or 17 but %d was presented!\n", index);
return -1;
}
length -= 1;
// Read in bits[]
table->bits[0] = 0;
int count = 0;
for ( int i = 1; i <= 16; i++ ) {
table->bits[i] = gpujpeg_reader_read_byte(*image);
count += table->bits[i];
if ( length > 0 ) {
length--;
} else {
fprintf(stderr, "[GPUJPEG] [Error] DHT marker unexpected end when reading bit counts!\n", index);
return -1;
}
}
// Read in huffval
for ( int i = 0; i < count; i++ ){
table->huffval[i] = gpujpeg_reader_read_byte(*image);
if ( length > 0 ) {
length--;
} else {
fprintf(stderr, "[GPUJPEG] [Error] DHT marker unexpected end when reading huffman values!\n", index);
return -1;
}
}
// Check length
if ( length > 0 ) {
fprintf(stderr, "[GPUJPEG] [Warning] DHT marker contains %d more bytes than needed!\n", length);
*image += length;
}
// Compute huffman table for read values
gpujpeg_table_huffman_decoder_compute(table, d_table);
return 0;
}
/**
* Read restart interval block from image
*
* @param decoder
* @param image
* @return 0 if succeeds, otherwise nonzero
*/
int
gpujpeg_reader_read_dri(struct gpujpeg_decoder* decoder, uint8_t** image)
{
int length = (int)gpujpeg_reader_read_2byte(*image);
if ( length != 4 ) {
fprintf(stderr, "[GPUJPEG] [Error] DRI marker length should be 4 but %d was presented!\n", length);
return -1;
}
int restart_interval = gpujpeg_reader_read_2byte(*image);
if ( restart_interval == decoder->reader->param.restart_interval )
return 0;
if ( decoder->reader->param.restart_interval != 0 ) {
fprintf(stderr, "[GPUJPEG] [Error] DRI marker can't redefine restart interval!");
fprintf(stderr, "This may be caused when more DRI markers are presented which is not supported!\n");
return -1;
}
decoder->reader->param.restart_interval = restart_interval;
return 0;
}
/**
* Read start of scan block from image
*
* @param image
* @param image_end
* @return 0 if succeeds, otherwise nonzero
*/
int
gpujpeg_reader_read_sos(struct gpujpeg_decoder* decoder, uint8_t** image, uint8_t* image_end)
{
int length = (int)gpujpeg_reader_read_2byte(*image);
length -= 2;
int comp_count = (int)gpujpeg_reader_read_byte(*image);
// Not interleaved mode
if ( comp_count == 1 ) {
decoder->reader->param.interleaved = 0;
}
// Interleaved mode
else if ( comp_count == decoder->reader->param_image.comp_count ) {
if ( decoder->reader->comp_count != 0 ) {
fprintf(stderr, "[GPUJPEG] [Error] SOS marker component count %d is not supported for multiple scans!\n", comp_count);
return -1;
}
decoder->reader->param.interleaved = 1;
}
// Unknown mode
else {
fprintf(stderr, "[GPUJPEG] [Error] SOS marker component count %d is not supported (should be 1 or equals to total component count)!\n", comp_count);
return -1;
}
// We must init decoder before data is loaded into it
if ( decoder->reader->comp_count == 0 ) {
// Init decoder
gpujpeg_decoder_init(decoder, &decoder->reader->param, &decoder->reader->param_image);
}
// Check maximum component count
decoder->reader->comp_count += comp_count;
if ( decoder->reader->comp_count > decoder->reader->param_image.comp_count ) {
fprintf(stderr, "[GPUJPEG] [Error] SOS marker component count for all scans %d exceeds maximum component count %d!\n",
decoder->reader->comp_count, decoder->reader->param_image.comp_count);
}
// Collect the component-spec parameters
for ( int comp = 0; comp < comp_count; comp++ )
{
int index = (int)gpujpeg_reader_read_byte(*image);
int table = (int)gpujpeg_reader_read_byte(*image);
int table_dc = (table >> 4) & 15;
int table_ac = table & 15;
if ( index == 1 && (table_ac != 0 || table_dc != 0) ) {
fprintf(stderr, "[GPUJPEG] [Error] SOS marker for Y should have huffman tables 0,0 but %d,%d was presented!\n", table_dc, table_ac);
return -1;
}
if ( (index == 2 || index == 3) && (table_ac != 1 || table_dc != 1) ) {
fprintf(stderr, "[GPUJPEG] [Error] SOS marker for Cb or Cr should have huffman tables 1,1 but %d,%d was presented!\n", table_dc, table_ac);
return -1;
}
}
// Collect the additional scan parameters Ss, Se, Ah/Al.
int Ss = (int)gpujpeg_reader_read_byte(*image);
int Se = (int)gpujpeg_reader_read_byte(*image);
int Ax = (int)gpujpeg_reader_read_byte(*image);
int Ah = (Ax >> 4) & 15;
int Al = (Ax) & 15;
// Check maximum scan count
if ( decoder->reader->scan_count >= GPUJPEG_MAX_COMPONENT_COUNT ) {
fprintf(stderr, "[GPUJPEG] [Error] SOS marker reached maximum number of scans (3)!\n");
return -1;
}
int scan_index = decoder->reader->scan_count;
// Get scan structure
struct gpujpeg_reader_scan* scan = &decoder->reader->scan[scan_index];
decoder->reader->scan_count++;
// Scan segments begin at the end of previous scan segments or from zero index
scan->segment_index = decoder->reader->segment_count;
scan->segment_count = 0;
// Get first segment in scan
struct gpujpeg_segment* segment = &decoder->coder.segment[scan->segment_index];
segment->scan_index = scan_index;
segment->scan_segment_index = scan->segment_count;
segment->data_compressed_index = decoder->reader->data_compressed_size;
scan->segment_count++;
// Read scan data
uint8_t byte = 0;
uint8_t byte_previous = 0;
uint8_t previous_marker = GPUJPEG_MARKER_RST0 - 1;
do {
byte_previous = byte;
byte = gpujpeg_reader_read_byte(*image);
decoder->coder.data_compressed[decoder->reader->data_compressed_size] = byte;
decoder->reader->data_compressed_size++;
// Check markers
if ( byte_previous == 0xFF ) {
// Check zero byte
if ( byte == 0 ) {
continue;
}
// Check restart marker
else if ( byte >= GPUJPEG_MARKER_RST0 && byte <= GPUJPEG_MARKER_RST7 ) {
// Check expected marker
uint8_t expected_marker = (previous_marker < GPUJPEG_MARKER_RST7) ? (previous_marker + 1) : GPUJPEG_MARKER_RST0;
if ( expected_marker != byte ) {
fprintf(stderr, "[GPUJPEG] [Error] Expected marker 0x%X but 0x%X was presented!\n", expected_marker, byte);
// Skip bytes to expected marker
int found_expected_marker = 0;
int skip_count = 0;
byte_previous = byte;
while ( *image < image_end ) {
skip_count++;
byte = gpujpeg_reader_read_byte(*image);
if ( byte_previous == 0xFF ) {
// Expected marker was found so notify about it
if ( byte == expected_marker ) {
fprintf(stderr, "[GPUJPEG] [Recovery] Skipping %d bytes of data until marker 0x%X was found!\n", skip_count, expected_marker, byte);
found_expected_marker = 1;
break;
} else if ( byte == GPUJPEG_MARKER_EOI || byte == GPUJPEG_MARKER_SOS ) {
// Go back last marker (will be read again by main read cycle)
*image -= 2;
break;
}
}
byte_previous = byte;
}
// If expected marker was not found to end of stream
if ( found_expected_marker == 0 ) {
fprintf(stderr, "[GPUJPEG] [Error] No marker 0x%X was found until end of current scan!\n", expected_marker);
continue;
}
}
// Set previous marker
previous_marker = byte;
decoder->reader->data_compressed_size -= 2;
// Set segment byte count
segment->data_compressed_size = decoder->reader->data_compressed_size - segment->data_compressed_index;
// Start new segment in scan
segment = &decoder->coder.segment[scan->segment_index + scan->segment_count];
segment->scan_index = scan_index;
segment->scan_segment_index = scan->segment_count;
segment->data_compressed_index = decoder->reader->data_compressed_size;
scan->segment_count++;
}
// Check scan end
else if ( byte == GPUJPEG_MARKER_EOI || byte == GPUJPEG_MARKER_SOS ) {
*image -= 2;
decoder->reader->data_compressed_size -= 2;
// Set segment byte count
segment->data_compressed_size = decoder->reader->data_compressed_size - segment->data_compressed_index;
// Add scan segment count to decoder segment count
decoder->reader->segment_count += scan->segment_count;
return 0;
} else {
fprintf(stderr, "[GPUJPEG] [Error] JPEG scan contains unexpected marker 0x%X!\n", byte);
return -1;
}
}
} while( *image < image_end );
fprintf(stderr, "[GPUJPEG] [Error] JPEG data unexpected ended while reading SOS marker!\n");
return -1;
}
/** Documented at declaration */
int
gpujpeg_reader_read_image(struct gpujpeg_decoder* decoder, uint8_t* image, int image_size)
{
// Setup reader and decoder
decoder->reader->param = decoder->coder.param;
decoder->reader->param_image = decoder->coder.param_image;
decoder->reader->comp_count = 0;
decoder->reader->scan_count = 0;
decoder->reader->segment_count = 0;
decoder->reader->data_compressed_size = 0;
// Get image end
uint8_t* image_end = image + image_size;
// Check first SOI marker
int marker_soi = gpujpeg_reader_read_marker(&image);
if ( marker_soi != GPUJPEG_MARKER_SOI ) {
fprintf(stderr, "[GPUJPEG] [Error] JPEG data should begin with SOI marker, but marker %s was found!\n", gpujpeg_marker_name((enum gpujpeg_marker_code)marker_soi));
return -1;
}
int eoi_presented = 0;
while ( eoi_presented == 0 ) {
// Read marker
int marker = gpujpeg_reader_read_marker(&image);
// Read more info according to the marker
switch (marker)
{
case GPUJPEG_MARKER_APP0:
if ( gpujpeg_reader_read_app0(&image) != 0 )
return -1;
break;
case GPUJPEG_MARKER_APP1:
case GPUJPEG_MARKER_APP2:
case GPUJPEG_MARKER_APP3:
case GPUJPEG_MARKER_APP4:
case GPUJPEG_MARKER_APP5:
case GPUJPEG_MARKER_APP6:
case GPUJPEG_MARKER_APP7:
case GPUJPEG_MARKER_APP8:
case GPUJPEG_MARKER_APP9:
case GPUJPEG_MARKER_APP10:
case GPUJPEG_MARKER_APP11:
case GPUJPEG_MARKER_APP12:
case GPUJPEG_MARKER_APP13:
case GPUJPEG_MARKER_APP14:
case GPUJPEG_MARKER_APP15:
fprintf(stderr, "[GPUJPEG] [Warning] JPEG data contains not supported %s marker\n", gpujpeg_marker_name((enum gpujpeg_marker_code)marker));
gpujpeg_reader_skip_marker_content(&image);
break;
case GPUJPEG_MARKER_DQT:
if ( gpujpeg_reader_read_dqt(decoder, &image) != 0 )
return -1;
break;
case GPUJPEG_MARKER_SOF0:
// Baseline
if ( gpujpeg_reader_read_sof0(decoder, &image) != 0 )
return -1;
break;
case GPUJPEG_MARKER_SOF1:
// Extended sequential with Huffman coder
fprintf(stderr, "[GPUJPEG] [Warning] Reading SOF1 as it was SOF0 marker (should work but verify it)!\n", gpujpeg_marker_name((enum gpujpeg_marker_code)marker));
if ( gpujpeg_reader_read_sof0(decoder, &image) != 0 )
return -1;
break;
case GPUJPEG_MARKER_SOF2:
fprintf(stderr, "[GPUJPEG] [Error] Marker SOF2 (Progressive with Huffman coding) is not supported!");
return -1;
case GPUJPEG_MARKER_SOF3:
fprintf(stderr, "[GPUJPEG] [Error] Marker SOF3 (Lossless with Huffman coding) is not supported!");
return -1;
case GPUJPEG_MARKER_SOF5:
fprintf(stderr, "[GPUJPEG] [Error] Marker SOF5 (Differential sequential with Huffman coding) is not supported!");
return -1;
case GPUJPEG_MARKER_SOF6:
fprintf(stderr, "[GPUJPEG] [Error] Marker SOF6 (Differential progressive with Huffman coding) is not supported!");
return -1;
case GPUJPEG_MARKER_SOF7:
fprintf(stderr, "[GPUJPEG] [Error] Marker SOF7 (Extended lossless with Arithmetic coding) is not supported!");
return -1;
case GPUJPEG_MARKER_JPG:
fprintf(stderr, "[GPUJPEG] [Error] Marker JPG (Reserved for JPEG extensions ) is not supported!");
return -1;
case GPUJPEG_MARKER_SOF10:
fprintf(stderr, "[GPUJPEG] [Error] Marker SOF10 (Progressive with Arithmetic coding) is not supported!");
return -1;
case GPUJPEG_MARKER_SOF11:
fprintf(stderr, "[GPUJPEG] [Error] Marker SOF11 (Lossless with Arithmetic coding) is not supported!");
return -1;
case GPUJPEG_MARKER_SOF13:
fprintf(stderr, "[GPUJPEG] [Error] Marker SOF13 (Differential sequential with Arithmetic coding) is not supported!");
return -1;
case GPUJPEG_MARKER_SOF14:
fprintf(stderr, "[GPUJPEG] [Error] Marker SOF14 (Differential progressive with Arithmetic coding) is not supported!");
return -1;
case GPUJPEG_MARKER_SOF15:
fprintf(stderr, "[GPUJPEG] [Error] Marker SOF15 (Differential lossless with Arithmetic coding) is not supported!");
return -1;
case GPUJPEG_MARKER_DHT:
if ( gpujpeg_reader_read_dht(decoder, &image) != 0 )
return -1;
break;
case GPUJPEG_MARKER_DRI:
if ( gpujpeg_reader_read_dri(decoder, &image) != 0 )
return -1;
break;
case GPUJPEG_MARKER_SOS:
if ( gpujpeg_reader_read_sos(decoder, &image, image_end) != 0 )
return -1;
break;
case GPUJPEG_MARKER_EOI:
eoi_presented = 1;
break;
case GPUJPEG_MARKER_COM:
case GPUJPEG_MARKER_DAC:
case GPUJPEG_MARKER_DNL:
fprintf(stderr, "[GPUJPEG] [Warning] JPEG data contains not supported %s marker\n", gpujpeg_marker_name((enum gpujpeg_marker_code)marker));
gpujpeg_reader_skip_marker_content(&image);
break;
default:
fprintf(stderr, "[GPUJPEG] [Error] JPEG data contains not supported %s marker!\n", gpujpeg_marker_name((enum gpujpeg_marker_code)marker));
gpujpeg_reader_skip_marker_content(&image);
return -1;
}
}
// Check EOI marker
if ( eoi_presented == 0 ) {
fprintf(stderr, "[GPUJPEG] [Error] JPEG data should end with EOI marker!\n");
return -1;
}
// Set decoder parameters
decoder->segment_count = decoder->reader->segment_count;
decoder->data_compressed_size = decoder->reader->data_compressed_size;
//decoder->segment_count += 100;
if ( decoder->segment_count > decoder->coder.segment_count ) {
fprintf(stderr, "[GPUJPEG] [Error] Decoder can't decode image that has segment count %d (maximum segment count for specified parameters is %d)!\n",
decoder->segment_count, decoder->coder.segment_count);
return -1;
}
return 0;
}