satdump/plugins/hinode_support/hinode/instruments/common.cpp

476 lines
18 KiB
C++
Raw Normal View History

2023-11-13 01:28:14 +01:00
#include "common.h"
#include <cmath>
#include "defines.h"
#include <cstring>
#include "common/image/jpeg12_utils.h"
namespace hinode
{
ScienceHeader HinodeDepacketizer::parse_science_header(ccsds::CCSDSPacket &pkt)
{
ScienceHeader wk;
uint8_t *p = &pkt.payload[0];
wk.DataType = p[12]; // DataType
wk.PacketSize = p[13] << 16 | p[14] << 8 | p[15]; // PacketSize
wk.SerialPacketNo = p[16] << 24 | p[17] << 16 | p[18] << 8 | p[19]; // SerialPacketNo
wk.MainID = p[20] << 8 | p[21]; // MainID
wk.MainSQFlag = (p[22] & 0xc0) >> 6; // MainSequenceFlag
wk.MainSQCount = (p[22] & 0x3f) << 8 | p[23] << 0; // MainSequenceCount
// p[30] ̏2 bit reserved
wk.NumOfPacket = (p[24] & 0x3f) << 2 | (p[25] & 0xc0) >> 6; // NumberOfPacket
wk.NumOfFrame = p[25] & 0x3f; // NumberOfFrame
wk.SubID = p[26] << 8 | p[27]; // SubID
wk.SubSQFlag = (p[28] & 0xc0) >> 6; // SequenceFlag
wk.SubSQCount = (p[28] & 0x3f) << 8 | p[29]; // SequenceCount
wk.FullImageSizeX = p[30] << 8 | p[31]; // FullImageSizeX
wk.FullImageSizeY = p[32] << 8 | p[33]; // FullImageSizeY
wk.BasePointCoorX = p[34] << 8 | p[35]; // BasePointCoorX
wk.BasePointCoorY = p[36] << 8 | p[37]; // BasePointCoorY
wk.PartImageSizeX = p[38] << 8 | p[39]; // PartImageSizeX
wk.PartImageSizeY = p[40] << 8 | p[41]; // PartImageSizeY
// p[48] 1 bit reserved
wk.BitCompMode = (p[42] & 0x78) >> 3; // k[hibit)
wk.ImageCompMode = p[42] & 0x07; // k[hiImage)
// p[49] ̏1 bit reserved
wk.HTACNo = (p[43] & 0x60) >> 5; // nt}ACNo
wk.HTDCNo = (p[43] & 0x18) >> 3; // nt}DCNo
wk.QTNo = p[43] & 0x07; // ʎqe[uNo
{
int restart_pixel = 99; // invalid
int num_segment = 99; // invalid
switch (wk.ImageCompMode)
{
case COMP_MODE_DPCM12: // DPCM<43><4D><EFBFBD>k
for (restart_pixel = wk.PartImageSizeX; restart_pixel % 64 != 0;)
{ // <20><><EFBFBD>X<EFBFBD>^<5E>[<5B>g<EFBFBD>Ԋu
restart_pixel = restart_pixel * 2;
}
num_segment = (int)ceil(1.0 * wk.PartImageSizeX * wk.PartImageSizeY / restart_pixel);
break;
case COMP_MODE_DCT12: // DCT<43><54><EFBFBD>k
restart_pixel = 8 * 8 * 64; // <20><><EFBFBD>X<EFBFBD>^<5E>[<5B>g<EFBFBD>Ԋu
num_segment = (int)ceil(1.0 * wk.PartImageSizeX * wk.PartImageSizeY / restart_pixel);
break;
default:
wk.ImageCompMode = 0;
}
wk.restart_pixel = restart_pixel;
wk.num_segment = num_segment;
}
2023-11-13 12:13:50 +01:00
// uint32_t time = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
// double ttime = time + 946684800.0;
// printf("TIME = %s\n", timestamp_to_string(ttime).c_str());
2023-11-13 01:28:14 +01:00
num_RST = 0;
restored_flag = 0;
buff_pos = 0;
ECS0_start = 0;
return wk;
}
HinodeDepacketizer::HinodeDepacketizer()
{
buffer = new uint8_t[MAX_COMP_LEN];
_chk_tbl = new uint8_t[MAX_PIXELS];
rst_tbl_array = new rst_tbl_t[MAX_RST];
status = JPEG_INIT;
}
HinodeDepacketizer::~HinodeDepacketizer()
{
delete[] buffer;
delete[] _chk_tbl;
delete[] rst_tbl_array;
}
int HinodeDepacketizer::work(ccsds::CCSDSPacket &pkt, DecodedImage *result)
{
// if (pkt.payload.size() == pkt.header.packet_length + 1)
// return status;
result->apid = -1;
int wk = 0;
int rst2ndNo = 0;
if (status != BUFF_NOW)
{ /* 1. waiting for start of next image */
if (pkt.header.sequence_flag == 0b01)
{
sci_hdr = parse_science_header(pkt);
if (sci_hdr.ImageCompMode != 0)
{ // JPEG data
status = BUFF_NOW;
before_sq_count = pkt.header.packet_sequence_count;
before_sq_flag = pkt.header.sequence_flag;
}
else
{ // not JPEG data
status = NOT_JPEG_DATA;
}
}
if (status == JPEG_INIT)
return JPEG_IRRETRIEVABLE; // KM note *12
return status;
}
else
{ /* 2. Processing of image */
rst_tbl_t *rst_tbl = &rst_tbl_array[0];
if (pkt.header.sequence_flag == 0b01)
{ /* 2.1. <20><><EFBFBD>̓p<CD83>P<EFBFBD>b<EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD>P<EFBFBD>p<EFBFBD>P<EFBFBD>b<EFBFBD>g<EFBFBD>̏ꍇ */
/* finalize process of accumulated image */
int iret = 99; // invalid, determined soon
if (before_sq_flag == 0b01)
{
/* 2.1.1. Processing of designed pattern 8 */
iret = JPEG_IRRETRIEVABLE; // discard accumlated image
}
else
{
/* 2.1.2. Processing of designed pattern 4, 10 */
fill_tail(); // recover RSTn, EOI [KM51]
// Input: _sci_head.num_segment, Modified: num_RST, rst_tbl, buff_pos, buffer
if (num_RST != sci_hdr.num_segment - 1)
{ // check number of RSTn
/* recovery failed, retry recovery */
wk = trunc_recovered(); // [KM52], KM note *9)
// Input: _sci_head.num_segment, Modified: num_RST, rst_tbl, buff_pos, buffer
// dbg("KM52 wk=%d num_RST=%d num_segment=%d\n", wk, *num_RST, _sci_head->num_segment);
if (wk != 0)
{
// dbg("KM72");
return status = JPEG_IRRETRIEVABLE; // discard accumlated image
// KM: why return here ??
}
}
/* recovery succeeded */
clear_chktbl(); //////
fill_chktbl();
// Input: _sci_head, num_RST, rst_tbl, output: _chk_tbl
{
result->apid = pkt.header.apid;
result->sci = sci_hdr;
result->img = image::decompress_jpeg12(buffer, buff_pos);
img_cnt++;
}
// dbg("KM61");
iret = JPEG_RESTORED;
/* end of 2.1.2. */
}
sci_hdr = parse_science_header(pkt);
if (sci_hdr.ImageCompMode != 0)
{ // JPEG data
status = BUFF_NOW;
before_sq_count = pkt.header.packet_sequence_count;
before_sq_flag = pkt.header.sequence_flag;
}
else
{ // not JPEG data
status = NOT_JPEG_DATA;
}
return iret;
/* end of 2.1. */
}
else
{
/* 2.2. <20><><EFBFBD>̓p<CD83>P<EFBFBD>b<EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD>P<EFBFBD>p<EFBFBD>P<EFBFBD>b<EFBFBD>g<EFBFBD>ȊO<C88A>̏ꍇ */
int istatus = BUFF_NOW;
int istart_flag = 1;
const int data_length = pkt.header.packet_length + 1 - 4;
const int sq_count_diff = (pkt.header.packet_sequence_count - before_sq_count + ALIGN) % ALIGN;
if (sq_count_diff >= MAX_SQDIFF)
{
/* 2.2.1. too large counter skip */
if (before_sq_flag == 0b01)
{
// dbg("KM73");
return status = JPEG_IRRETRIEVABLE; // discard accumulated image
}
else
{
fill_tail(); // recover RSTn, EOI [KM54] KM note *10)
// Input: _sci_head.num_segment, Modified: num_RST, rst_tbl, buff_pos, buffer
// dbg("KM73a");
istatus = RESTORED_IRRETRIEVABLE; // finish accumulation of image
istart_flag = 0;
}
/* end of 2.2.1. */
}
else if (sq_count_diff > 1)
{
/* 2.2.2. not too large counter skip */
/* <20><><EFBFBD>͂<EFBFBD><CD82><EFBFBD><EFBFBD>p<EFBFBD>P<EFBFBD>b<EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD>RSTn<54>̌<EFBFBD><CC8C><EFBFBD> */
int packetpos = -1;
#if 0
for (i=0; i<data_length; i++) {
#else
// KM notice *7 from here
for (int i = 0; i < data_length - 1; i++)
{
// KM notice *7 until here
#endif
if (pkt.payload[i + 4] == 0xFF)
{
const int rst2nd = pkt.payload[i + 5] & RST2ND_MASK;
rst2ndNo = pkt.payload[i + 5] & RSTNO_MASK;
if (rst2nd == 0xD0)
{
packetpos = i; // CCSDS<44>p<EFBFBD>P<EFBFBD>b<EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD>RST<53>̍ŏ<CC8D><C58F>̈ʒu
break;
}
}
}
if (packetpos == -1)
{
/* 2.2.2.1. no RSTn found */
if (pkt.header.sequence_flag != 0b10)
{
return status = BUFF_NOW; // discard packet, continue accumulation
// do not update before_sq_count, before_sq_flag
}
else
{
if (before_sq_flag == 0b01)
{
// dbg("KM74");
return status = JPEG_IRRETRIEVABLE; // discard accumulated image of image
}
else
{
fill_tail(); // recover RSTn, EOI [KM55] KM note *10)
// Input: _sci_head.num_segment, Modified: num_RST, rst_tbl, buff_pos, buffer
// dbg("KM62");
istatus = JPEG_RESTORED; // finish accumulation of image
istart_flag = 0;
}
}
/* end of 2.2.2.1. */
}
else
{
/* 2.2.2.2. RSTn found */
if (before_sq_flag == 0b01)
{
if (sci_hdr.ImageCompMode == COMP_MODE_DCT12)
{
insert_dct_header();
}
else if (sci_hdr.ImageCompMode == COMP_MODE_DPCM12)
{
insert_dpcm_header();
}
ECS0_start = buff_pos; // <20>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<40>̍ŏI<C58F>|<7C>C<EFBFBD><43><EFBFBD>^<5E><><EFBFBD><EFBFBD>
}
fill_gap(pkt, data_length, packetpos, rst2ndNo); // recover RSTn, add packet [KM53, KM56]
// Input: ECS0_start, Modified: num_RST, rst_tbl, buff_pos, buffer
if (pkt.header.sequence_flag == 0b10)
{
// dbg("KM63");
istatus = JPEG_RESTORED; // finsish accumulation of image
istart_flag = 0;
}
else
{
// istatus = BUFF_NOW; // continue accumlation of image
}
/* end of 2.2.2.2. */
}
/* end of 2.2.2. */
}
else
{
/* 2.2.3. no counter skip */
int markpos = -1;
// KM notice *8 from here
if (buffer[buff_pos - 1] == 0xFF)
{
markpos = buff_pos - 1;
}
// KM notice *8 until here
for (int i = 0; i < data_length; i++)
{
const unsigned char octet = pkt.payload[i + 4];
buffer[buff_pos] = octet;
if (octet == 0xFF)
{
markpos = buff_pos;
}
else
{
if (markpos >= 0)
{
const int rst2nd = octet & RST2ND_MASK;
rst2ndNo = octet & RSTNO_MASK;
if (rst2nd == 0xD0)
{ // RSTn<54><6E><EFBFBD><EFBFBD><EFBFBD>‚<EFBFBD><C282><EFBFBD><EFBFBD><EFBFBD>
rst_tbl[num_RST].pos = markpos;
rst_tbl[num_RST].No = rst2ndNo;
rst_tbl[num_RST].flg = 0;
num_RST++;
}
else if (octet == 0xDA)
{ // SOS <20><><EFBFBD><EFBFBD><EFBFBD>‚<EFBFBD><C282><EFBFBD><EFBFBD><EFBFBD>
ECS0_start = buff_pos + 9; // <20><EFBFBD>f<EFBFBD>[<5B>^<5E>̊J<CC8A>n<EFBFBD>ʒu<CA92>́ASOS <20>}<7D>[<5B>J<EFBFBD>̂Q<CC82>o<EFBFBD>C<EFBFBD>g<EFBFBD>ڂ<EFBFBD><DA82><EFBFBD>A<EFBFBD>X<EFBFBD>o<EFBFBD>C<EFBFBD>g<EFBFBD><67>ɂ<EFBFBD><C982><EFBFBD>B
// KM notice *3 from here
}
else if (octet == 0xD9)
{ // EOI
rst_tbl[num_RST].flg = 0;
// KM notice *3 until here
}
}
markpos = -1;
}
buff_pos++;
}
if (pkt.header.sequence_flag == 0b10)
{
//// dbg("KM64");
istatus = JPEG_RESTORED; // finsish accumulation of image
istart_flag = 0;
}
else
{
// istatus = BUFF_NOW; // continue accumlation of image
}
/* end of 2.2.3. */
}
if (istatus != BUFF_NOW)
{
clear_chktbl();
// Output: _chk_tbl
}
if (istatus == JPEG_RESTORED && istart_flag == 0)
{
if (restored_flag == 0)
{
istatus = JPEG_EXTRACT;
}
else
{
if (num_RST != sci_hdr.num_segment - 1)
{ // check number of RSTn
/* recovery failed, retry recovery */
wk = trunc_recovered(); // [KM57]
// Input: _sci_head.num_segment, Modified: num_RST, rst_tbl, buff_pos, buffer
if (wk != 0)
{
// dbg("KM75");
return status = JPEG_IRRETRIEVABLE; // discard accumlated image
}
// dbg("KM75a");
istatus = RESTORED_IRRETRIEVABLE; // finish accumulation of image
}
/* recovery succeeded */
clear_chktbl(); //////
fill_chktbl();
// Input: _sci_head, num_RST, rst_tbl, output: _chk_tbl
}
}
if (istatus != BUFF_NOW)
{
/* JPEG_EXTRACT or JPEG_RESTORED or RESTORED_IRRETRIEVABLE */
/* JPEG <20>f<EFBFBD>[<5B>^<5E><><EFBFBD>i<EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD>o<EFBFBD>b<EFBFBD>t<EFBFBD>@<40>̃|<7C>C<EFBFBD><43><EFBFBD>^<5E><>Ԃ<EFBFBD> */
{
result->apid = pkt.header.apid;
result->sci = sci_hdr;
result->img = image::decompress_jpeg12(buffer, buff_pos);
img_cnt++;
}
}
else
{
/* BUFF_NOW */
/* NULL <20><>Ԃ<EFBFBD> */
before_sq_count = pkt.header.packet_sequence_count;
before_sq_flag = pkt.header.sequence_flag;
}
switch (istatus)
{
case JPEG_EXTRACT:
case JPEG_RESTORED:
status = (istart_flag == 0) ? NOT_JPEG_DATA : BUFF_NOW;
break;
case RESTORED_IRRETRIEVABLE:
status = (istart_flag == 0) ? JPEG_IRRETRIEVABLE : BUFF_NOW;
break;
case BUFF_NOW:
status = BUFF_NOW;
break;
default:
fprintf(stderr, "DePacketizeBody(): fatal logic error (1266)\n");
}
return istatus;
/* end of 2.2. */
}
/* end of 2. */
}
}
}