1 /***************************************************************************
4 * Generic routines to pack Mini-SEED records using an MSrecord as a
5 * header template and data source.
7 * Written by Chad Trabant,
8 * IRIS Data Management Center
11 ***************************************************************************/
21 /* Function(s) internal to this file */
22 static int msr_pack_header_raw (MSRecord
*msr
, char *rawrec
, int maxheaderlen
,
23 flag swapflag
, flag normalize
,
24 struct blkt_1001_s
**blkt1001
, flag verbose
);
25 static int msr_update_header (MSRecord
* msr
, char *rawrec
, flag swapflag
,
26 struct blkt_1001_s
*blkt1001
, flag verbose
);
27 static int msr_pack_data (void *dest
, void *src
, int maxsamples
, int maxdatabytes
,
28 int *packsamples
, int32_t *lastintsample
, flag comphistory
,
29 char sampletype
, flag encoding
, flag swapflag
,
32 /* Header and data byte order flags controlled by environment variables */
33 /* -2 = not checked, -1 = checked but not set, or 0 = LE and 1 = BE */
34 flag packheaderbyteorder
= -2;
35 flag packdatabyteorder
= -2;
37 /* A pointer to the srcname of the record being packed */
38 char *PACK_SRCNAME
= NULL
;
41 /***************************************************************************
44 * Pack data into SEED data records. Using the record header values
45 * in the MSRecord as a template the common header fields are packed
46 * into the record header, blockettes in the blockettes chain are
47 * packed and data samples are packed in the encoding format indicated
48 * by the MSRecord->encoding field. A Blockette 1000 will be added if
51 * The MSRecord->datasamples array and MSRecord->numsamples value will
52 * not be changed by this routine. It is the responsibility of the
53 * calling routine to adjust the data buffer if desired.
55 * As each record is filled and finished they are passed to
56 * record_handler which expects 1) a char * to the record, 2) the
57 * length of the record and 3) a pointer supplied by the original
58 * caller containing optional private data (handlerdata). It is the
59 * responsibility of record_handler to process the record, the memory
60 * will be re-used or freed when record_handler returns.
62 * If the flush flag != 0 all of the data will be packed into data
63 * records even though the last one will probably not be filled.
65 * Default values are: data record & quality indicator = 'D', record
66 * length = 4096, encoding = 11 (Steim2) and byteorder = 1 (MSBF).
67 * The defaults are triggered when the the msr->dataquality is 0 or
68 * msr->reclen, msr->encoding and msr->byteorder are -1 respectively.
70 * Returns the number of records created on success and -1 on error.
71 ***************************************************************************/
73 msr_pack ( MSRecord
* msr
, void (*record_handler
) (char *, int, void *),
74 void *handlerdata
, int64_t *packedsamples
, flag flush
, flag verbose
)
76 uint16_t *HPnumsamples
;
77 uint16_t *HPdataoffset
;
78 struct blkt_1001_s
*HPblkt1001
= NULL
;
84 flag headerswapflag
= 0;
85 flag dataswapflag
= 0;
94 int packsamples
, packoffset
;
95 int64_t totalpackedsamples
;
96 hptime_t segstarttime
;
101 if ( ! record_handler
)
103 ms_log (2, "msr_pack(): record_handler() function pointer not set!\n");
107 /* Allocate stream processing state space if needed */
108 if ( ! msr
->ststate
)
110 msr
->ststate
= (StreamState
*) malloc (sizeof(StreamState
));
111 if ( ! msr
->ststate
)
113 ms_log (2, "msr_pack(): Could not allocate memory for StreamState\n");
116 memset (msr
->ststate
, 0, sizeof(StreamState
));
119 /* Generate source name for MSRecord */
120 if ( msr_srcname (msr
, srcname
, 1) == NULL
)
122 ms_log (2, "msr_unpack_data(): Cannot generate srcname\n");
126 /* Set shared srcname pointer to source name */
127 PACK_SRCNAME
= &srcname
[0];
129 /* Track original segment start time for new start time calculation */
130 segstarttime
= msr
->starttime
;
132 /* Read possible environmental variables that force byteorder */
133 if ( packheaderbyteorder
== -2 )
135 if ( (envvariable
= getenv("PACK_HEADER_BYTEORDER")) )
137 if ( *envvariable
!= '0' && *envvariable
!= '1' )
139 ms_log (2, "Environment variable PACK_HEADER_BYTEORDER must be set to '0' or '1'\n");
142 else if ( *envvariable
== '0' )
144 packheaderbyteorder
= 0;
146 ms_log (1, "PACK_HEADER_BYTEORDER=0, packing little-endian header\n");
150 packheaderbyteorder
= 1;
152 ms_log (1, "PACK_HEADER_BYTEORDER=1, packing big-endian header\n");
157 packheaderbyteorder
= -1;
160 if ( packdatabyteorder
== -2 )
162 if ( (envvariable
= getenv("PACK_DATA_BYTEORDER")) )
164 if ( *envvariable
!= '0' && *envvariable
!= '1' )
166 ms_log (2, "Environment variable PACK_DATA_BYTEORDER must be set to '0' or '1'\n");
169 else if ( *envvariable
== '0' )
171 packdatabyteorder
= 0;
173 ms_log (1, "PACK_DATA_BYTEORDER=0, packing little-endian data samples\n");
177 packdatabyteorder
= 1;
179 ms_log (1, "PACK_DATA_BYTEORDER=1, packing big-endian data samples\n");
184 packdatabyteorder
= -1;
188 /* Set default indicator, record length, byte order and encoding if needed */
189 if ( msr
->dataquality
== 0 ) msr
->dataquality
= 'D';
190 if ( msr
->reclen
== -1 ) msr
->reclen
= 4096;
191 if ( msr
->byteorder
== -1 ) msr
->byteorder
= 1;
192 if ( msr
->encoding
== -1 ) msr
->encoding
= DE_STEIM2
;
194 /* Cleanup/reset sequence number */
195 if ( msr
->sequence_number
<= 0 || msr
->sequence_number
> 999999)
196 msr
->sequence_number
= 1;
198 if ( msr
->reclen
< MINRECLEN
|| msr
->reclen
> MAXRECLEN
)
200 ms_log (2, "msr_pack(%s): Record length is out of range: %d\n",
201 PACK_SRCNAME
, msr
->reclen
);
205 if ( msr
->numsamples
<= 0 )
207 ms_log (2, "msr_pack(%s): No samples to pack\n", PACK_SRCNAME
);
211 samplesize
= ms_samplesize (msr
->sampletype
);
215 ms_log (2, "msr_pack(%s): Unknown sample type '%c'\n",
216 PACK_SRCNAME
, msr
->sampletype
);
220 /* Sanity check for msr/quality indicator */
221 if ( ! MS_ISDATAINDICATOR(msr
->dataquality
) )
223 ms_log (2, "msr_pack(%s): Record header & quality indicator unrecognized: '%c'\n",
224 PACK_SRCNAME
, msr
->dataquality
);
225 ms_log (2, "msr_pack(%s): Packing failed.\n", PACK_SRCNAME
);
229 /* Allocate space for data record */
230 rawrec
= (char *) malloc (msr
->reclen
);
232 if ( rawrec
== NULL
)
234 ms_log (2, "msr_pack(%s): Cannot allocate memory\n", PACK_SRCNAME
);
238 /* Set header pointers to known offsets into FSDH */
239 HPnumsamples
= (uint16_t *) (rawrec
+ 30);
240 HPdataoffset
= (uint16_t *) (rawrec
+ 44);
242 /* Check to see if byte swapping is needed */
243 if ( msr
->byteorder
!= ms_bigendianhost() )
244 headerswapflag
= dataswapflag
= 1;
246 /* Check if byte order is forced */
247 if ( packheaderbyteorder
>= 0 )
249 headerswapflag
= ( msr
->byteorder
!= packheaderbyteorder
) ? 1 : 0;
252 if ( packdatabyteorder
>= 0 )
254 dataswapflag
= ( msr
->byteorder
!= packdatabyteorder
) ? 1 : 0;
259 if ( headerswapflag
&& dataswapflag
)
260 ms_log (1, "%s: Byte swapping needed for packing of header and data samples\n", PACK_SRCNAME
);
261 else if ( headerswapflag
)
262 ms_log (1, "%s: Byte swapping needed for packing of header\n", PACK_SRCNAME
);
263 else if ( dataswapflag
)
264 ms_log (1, "%s: Byte swapping needed for packing of data samples\n", PACK_SRCNAME
);
266 ms_log (1, "%s: Byte swapping NOT needed for packing\n", PACK_SRCNAME
);
269 /* Add a blank 1000 Blockette if one is not present, the blockette values
270 will be populated in msr_pack_header_raw()/msr_normalize_header() */
271 if ( ! msr
->Blkt1000
)
273 struct blkt_1000_s blkt1000
;
274 memset (&blkt1000
, 0, sizeof (struct blkt_1000_s
));
277 ms_log (1, "%s: Adding 1000 Blockette\n", PACK_SRCNAME
);
279 if ( ! msr_addblockette (msr
, (char *) &blkt1000
, sizeof(struct blkt_1000_s
), 1000, 0) )
281 ms_log (2, "msr_pack(%s): Error adding 1000 Blockette\n", PACK_SRCNAME
);
287 headerlen
= msr_pack_header_raw (msr
, rawrec
, msr
->reclen
, headerswapflag
, 1, &HPblkt1001
, verbose
);
289 if ( headerlen
== -1 )
291 ms_log (2, "msr_pack(%s): Error packing header\n", PACK_SRCNAME
);
296 /* Determine offset to encoded data */
297 if ( msr
->encoding
== DE_STEIM1
|| msr
->encoding
== DE_STEIM2
)
300 while ( dataoffset
< headerlen
)
303 /* Zero memory between blockettes and data if any */
304 memset (rawrec
+ headerlen
, 0, dataoffset
- headerlen
);
308 dataoffset
= headerlen
;
311 *HPdataoffset
= (uint16_t) dataoffset
;
312 if ( headerswapflag
) ms_gswap2 (HPdataoffset
);
314 /* Determine the max data bytes and sample count */
315 maxdatabytes
= msr
->reclen
- dataoffset
;
317 if ( msr
->encoding
== DE_STEIM1
)
319 maxsamples
= (int) (maxdatabytes
/64) * STEIM1_FRAME_MAX_SAMPLES
;
321 else if ( msr
->encoding
== DE_STEIM2
)
323 maxsamples
= (int) (maxdatabytes
/64) * STEIM2_FRAME_MAX_SAMPLES
;
327 maxsamples
= maxdatabytes
/ samplesize
;
330 /* Pack samples into records */
332 totalpackedsamples
= 0;
333 if ( packedsamples
) *packedsamples
= 0;
336 while ( (msr
->numsamples
- totalpackedsamples
) > maxsamples
|| flush
)
338 packret
= msr_pack_data (rawrec
+ dataoffset
,
339 (char *) msr
->datasamples
+ packoffset
,
340 (int)(msr
->numsamples
- totalpackedsamples
), maxdatabytes
,
341 &packsamples
, &msr
->ststate
->lastintsample
, msr
->ststate
->comphistory
,
342 msr
->sampletype
, msr
->encoding
, dataswapflag
, verbose
);
346 ms_log (2, "msr_pack(%s): Error packing record\n", PACK_SRCNAME
);
351 packoffset
+= packsamples
* samplesize
;
353 /* Update number of samples */
354 *HPnumsamples
= (uint16_t) packsamples
;
355 if ( headerswapflag
) ms_gswap2 (HPnumsamples
);
358 ms_log (1, "%s: Packed %d samples\n", PACK_SRCNAME
, packsamples
);
360 /* Send record to handler */
361 record_handler (rawrec
, msr
->reclen
, handlerdata
);
363 totalpackedsamples
+= packsamples
;
364 if ( packedsamples
) *packedsamples
= totalpackedsamples
;
365 msr
->ststate
->packedsamples
+= packsamples
;
367 /* Update record header for next record */
368 msr
->sequence_number
= ( msr
->sequence_number
>= 999999 ) ? 1 : msr
->sequence_number
+ 1;
369 if ( msr
->samprate
> 0 )
370 msr
->starttime
= segstarttime
+ (hptime_t
)(totalpackedsamples
/ msr
->samprate
* HPTMODULUS
+ 0.5);
372 msr_update_header (msr
, rawrec
, headerswapflag
, HPblkt1001
, verbose
);
375 msr
->ststate
->packedrecords
++;
377 /* Set compression history flag for subsequent records (Steim encodings) */
378 if ( ! msr
->ststate
->comphistory
)
379 msr
->ststate
->comphistory
= 1;
381 if ( totalpackedsamples
>= msr
->numsamples
)
386 ms_log (1, "%s: Packed %d total samples\n", PACK_SRCNAME
, totalpackedsamples
);
391 } /* End of msr_pack() */
394 /***************************************************************************
397 * Pack data header/blockettes into the SEED record at
398 * MSRecord->record. Unlike msr_pack no default values are applied,
399 * the header structures are expected to be self describing and no
400 * Blockette 1000 will be added. This routine is only useful for
401 * re-packing a record header.
403 * Returns the header length in bytes on success and -1 on error.
404 ***************************************************************************/
406 msr_pack_header ( MSRecord
*msr
, flag normalize
, flag verbose
)
410 flag headerswapflag
= 0;
417 /* Generate source name for MSRecord */
418 if ( msr_srcname (msr
, srcname
, 1) == NULL
)
420 ms_log (2, "msr_unpack_data(): Cannot generate srcname\n");
424 /* Set shared srcname pointer to source name */
425 PACK_SRCNAME
= &srcname
[0];
427 /* Read possible environmental variables that force byteorder */
428 if ( packheaderbyteorder
== -2 )
430 if ( (envvariable
= getenv("PACK_HEADER_BYTEORDER")) )
432 if ( *envvariable
!= '0' && *envvariable
!= '1' )
434 ms_log (2, "Environment variable PACK_HEADER_BYTEORDER must be set to '0' or '1'\n");
437 else if ( *envvariable
== '0' )
439 packheaderbyteorder
= 0;
441 ms_log (1, "PACK_HEADER_BYTEORDER=0, packing little-endian header\n");
445 packheaderbyteorder
= 1;
447 ms_log (1, "PACK_HEADER_BYTEORDER=1, packing big-endian header\n");
452 packheaderbyteorder
= -1;
456 if ( msr
->reclen
< MINRECLEN
|| msr
->reclen
> MAXRECLEN
)
458 ms_log (2, "msr_pack_header(%s): record length is out of range: %d\n",
459 PACK_SRCNAME
, msr
->reclen
);
463 if ( msr
->byteorder
!= 0 && msr
->byteorder
!= 1 )
465 ms_log (2, "msr_pack_header(%s): byte order is not defined correctly: %d\n",
466 PACK_SRCNAME
, msr
->byteorder
);
472 maxheaderlen
= (msr
->fsdh
->data_offset
> 0) ?
473 msr
->fsdh
->data_offset
:
478 maxheaderlen
= msr
->reclen
;
481 /* Check to see if byte swapping is needed */
482 if ( msr
->byteorder
!= ms_bigendianhost() )
485 /* Check if byte order is forced */
486 if ( packheaderbyteorder
>= 0 )
488 headerswapflag
= ( msr
->byteorder
!= packheaderbyteorder
) ? 1: 0;
493 if ( headerswapflag
)
494 ms_log (1, "%s: Byte swapping needed for packing of header\n", PACK_SRCNAME
);
496 ms_log (1, "%s: Byte swapping NOT needed for packing of header\n", PACK_SRCNAME
);
499 headerlen
= msr_pack_header_raw (msr
, msr
->record
, maxheaderlen
,
500 headerswapflag
, normalize
, NULL
, verbose
);
503 } /* End of msr_pack_header() */
506 /***************************************************************************
507 * msr_pack_header_raw:
509 * Pack data header/blockettes into the specified SEED data record.
511 * Returns the header length in bytes on success or -1 on error.
512 ***************************************************************************/
514 msr_pack_header_raw ( MSRecord
*msr
, char *rawrec
, int maxheaderlen
,
515 flag swapflag
, flag normalize
,
516 struct blkt_1001_s
**blkt1001
, flag verbose
)
518 struct blkt_link_s
*cur_blkt
;
524 if ( ! msr
|| ! rawrec
)
527 /* Make sure a fixed section of data header is available */
530 msr
->fsdh
= (struct fsdh_s
*) calloc (1, sizeof (struct fsdh_s
));
532 if ( msr
->fsdh
== NULL
)
534 ms_log (2, "msr_pack_header_raw(%s): Cannot allocate memory\n",
540 /* Update the SEED structures associated with the MSRecord */
542 if ( msr_normalize_header (msr
, verbose
) < 0 )
544 ms_log (2, "msr_pack_header_raw(%s): error normalizing header values\n",
550 ms_log (1, "%s: Packing fixed section of data header\n", PACK_SRCNAME
);
552 if ( maxheaderlen
> msr
->reclen
)
554 ms_log (2, "msr_pack_header_raw(%s): maxheaderlen of %d is beyond record length of %d\n",
555 PACK_SRCNAME
, maxheaderlen
, msr
->reclen
);
559 if ( maxheaderlen
< (int)sizeof(struct fsdh_s
) )
561 ms_log (2, "msr_pack_header_raw(%s): maxheaderlen of %d is too small, must be >= %d\n",
562 PACK_SRCNAME
, maxheaderlen
, sizeof(struct fsdh_s
));
566 fsdh
= (struct fsdh_s
*) rawrec
;
569 /* Roll-over sequence number if necessary */
570 if ( msr
->sequence_number
> 999999 )
571 msr
->sequence_number
= 1;
573 /* Copy FSDH associated with the MSRecord into the record */
574 memcpy (fsdh
, msr
->fsdh
, sizeof(struct fsdh_s
));
576 /* Swap byte order? */
579 MS_SWAPBTIME (&fsdh
->start_time
);
580 ms_gswap2 (&fsdh
->numsamples
);
581 ms_gswap2 (&fsdh
->samprate_fact
);
582 ms_gswap2 (&fsdh
->samprate_mult
);
583 ms_gswap4 (&fsdh
->time_correct
);
584 ms_gswap2 (&fsdh
->data_offset
);
585 ms_gswap2 (&fsdh
->blockette_offset
);
588 /* Traverse blockette chain and pack blockettes at 'offset' */
589 cur_blkt
= msr
->blkts
;
591 while ( cur_blkt
&& offset
< maxheaderlen
)
593 /* Check that the blockette fits */
594 if ( (offset
+ 4 + cur_blkt
->blktdatalen
) > maxheaderlen
)
596 ms_log (2, "msr_pack_header_raw(%s): header exceeds maxheaderlen of %d\n",
597 PACK_SRCNAME
, maxheaderlen
);
601 /* Pack blockette type and leave space for next offset */
602 memcpy (rawrec
+ offset
, &cur_blkt
->blkt_type
, 2);
603 if ( swapflag
) ms_gswap2 (rawrec
+ offset
);
604 nextoffset
= offset
+ 2;
607 if ( cur_blkt
->blkt_type
== 100 )
609 struct blkt_100_s
*blkt_100
= (struct blkt_100_s
*) (rawrec
+ offset
);
610 memcpy (blkt_100
, cur_blkt
->blktdata
, sizeof (struct blkt_100_s
));
611 offset
+= sizeof (struct blkt_100_s
);
615 ms_gswap4 (&blkt_100
->samprate
);
619 else if ( cur_blkt
->blkt_type
== 200 )
621 struct blkt_200_s
*blkt_200
= (struct blkt_200_s
*) (rawrec
+ offset
);
622 memcpy (blkt_200
, cur_blkt
->blktdata
, sizeof (struct blkt_200_s
));
623 offset
+= sizeof (struct blkt_200_s
);
627 ms_gswap4 (&blkt_200
->amplitude
);
628 ms_gswap4 (&blkt_200
->period
);
629 ms_gswap4 (&blkt_200
->background_estimate
);
630 MS_SWAPBTIME (&blkt_200
->time
);
634 else if ( cur_blkt
->blkt_type
== 201 )
636 struct blkt_201_s
*blkt_201
= (struct blkt_201_s
*) (rawrec
+ offset
);
637 memcpy (blkt_201
, cur_blkt
->blktdata
, sizeof (struct blkt_201_s
));
638 offset
+= sizeof (struct blkt_201_s
);
642 ms_gswap4 (&blkt_201
->amplitude
);
643 ms_gswap4 (&blkt_201
->period
);
644 ms_gswap4 (&blkt_201
->background_estimate
);
645 MS_SWAPBTIME (&blkt_201
->time
);
649 else if ( cur_blkt
->blkt_type
== 300 )
651 struct blkt_300_s
*blkt_300
= (struct blkt_300_s
*) (rawrec
+ offset
);
652 memcpy (blkt_300
, cur_blkt
->blktdata
, sizeof (struct blkt_300_s
));
653 offset
+= sizeof (struct blkt_300_s
);
657 MS_SWAPBTIME (&blkt_300
->time
);
658 ms_gswap4 (&blkt_300
->step_duration
);
659 ms_gswap4 (&blkt_300
->interval_duration
);
660 ms_gswap4 (&blkt_300
->amplitude
);
661 ms_gswap4 (&blkt_300
->reference_amplitude
);
665 else if ( cur_blkt
->blkt_type
== 310 )
667 struct blkt_310_s
*blkt_310
= (struct blkt_310_s
*) (rawrec
+ offset
);
668 memcpy (blkt_310
, cur_blkt
->blktdata
, sizeof (struct blkt_310_s
));
669 offset
+= sizeof (struct blkt_310_s
);
673 MS_SWAPBTIME (&blkt_310
->time
);
674 ms_gswap4 (&blkt_310
->duration
);
675 ms_gswap4 (&blkt_310
->period
);
676 ms_gswap4 (&blkt_310
->amplitude
);
677 ms_gswap4 (&blkt_310
->reference_amplitude
);
681 else if ( cur_blkt
->blkt_type
== 320 )
683 struct blkt_320_s
*blkt_320
= (struct blkt_320_s
*) (rawrec
+ offset
);
684 memcpy (blkt_320
, cur_blkt
->blktdata
, sizeof (struct blkt_320_s
));
685 offset
+= sizeof (struct blkt_320_s
);
689 MS_SWAPBTIME (&blkt_320
->time
);
690 ms_gswap4 (&blkt_320
->duration
);
691 ms_gswap4 (&blkt_320
->ptp_amplitude
);
692 ms_gswap4 (&blkt_320
->reference_amplitude
);
696 else if ( cur_blkt
->blkt_type
== 390 )
698 struct blkt_390_s
*blkt_390
= (struct blkt_390_s
*) (rawrec
+ offset
);
699 memcpy (blkt_390
, cur_blkt
->blktdata
, sizeof (struct blkt_390_s
));
700 offset
+= sizeof (struct blkt_390_s
);
704 MS_SWAPBTIME (&blkt_390
->time
);
705 ms_gswap4 (&blkt_390
->duration
);
706 ms_gswap4 (&blkt_390
->amplitude
);
710 else if ( cur_blkt
->blkt_type
== 395 )
712 struct blkt_395_s
*blkt_395
= (struct blkt_395_s
*) (rawrec
+ offset
);
713 memcpy (blkt_395
, cur_blkt
->blktdata
, sizeof (struct blkt_395_s
));
714 offset
+= sizeof (struct blkt_395_s
);
718 MS_SWAPBTIME (&blkt_395
->time
);
722 else if ( cur_blkt
->blkt_type
== 400 )
724 struct blkt_400_s
*blkt_400
= (struct blkt_400_s
*) (rawrec
+ offset
);
725 memcpy (blkt_400
, cur_blkt
->blktdata
, sizeof (struct blkt_400_s
));
726 offset
+= sizeof (struct blkt_400_s
);
730 ms_gswap4 (&blkt_400
->azimuth
);
731 ms_gswap4 (&blkt_400
->slowness
);
732 ms_gswap2 (&blkt_400
->configuration
);
736 else if ( cur_blkt
->blkt_type
== 405 )
738 struct blkt_405_s
*blkt_405
= (struct blkt_405_s
*) (rawrec
+ offset
);
739 memcpy (blkt_405
, cur_blkt
->blktdata
, sizeof (struct blkt_405_s
));
740 offset
+= sizeof (struct blkt_405_s
);
744 ms_gswap2 (&blkt_405
->delay_values
);
749 ms_log (1, "msr_pack_header_raw(%s): WARNING Blockette 405 cannot be fully supported\n",
754 else if ( cur_blkt
->blkt_type
== 500 )
756 struct blkt_500_s
*blkt_500
= (struct blkt_500_s
*) (rawrec
+ offset
);
757 memcpy (blkt_500
, cur_blkt
->blktdata
, sizeof (struct blkt_500_s
));
758 offset
+= sizeof (struct blkt_500_s
);
762 ms_gswap4 (&blkt_500
->vco_correction
);
763 MS_SWAPBTIME (&blkt_500
->time
);
764 ms_gswap4 (&blkt_500
->exception_count
);
768 else if ( cur_blkt
->blkt_type
== 1000 )
770 struct blkt_1000_s
*blkt_1000
= (struct blkt_1000_s
*) (rawrec
+ offset
);
771 memcpy (blkt_1000
, cur_blkt
->blktdata
, sizeof (struct blkt_1000_s
));
772 offset
+= sizeof (struct blkt_1000_s
);
774 /* This guarantees that the byte order is in sync with msr_pack() */
775 if ( packdatabyteorder
>= 0 )
776 blkt_1000
->byteorder
= packdatabyteorder
;
779 else if ( cur_blkt
->blkt_type
== 1001 )
781 struct blkt_1001_s
*blkt_1001
= (struct blkt_1001_s
*) (rawrec
+ offset
);
782 memcpy (blkt_1001
, cur_blkt
->blktdata
, sizeof (struct blkt_1001_s
));
783 offset
+= sizeof (struct blkt_1001_s
);
785 /* Track location of Blockette 1001 if requested */
787 *blkt1001
= blkt_1001
;
790 else if ( cur_blkt
->blkt_type
== 2000 )
792 struct blkt_2000_s
*blkt_2000
= (struct blkt_2000_s
*) (rawrec
+ offset
);
793 memcpy (blkt_2000
, cur_blkt
->blktdata
, cur_blkt
->blktdatalen
);
794 offset
+= cur_blkt
->blktdatalen
;
798 ms_gswap2 (&blkt_2000
->length
);
799 ms_gswap2 (&blkt_2000
->data_offset
);
800 ms_gswap4 (&blkt_2000
->recnum
);
803 /* Nothing done to pack the opaque headers and data, they should already
804 be packed into the blockette payload */
809 memcpy (rawrec
+ offset
, cur_blkt
->blktdata
, cur_blkt
->blktdatalen
);
810 offset
+= cur_blkt
->blktdatalen
;
813 /* Pack the offset to the next blockette */
814 if ( cur_blkt
->next
)
816 memcpy (rawrec
+ nextoffset
, &offset
, 2);
817 if ( swapflag
) ms_gswap2 (rawrec
+ nextoffset
);
821 memset (rawrec
+ nextoffset
, 0, 2);
825 cur_blkt
= cur_blkt
->next
;
828 fsdh
->numblockettes
= blktcnt
;
831 ms_log (1, "%s: Packed %d blockettes\n", PACK_SRCNAME
, blktcnt
);
834 } /* End of msr_pack_header_raw() */
837 /***************************************************************************
840 * Update the header values that change between records: start time,
841 * sequence number, etc.
843 * Returns 0 on success or -1 on error.
844 ***************************************************************************/
846 msr_update_header ( MSRecord
*msr
, char *rawrec
, flag swapflag
,
847 struct blkt_1001_s
*blkt1001
, flag verbose
)
854 if ( ! msr
|| ! rawrec
)
858 ms_log (1, "%s: Updating fixed section of data header\n", PACK_SRCNAME
);
860 fsdh
= (struct fsdh_s
*) rawrec
;
862 /* Pack values into the fixed section of header */
863 snprintf (seqnum
, 7, "%06d", msr
->sequence_number
);
864 memcpy (fsdh
->sequence_number
, seqnum
, 6);
866 /* Get start time rounded to tenths of milliseconds and microsecond offset */
867 ms_hptime2tomsusecoffset (msr
->starttime
, &hptimems
, &usecoffset
);
869 /* Update fixed-section start time */
870 ms_hptime2btime (hptimems
, &(fsdh
->start_time
));
872 /* Swap byte order? */
875 MS_SWAPBTIME (&fsdh
->start_time
);
878 /* Update microsecond offset value if Blockette 1001 is present */
879 if ( msr
->Blkt1001
&& blkt1001
)
881 /* Update microseconds offset in blockette chain entry */
882 msr
->Blkt1001
->usec
= usecoffset
;
884 /* Update microseconds offset in packed header */
885 blkt1001
->usec
= usecoffset
;
889 } /* End of msr_update_header() */
892 /************************************************************************
895 * Pack Mini-SEED data samples. The input data samples specified as
896 * 'src' will be packed with 'encoding' format and placed in 'dest'.
898 * If a pointer to a 32-bit integer sample is provided in the
899 * argument 'lastintsample' and 'comphistory' is true the sample
900 * value will be used to seed the difference buffer for Steim1/2
901 * encoding and provide a compression history. It will also be
902 * updated with the last sample packed in order to be used with a
903 * subsequent call to this routine.
905 * The number of samples packed will be placed in 'packsamples' and
906 * the number of bytes packed will be placed in 'packbytes'.
908 * Return 0 on success and a negative number on error.
909 ************************************************************************/
911 msr_pack_data (void *dest
, void *src
, int maxsamples
, int maxdatabytes
,
912 int *packsamples
, int32_t *lastintsample
, flag comphistory
,
913 char sampletype
, flag encoding
, flag swapflag
, flag verbose
)
921 /* Decide if this is a format that we can decode */
926 if ( sampletype
!= 'a' )
928 ms_log (2, "%s: Sample type must be ascii (a) for ASCII encoding not '%c'\n",
929 PACK_SRCNAME
, sampletype
);
934 ms_log (1, "%s: Packing ASCII data\n", PACK_SRCNAME
);
936 retval
= msr_pack_text (dest
, src
, maxsamples
, maxdatabytes
, 1,
937 &npacked
, packsamples
);
942 if ( sampletype
!= 'i' )
944 ms_log (2, "%s: Sample type must be integer (i) for integer-16 encoding not '%c'\n",
945 PACK_SRCNAME
, sampletype
);
950 ms_log (1, "%s: Packing INT-16 data samples\n", PACK_SRCNAME
);
952 retval
= msr_pack_int_16 (dest
, src
, maxsamples
, maxdatabytes
, 1,
953 &npacked
, packsamples
, swapflag
);
958 if ( sampletype
!= 'i' )
960 ms_log (2, "%s: Sample type must be integer (i) for integer-32 encoding not '%c'\n",
961 PACK_SRCNAME
, sampletype
);
966 ms_log (1, "%s: Packing INT-32 data samples\n", PACK_SRCNAME
);
968 retval
= msr_pack_int_32 (dest
, src
, maxsamples
, maxdatabytes
, 1,
969 &npacked
, packsamples
, swapflag
);
974 if ( sampletype
!= 'f' )
976 ms_log (2, "%s: Sample type must be float (f) for float-32 encoding not '%c'\n",
977 PACK_SRCNAME
, sampletype
);
982 ms_log (1, "%s: Packing FLOAT-32 data samples\n", PACK_SRCNAME
);
984 retval
= msr_pack_float_32 (dest
, src
, maxsamples
, maxdatabytes
, 1,
985 &npacked
, packsamples
, swapflag
);
990 if ( sampletype
!= 'd' )
992 ms_log (2, "%s: Sample type must be double (d) for float-64 encoding not '%c'\n",
993 PACK_SRCNAME
, sampletype
);
998 ms_log (1, "%s: Packing FLOAT-64 data samples\n", PACK_SRCNAME
);
1000 retval
= msr_pack_float_64 (dest
, src
, maxsamples
, maxdatabytes
, 1,
1001 &npacked
, packsamples
, swapflag
);
1006 if ( sampletype
!= 'i' )
1008 ms_log (2, "%s: Sample type must be integer (i) for Steim-1 compression not '%c'\n",
1009 PACK_SRCNAME
, sampletype
);
1013 intbuff
= (int32_t *) src
;
1015 /* If a previous sample is supplied use it for compression history otherwise cold-start */
1016 d0
= ( lastintsample
&& comphistory
) ? (intbuff
[0] - *lastintsample
) : 0;
1019 ms_log (1, "%s: Packing Steim-1 data frames\n", PACK_SRCNAME
);
1021 nframes
= maxdatabytes
/ 64;
1023 retval
= msr_pack_steim1 (dest
, src
, d0
, maxsamples
, nframes
, 1,
1024 &npacked
, packsamples
, swapflag
);
1026 /* If a previous sample is supplied update it with the last sample value */
1027 if ( lastintsample
&& retval
== 0 )
1028 *lastintsample
= intbuff
[*packsamples
-1];
1033 if ( sampletype
!= 'i' )
1035 ms_log (2, "%s: Sample type must be integer (i) for Steim-2 compression not '%c'\n",
1036 PACK_SRCNAME
, sampletype
);
1040 intbuff
= (int32_t *) src
;
1042 /* If a previous sample is supplied use it for compression history otherwise cold-start */
1043 d0
= ( lastintsample
&& comphistory
) ? (intbuff
[0] - *lastintsample
) : 0;
1046 ms_log (1, "%s: Packing Steim-2 data frames\n", PACK_SRCNAME
);
1048 nframes
= maxdatabytes
/ 64;
1050 retval
= msr_pack_steim2 (dest
, src
, d0
, maxsamples
, nframes
, 1,
1051 &npacked
, packsamples
, swapflag
);
1053 /* If a previous sample is supplied update it with the last sample value */
1054 if ( lastintsample
&& retval
== 0 )
1055 *lastintsample
= intbuff
[*packsamples
-1];
1060 ms_log (2, "%s: Unable to pack format %d\n", PACK_SRCNAME
, encoding
);
1066 } /* End of msr_pack_data() */