📄 hpbit_stream_out.c
字号:
/*****************************************************************************/
/* Copyright 1998, Hewlett-Packard Company */
/* All rights reserved */
/* File: "hpbit_stream_out.c" */
/* Description: Reference implementation of the `stream_out' object. */
/* Author: David Taubman */
/* Affiliation: Hewlett-Packard and */
/* The University of New South Wales, Australia */
/* Acknowledgements: Partly developed in collaboration with Salma Soudagar */
/* of Motorola, Switzerland, and her colleagues */
/* Version: VM9.0 */
/* Last Revised: 19 April, 2001 */
/*****************************************************************************/
/*****************************************************************************/
/* Modified by David Taubman to avoid the need for byte stuffing when resync */
/* markers are in use. This simplifies the code and substantially improves */
/* the usefulness of the system for applications requiring error resilience. */
/* Copyright 1999 by Hewlett-Packard Company with all */
/* rights reserved for the modified parts. */
/*****************************************************************************/
/*****************************************************************************/
/* Modified by David Taubman to support interface modifications, arbitrary */
/* changes in coding parameters from component to component and from tile */
/* to tile, to support the full generality of PART-1 of the JPEG2000 */
/* standard, and to support most anticipated generality of PART-2. Changes */
/* are too numerous to flag individually within the code, which in some */
/* places has been completely rewritten. All changes copyrighted by HP with */
/* all rights reserved for the modified parts. */
/*****************************************************************************/
/*****************************************************************************/
/* Modified by Gene Wu to add real markers for COD/COC and QCD/QCC. */
/* All changes copyright 2000 by Ricoh Silicon Valley with all rights */
/* reserved for the modified parts. */
/*****************************************************************************/
/*****************************************************************************/
/* Modified by David Taubman to implement changes in Tokyo between CD and */
/* FCD for Part-1 of the standard. Copyrighted by HP with all rights */
/* reserved for the modified parts. */
/*****************************************************************************/
/*****************************************************************************/
/* Modified by David Taubman to incorporate changes to the POC marker (used */
/* to be POD). Changes are quite extensive and not always explicitly */
/* When flagged, the relevant comment string is "DST POC mod". */
/* Generally, any reference to tile-parts (e.g. through variable names */
/* containing the string `tpart' are part of this modification, since the */
/* compressor did not previously need to be tile-part aware. */
/* Copyright 2000 The University of New South Wales. */
/* All rights reserved for the modified parts. */
/*****************************************************************************/
/*****************************************************************************/
/* Modified by Gene Wu to add CRG marker. */
/* All changes copyright 2000 by Ricoh Silicon Valley with all rights */
/* reserved for the modified parts. */
/*****************************************************************************/
#include <local_services.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <ifc.h>
#include <markers.h>
#include "hpbit_stream_out_local.h"
#include "hpbit_markers.h"
/* ========================================================================= */
/* ---------------------------- Internal Functions ------------------------- */
/* ========================================================================= */
/*****************************************************************************/
/* STATIC make_big_endian */
/*****************************************************************************/
static void
make_big_endian(void *buf, int num_words, int precision)
/* Use this convenience function to reverse the byte order in words
from which a buffer is constructed, when the current architecture uses
a Little Endian byte order. The `buf' argument is assumed to
point to a structure consisting of integer-valued fields with 1, 2 or 4
bytes of precision each. */
{
int bigendian, n;
std_byte *bp, b0, b1, b2, b3;
bigendian = 1;
bp = (std_byte *)(&bigendian);
*bp = 0;
if (bigendian || (precision == 1))
return;
assert(num_words != 0);
if (precision == 2)
{
for (bp=(std_byte *) buf, n=num_words; n > 0; n--, bp += 2)
{
b0 = bp[0]; b1 = bp[1];
bp[0] = b1; bp[1] = b0;
}
}
else if (precision == 4)
{
for (bp=(std_byte *) buf, n=num_words; n > 0; n--, bp += 4)
{
b0 = bp[0]; b1 = bp[1]; b2 = bp[2]; b3 = bp[3];
bp[0] = b3; bp[1] = b2; bp[2] = b1; bp[3] = b0;
}
}
else
assert(0);
}
/*****************************************************************************/
/* STATIC copy_to_big_endian */
/*****************************************************************************/
static void
copy_to_big_endian(void *src, void *dst, int num_words, int precision)
/* Copies the `src' data to the `dst' data and performs any byte reversal
required to ensure that quantities represented in `dst' have the
Big Endian byte order. */
{
int bigendian, n;
std_byte *sp, *dp;
bigendian = 1;
sp = (std_byte *)(&bigendian);
*sp = 0;
if (bigendian || (precision == 1))
{
memcpy(dst,src,num_words*precision);
return;
}
assert(num_words != 0);
if (precision == 2)
{
for (sp=(std_byte *) src, dp=(std_byte *) dst,
n=num_words; n > 0; n--, sp+=2, dp+=2)
{
dp[0] = sp[1];
dp[1] = sp[0];
}
}
else if (precision == 4)
{
for (sp=(std_byte *) src, dp=(std_byte *) dst,
n=num_words; n > 0; n--, sp+=4, dp+=4)
{
dp[0] = sp[3];
dp[1] = sp[2];
dp[2] = sp[1];
dp[3] = sp[0];
}
}
else
assert(0);
}
/*****************************************************************************/
/* STATIC emit_bytes */
/*****************************************************************************/
static void
emit_bytes(hpbit_stream_out_ref self, std_byte *buf, int num_bytes)
/* Emits the indicated bytes directly to the file, up to the limit imposed
by `self->remaining_bytes'. Byte stuffing, error correction codes, etc.,
should all be handled at a higher level by functions which ultimately
call this function to output the final code stream. */
{
self->remaining_bytes -= num_bytes;
if (self->remaining_bytes < 0)
{
num_bytes += self->remaining_bytes;
if (num_bytes <= 0) {
/* TJF: Reset remaining_bytes to value at entry to this routine */
/* TJF: this statement and the one below breaks iterations; not sure
if it is needed; take out for now
self->remaining_bytes = num_bytes; */
return;
}
/* TJF: this statement and the one above breaks iterations; not sure if
it is needed; take out for now
self->remaining_bytes = 0; */
}
fwrite(buf,1,(size_t) num_bytes,self->fp);
}
/*****************************************************************************/
/* STATIC emit_words */
/*****************************************************************************/
static void
emit_words(hpbit_stream_out_ref self, void *buf,
int num_words, int precision)
/* Same as `emit_bytes' except that the function emits multi-byte values.
`precision' indicates the number of bytes in each word; it must be
one of 1, 2 or 4. The function differs from `emit_bytes' in that it
may reorganize the bytes in each word to achieve a consistent BIGENDIAN
byte order (MSB first). */
{
make_big_endian(buf,num_words,precision);
emit_bytes(self,(std_byte *) buf,precision*num_words);
}
/*****************************************************************************/
/* STATIC add_tile */
/*****************************************************************************/
static hpbit_tile_ptr
add_tile(hpbit_stream_out_ref self, int tnum)
{
hpbit_tile_ptr tile;
tile = (hpbit_tile_ptr)
local_malloc(HPBIT_MEM_KEY,sizeof(hpbit_tile));
tile->tnum = tnum;
tile->next = self->tiles;
self->tiles = tile;
tile->resync = self->global_resync;
tile->eph = self->global_eph;
return(tile);
}
/*****************************************************************************/
/* STATIC insert_pre_marker_element */
/*****************************************************************************/
static void
insert_pre_marker_element(hpbit_marker_elt_ptr elt, hpbit_pre_marker_ptr pm)
/* Inserts the new element into the list of elements managed by the `pm'
structure, being careful to apply a unique ordering condition to the
marker elements to facilitate later comparison of markers. */
{
hpbit_marker_elt_ptr scan, last;
for (last=NULL, scan=pm->elements; scan != NULL; last=scan, scan=scan->next)
if (scan->element_id > elt->element_id)
break;
elt->next = scan;
if (last == NULL)
pm->elements = elt;
else
last->next = elt;
}
/*****************************************************************************/
/* STATIC destroy_pre_marker */
/*****************************************************************************/
static void
destroy_pre_marker(hpbit_pre_marker_ptr pm)
{
hpbit_marker_elt_ptr elt;
while ((elt = pm->elements) != NULL)
{
pm->elements = elt->next;
if (elt->buf != NULL)
local_free(elt->buf);
if (elt->set_buf != NULL)
local_free(elt->set_buf);
local_free(elt);
}
local_free(pm);
}
/*****************************************************************************/
/* STATIC link_connected_pre_markers */
/*****************************************************************************/
static void
link_connected_pre_markers(hpbit_markers_ptr markers)
/* This function implements any prior knowledge concerning the
inter-dependence of pre-markers. The main objective is to ensure that
a marker will be eliminated (as redundant) from a tile-header only if
all dependent markers in the tile-header can simultaneously be
eliminated. */
{
hpbit_pre_marker_ptr pm, prev;
/* Process connectedness of COD/COC markers. */
for (prev=NULL, pm=markers->pre_markers; pm != NULL; pm = pm->next)
if ((pm->id == (MARKER_COD & 0x00FF)) ||
(pm->id == (MARKER_COC & 0x00FF)))
{
pm->link_prev = prev;
if (prev != NULL)
prev->link_next = pm;
prev = pm;
}
/* Process connectedness of QCD/QCC markers. */
for (prev=NULL, pm=markers->pre_markers; pm != NULL; pm = pm->next)
if ((pm->id == (MARKER_QCD & 0x00FF)) ||
(pm->id == (MARKER_QCC & 0x00FF)))
{
pm->link_prev = prev;
if (prev != NULL)
prev->link_next = pm;
prev = pm;
}
}
/*****************************************************************************/
/* STATIC add_codestream_marker */
/*****************************************************************************/
static void
add_codestream_marker(hpbit_markers_ptr markers, void *buf, int length,
int instance, int place_at_end)
/* Use this convenience function to push newly created codestream markers
onto the list (LIFO) referenced from a `markers' structure (there is one
`markers' structure for the global header and one for each tile header.
The contents of the `buf' array are already supposed to contain values
with the correct byte alignment (i.e. big endian). The `place_at_end'
argument indicates whether the new marker should be placed at the
end or the front of the current list of codestream markers. This
should be irrelevant for all markers except the CME marker, which is
the only one for which order of appearance in the codestream has
some significance (if there are multiple occurrences of the same
marker with the same Rcme value). */
{
hpbit_codestream_marker_ptr elt, last;
std_byte id;
id = ((std_byte *) buf)[1]; /* DST POC mod */
elt = (hpbit_codestream_marker_ptr)
local_malloc(HPBIT_MEM_KEY,sizeof(hpbit_codestream_marker));
elt->instance = instance;
elt->tpart = 0;
/* Begin DST POC mod */
if ((id == (MARKER_POC & 0x00FF)) && (instance > 0))
{
elt->tpart = instance - 1;
elt->instance = 0;
}
/* End DST POC mod */
elt->num_bytes = length;
elt->buf = buf;
last = markers->codestream_markers;
if (place_at_end && (last != NULL))
{
while (last->next != NULL)
last = last->next;
last->next = elt;
}
else
{
elt->next = markers->codestream_markers;
markers->codestream_markers = elt;
}
markers->total_codestream_bytes += elt->num_bytes;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -