📄 hpbit_stream_in.c
字号:
{ assert(elt->size == 1); tp->eph = (int) elt->buf[0]; } } } return(1);}/*****************************************************************************//* STATIC consume_anticipated_resync_marker *//*****************************************************************************/static int consume_anticipated_resync_marker(hpbit_stream_in_ref self, int *end_of_tilepart) /* This function expects to find a resync marker (SOP) with the correct packet sequence index or else run into the end of the current tile-part (possibly by reaching the end of the file). If successful, the `self->missing_packets' field remains zero and the function returns 1. Otherwise, the function keeps reading until the next valid resync marker or the end of the tile-part, and sets the `self->missing_packets' field to hold the number of missing packets, as estimated from the next valid resync marker. In this case the function returns 0. The number of missing packets may still appear to be 0, because the sequence indices align. This generally means that the previous packet was not completely read, but this might not be the case. Before returning, the function sets *`end_of_tilepart' to 1 or 0, depending upon whether or not the end of the current tile-part was reached before encountering a resync marker. It is the caller's responsibility to advance to the next tile-part, set its sequence index as appropriate and then reinvoke this function to synchronize at the start of the first packet of the new tile-part. */{ hpbit_tilepart_ptr tp; int corrupt, byte_val; std_ushort seq; *end_of_tilepart = 0; tp = self->current_tilepart; assert(!self->missing_packets); corrupt = 0; byte_val = 0; do { while (byte_val != 0x00FF) { byte_val = fetch_data_byte(self,tp); if (byte_val == EOF) break; if (byte_val != 0x00FF) corrupt = 1; } if ((byte_val == EOF) || ((byte_val=fetch_data_byte(self,tp)) == EOF)) { /* Reached the end of the tile-part. */ *end_of_tilepart = 1; return(!corrupt); } if ((byte_val == (MARKER_SOT & 0x00FF)) || (byte_val == (MARKER_EOI & 0x00FF))) { /* Same as processing EOF except that we have encountered the end of the tile-part prematurely, so we will have to correct some length fields which were set at the start of the tile in anticipation of an incorrect tile length. */ *end_of_tilepart = 1; assert(tp->data == NULL); /* Must be reading from a file. */ assert(!self->have_sot); if (byte_val == (MARKER_SOT & 0x00FF)) self->have_sot = 1; tp->data_bytes -= tp->data_bytes_left+2; self->non_data_bytes_left += tp->data_bytes_left; tp->data_bytes_left = 0; return(!corrupt); } else if (byte_val != (MARKER_SOP & 0x00FF)) corrupt = 1; } while (byte_val != (MARKER_SOP & 0x00FF)); /* Read the packet sequence index and compare. */ byte_val = fetch_data_byte(self,tp); seq = byte_val; if ((byte_val == EOF) || ((byte_val = fetch_data_byte(self,tp)) == EOF)) { /* Reached the end of the tile-part. */ *end_of_tilepart = 1; return(!corrupt); } seq <<= 8; seq |= (byte_val & 0x00FF); if (corrupt || (seq != tp->packet_sequence_idx)) { /* Later we will need to fix this to anticipate the possibility of corrupted sequence indices. */ self->missing_packets = ((int) seq) - ((int)(tp->packet_sequence_idx)); if (self->missing_packets < 0) self->missing_packets += (1<<16); return(0); } return(1);}/*****************************************************************************//* STATIC consume_anticipated_eph_marker *//*****************************************************************************/static int consume_anticipated_eph_marker(hpbit_stream_in_ref self, hpbit_tilepart_ptr tp) /* Expects the next two bytes in the current packet to hold an EPH marker. Reads until the EPH marker is recovered regardless. Returns 1 if the EPH marker is found. Returns 0 if the end of the file or tile-part is encountered or reading stopped due to encountering an unexpected SOP marker; in the latter case, the number of missing packets is also set, exactly as if the premature SOP marker had been encountered within a call to `pull_packet_bytes'. In the special case of packed packet headers, the function invariably returns 1, since we do not want to prevent any reading of the packet body in the event that a packet header was corrupted. */{ int byte_val; hpbit_packed_head_ptr ph; assert(tp->eph && !self->eph_found); byte_val = 0; if ((ph = tp->packed_heads) != NULL) { int have_ff; self->eph_found = 1; do { have_ff = (byte_val == 0x00FF); while ((ph->bytes_left == 0) && (ph->next != NULL)) { tp->packed_heads = ph->next; if (ph->data_handle != NULL) local_free(ph->data_handle); local_free(ph); ph = tp->packed_heads; } if (ph->bytes_left == 0) return(1); byte_val = *(ph->data++); ph->bytes_left--; } while ((!have_ff) || (byte_val != (MARKER_EPH & 0x00FF))); return(1); } do { if (byte_val != 0x00FF) { if ((byte_val = fetch_data_byte(self,tp)) == EOF) return(0); self->packet_bytes++; } if (byte_val != 0x00FF) continue; if ((byte_val = fetch_data_byte(self,tp)) == EOF) return(0); self->packet_bytes++; if ((byte_val == (MARKER_EOI & 0x00FF)) || (byte_val == (MARKER_SOT & 0x00FF))) { /* We appear to have run into the end of the tile-part prematurely. Treat like encountering the end of the tile-part normally, except that counters need to be corrected. */ assert(tp->data == NULL); /* Must be reading from a file. */ assert(!self->have_sot); if (byte_val == (MARKER_SOT & 0x00FF)) self->have_sot = 1; tp->data_bytes -= tp->data_bytes_left+2; self->non_data_bytes_left += tp->data_bytes_left; tp->data_bytes_left = 0; return(0); } else if (tp->resync && (byte_val == (MARKER_SOP & 0x00FF))) { /* We appear to have run into the next packet. */ std_ushort seq; byte_val = fetch_data_byte(self,tp); if (byte_val == EOF) return(0); seq = byte_val; byte_val = fetch_data_byte(self,tp); if (byte_val == EOF) return(0); seq <<= 8; seq |= byte_val; self->missing_packets = ((int) seq) - ((int)(tp->packet_sequence_idx)); if (self->missing_packets < 0) self->missing_packets += 1<<16; self->missing_packets++; /* Rest of current packet missing */ return(0); } } while (byte_val != (MARKER_EPH & 0x00FF)); self->eph_found = 1; return(1);}/*****************************************************************************//* STATIC advance_current_tilepart *//*****************************************************************************/static void advance_current_tilepart(hpbit_stream_in_ref self) /* Advances from the tile-part identified by `self->current_tilepart' to the next non-empty tile-part in sequence, reading tile-part headers as necessary. Note that the relevant tile-part's header and even its body may already have been read. If there are no more tile-parts, the `current_tilepart' pointer is set to NULL. Storage managed by the previous tile-part may be released at this point. */{ hpbit_tilepart_ptr tp; int code, empty_tilepart; empty_tilepart = 0; do { tp = self->current_tilepart; if (tp == NULL) tp = self->tileparts; else { hpbit_packed_head_ptr packed; destroy_markers(&(tp->markers),tp); if (tp->data_handle != NULL) local_free(tp->data_handle); tp->data_handle = tp->data = NULL; while ((packed = tp->packed_heads) != NULL) { tp->packed_heads = packed->next; if (packed->data_handle != NULL) local_free(packed->data_handle); local_free(packed); } tp = tp->next; } if (tp == NULL) { /* Read a new tile-part header. */ do { code = read_new_tilepart_header(self); } while (code < 0); if (code == 0) { /* Reached the end of the codestream. */ self->current_tilepart = NULL; return; } } tp = self->current_tilepart; if (tp == NULL) tp = self->tileparts; else tp = tp->next; assert(tp != NULL); self->current_tilepart = tp; self->missing_packets = 0; if (tp->last_part != NULL) tp->packet_sequence_idx = tp->last_part->packet_sequence_idx; if (tp->resync) consume_anticipated_resync_marker(self,&empty_tilepart); } while (empty_tilepart); self->virgin_tilepart = 1;}/*****************************************************************************//* STATIC pull_packet_bytes *//*****************************************************************************/static int pull_packet_bytes(hpbit_stream_in_ref self, std_byte *buf, int num_bytes, int in_head) /* Under normal circumstances, this function does most of the work of `__pull_head_bytes' and `__pull_body_bytes'. */{ hpbit_tilepart_ptr tp; int result, byte_val; assert(self->open_packet); tp = self->current_tilepart; if (self->missing_packets) return(0); for (result=0; num_bytes > 0; num_bytes--, result++) { if ((byte_val = fetch_data_byte(self,tp)) == EOF) return(result); if (byte_val == 0x00FF) { byte_val = fetch_data_byte(self,tp); if (byte_val == EOF) { /* We have run into the end of the tile-part. */ return(result); } else if ((byte_val == (MARKER_EOI & 0x00FF)) || (byte_val == (MARKER_SOT & 0x00FF))) { /* We appear to have run into the end of the tile-part prematurely. Treat like encountering the end of the tile-part normally, except that counters need to be corrected. */ assert(tp->data == NULL); /* Must be reading from a file. */ assert(!self->have_sot); if (byte_val == (MARKER_SOT & 0x00FF)) self->have_sot = 1; tp->data_bytes -= tp->data_bytes_left+2; self->non_data_bytes_left += tp->data_bytes_left; tp->data_bytes_left = 0; return(result); } else if (tp->resync && (byte_val == (MARKER_SOP & 0x00FF))) { /* We appear to have run into the next packet. */ std_ushort seq; byte_val = fetch_data_byte(self,tp); if (byte_val == EOF) return(result); seq = byte_val; byte_val = fetch_data_byte(self,tp); if (byte_val == EOF) return(result); seq <<= 8; seq |= byte_val; self->missing_packets = ((int) seq) - ((int)(tp->packet_sequence_idx)); if (self->missing_packets < 0) self->missing_packets += 1<<16; self->missing_packets++; /* Rest of current packet missing */ return(result); } else if ((byte_val == (MARKER_EPH & 0x00FF)) && tp->eph && !self->eph_found) { /* Skip over the EPH marker. */ self->eph_found = 1; num_bytes++; result--; self->packet_bytes += 2; continue; } else { /* Treat marker as part of packet stream. */ return_data_byte(self,tp,byte_val); byte_val = 0x00FF; } } *(buf++) = (std_byte) byte_val; self->packet_bytes++; } return(result);} /* ========================================================================= *//* ------------------------- Interface Implementation ---------------------- *//* ========================================================================= *//*****************************************************************************//* STATIC __initialize *//*****************************************************************************/static void __initialize(stream_in_ref base, char *filename, cmdl_ref cmdl){ hpbit_stream_in_ref self = (hpbit_stream_in_ref) base; std_ushort soc; std_ushort delimiter; int byte_val; self->fp = fopen(filename,"rb"); if (self->fp == NULL) local_error("Unable to open input file, \"%s\"!",filename); byte_val = fetch_non_data_byte(self); soc = (std_ushort ) byte_val; byte_val = fetch_non_data_byte(self); soc = (soc <<8) | (std_ushort) byte_val; if ((byte_val == EOF) || (soc != MARKER_SOC)) local_error("Input codestream does not commence with the SOC marker!"); self->global_markers.total_codestream_bytes = 2; delimiter = read_markers(self,NULL); if (delimiter != MARKER_SOT) local_error("I
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -