Skip to content

Commit 2a1a0da

Browse files
committed
Added support for CAP, PRF and CPF markers
Improved Marker vs Marker Segment discrimination
1 parent 20c2f74 commit 2a1a0da

8 files changed

+393
-32
lines changed

.gitignore

+7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616
#
1717
src/.deps
1818
src/.libs
19+
/build
20+
21+
###
22+
# some tool dirs
23+
#
24+
25+
/.vscode
1926

2027
###
2128
# autotools output

src/AS_DCP.h

+25
Original file line numberDiff line numberDiff line change
@@ -1048,6 +1048,9 @@ namespace ASDCP {
10481048
const ui32_t MaxComponents = 3;
10491049
const ui32_t MaxPrecincts = 32; // ISO 15444-1 Annex A.6.1
10501050
const ui32_t MaxDefaults = 256; // made up
1051+
const ui8_t MaxCapabilities = 32;
1052+
const ui16_t MaxPRFN = 4;
1053+
const ui16_t MaxCPFN = 4;
10511054

10521055
#pragma pack(1)
10531056
struct ImageComponent_t // ISO 15444-1 Annex A.5.1
@@ -1085,6 +1088,25 @@ namespace ASDCP {
10851088
ui8_t SPqcd[MaxDefaults];
10861089
ui8_t SPqcdLength;
10871090
};
1091+
1092+
struct ExtendedCapabilities_t // ISO 15444-1 Annex A.5.2
1093+
{
1094+
ui32_t Pcap; // Pcap = 0 means that no extended capabilities are required
1095+
ui16_t Ccap[MaxCapabilities]; // Ccap^i in ISO/IEC 15444-1 corresponds to Ccap[i -1]
1096+
};
1097+
1098+
struct Profile_t // ISO 15444-1
1099+
{
1100+
ui16_t N; // N = 0 means that the profile is signaled through Rsiz exclusively
1101+
ui16_t Pprf[MaxPRFN]; // Pprf^i in ISO/IEC 15444-1 corresponds to Pprf[i -1]
1102+
};
1103+
1104+
struct CorrespondingProfile_t // ISO 15444-1
1105+
{
1106+
ui16_t N; // N = 0 means that no corresponding profile is signaled
1107+
ui16_t Pcpf[MaxCPFN]; // Pcpf^i in ISO/IEC 15444-1 corresponds to Pcpf[i -1]
1108+
};
1109+
10881110
#pragma pack()
10891111

10901112
struct PictureDescriptor
@@ -1108,6 +1130,9 @@ namespace ASDCP {
11081130
ImageComponent_t ImageComponents[MaxComponents];
11091131
CodingStyleDefault_t CodingStyleDefault;
11101132
QuantizationDefault_t QuantizationDefault;
1133+
ExtendedCapabilities_t ExtendedCapabilities;
1134+
Profile_t Profile;
1135+
CorrespondingProfile_t CorrespondingProfile;
11111136
};
11121137

11131138
// Print debugging information to std::ostream

src/AS_DCP_JP2K.cpp

+72
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,46 @@ ASDCP::JP2K::operator << (std::ostream& strm, const PictureDescriptor& PDesc)
106106
strm << " SPqcd: " << Kumu::bin2hex(PDesc.QuantizationDefault.SPqcd, PDesc.QuantizationDefault.SPqcdLength, tmp_buf, MaxDefaults*2)
107107
<< std::endl;
108108

109+
if (PDesc.Profile.N != 0) {
110+
strm << "Profile:" << std::endl;
111+
112+
for (ui16_t i = 0; i < PDesc.Profile.N; i++) {
113+
strm << " Pprf(" << (i + 1) << "): "
114+
<< std::hex << std::showbase << PDesc.Profile.Pprf[i] << std::dec << std::noshowbase
115+
<< std::endl;
116+
}
117+
}
118+
119+
if (PDesc.CorrespondingProfile.N != 0) {
120+
strm << "Corresponding Profile:" << std::endl;
121+
122+
for (ui16_t i = 0; i < PDesc.CorrespondingProfile.N; i++) {
123+
124+
strm << " Pcpf(" << (i + 1) << "): "
125+
<< std::hex << std::showbase << PDesc.CorrespondingProfile.Pcpf[i] << std::dec << std::noshowbase
126+
<< std::endl;
127+
}
128+
}
129+
130+
if (PDesc.ExtendedCapabilities.Pcap != 0) {
131+
132+
strm << "Extended Capabilities:" << std::endl;
133+
134+
135+
strm << " Pcap:" << PDesc.ExtendedCapabilities.Pcap << std::endl;
136+
137+
for (i32_t b = 0; b < JP2K::MaxCapabilities; b++) {
138+
139+
if ((PDesc.ExtendedCapabilities.Pcap >> b) & 0x1) {
140+
141+
strm << " Ccap(" << (JP2K::MaxCapabilities - b) << "): " <<
142+
std::hex << std::showbase << PDesc.ExtendedCapabilities.Ccap[JP2K::MaxCapabilities - b - 1] << std::dec << std::noshowbase
143+
<< std::endl;
144+
145+
}
146+
}
147+
}
148+
109149
return strm;
110150
}
111151

@@ -197,6 +237,38 @@ ASDCP::JP2K::PictureDescriptorDump(const PictureDescriptor& PDesc, FILE* stream)
197237
Kumu::bin2hex(PDesc.QuantizationDefault.SPqcd, PDesc.QuantizationDefault.SPqcdLength,
198238
tmp_buf, MaxDefaults*2)
199239
);
240+
241+
242+
if (PDesc.Profile.N != 0) {
243+
fprintf(stream, " Profile:\n");
244+
245+
for (ui16_t i = 0; i < PDesc.Profile.N; i++) {
246+
247+
fprintf(stream, " Pprf(%d): %hx\n", i + 1, PDesc.Profile.Pprf[i]);
248+
249+
}
250+
}
251+
252+
if (PDesc.CorrespondingProfile.N != 0) {
253+
fprintf(stream, "Corresponding Profile:\n");
254+
255+
for (ui16_t i = 0; i < PDesc.CorrespondingProfile.N; i++) {
256+
fprintf(stream, " Pcpf(%d): %hx\n", i + 1, PDesc.CorrespondingProfile.Pcpf[i]);
257+
258+
}
259+
}
260+
261+
fprintf(stream, "Extended Capabilities: %x\n", PDesc.ExtendedCapabilities.Pcap);
262+
263+
for (i32_t b = 0; b < JP2K::MaxCapabilities; b++) {
264+
265+
if ((PDesc.ExtendedCapabilities.Pcap >> b) & 0x1) {
266+
267+
fprintf(stream, " Ccap(%d): %hx\n", JP2K::MaxCapabilities - b, PDesc.ExtendedCapabilities.Ccap[JP2K::MaxCapabilities - b - 1]);
268+
269+
}
270+
}
271+
200272
}
201273

202274

src/JP2K.cpp

+79-32
Original file line numberDiff line numberDiff line change
@@ -37,45 +37,17 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737
using Kumu::DefaultLogSink;
3838

3939

40-
// when indexed with the second byte of a marker code, this table will procuce one of
41-
// two values:
42-
// 0 - the marker is a standalone marker
43-
// 1 - the marker designates a marker segment
44-
//
45-
const byte_t MarkerSegmentMap[] =
46-
{
47-
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
48-
/* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
49-
/* 1 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
50-
/* 2 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
51-
/* 3 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
52-
/* 4 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
53-
/* 5 */ 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, // 5
54-
/* 6 */ 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
55-
/* 7 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
56-
/* 8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
57-
/* 9 */ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
58-
/* a */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // a
59-
/* b */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // b
60-
/* c */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // c
61-
/* d */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // d
62-
/* e */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // e
63-
/* f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // f
64-
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
65-
};
66-
67-
6840
//
6941
ASDCP::Result_t
7042
ASDCP::JP2K::GetNextMarker(const byte_t** buf, JP2K::Marker& Marker)
7143
{
7244
assert((buf != 0) && (*buf != 0 ));
7345

74-
if ( **buf != 0xff )
46+
if (*(*buf)++ != 0xff )
7547
return ASDCP::RESULT_FAIL;
7648

77-
Marker.m_IsSegment = (MarkerSegmentMap[*(++(*buf))] == 1);
7849
Marker.m_Type = (Marker_t)(0xff00 | *(*buf)++);
50+
Marker.m_IsSegment = Marker.m_Type != MRK_SOC && Marker.m_Type != MRK_SOD && Marker.m_Type != MRK_EOC;
7951

8052
if ( Marker.m_IsSegment )
8153
{
@@ -86,13 +58,13 @@ ASDCP::JP2K::GetNextMarker(const byte_t** buf, JP2K::Marker& Marker)
8658
*buf += Marker.m_DataSize;
8759
}
8860

89-
61+
/* TODO: why is this here?
9062
if ( Marker.m_DataSize != 0 && Marker.m_DataSize < 3 )
9163
{
9264
DefaultLogSink().Error("Illegal data size: %u\n", Marker.m_DataSize);
9365
return ASDCP::RESULT_FAIL;
9466
}
95-
67+
*/
9668
return ASDCP::RESULT_OK;
9769
}
9870

@@ -227,6 +199,78 @@ ASDCP::JP2K::Accessor::COM::Dump(FILE* stream) const
227199
}
228200
}
229201

202+
//
203+
void
204+
ASDCP::JP2K::Accessor::PRF::Dump(FILE* stream) const
205+
{
206+
if ( stream == 0 )
207+
stream = stderr;
208+
209+
fprintf(stream, "PRF: \n");
210+
211+
if (N() == 0) {
212+
213+
fprintf(stream, " N/A");
214+
215+
} else {
216+
217+
for (ui16_t i = 1; i <= N(); i++) {
218+
fprintf(stream, "pprf(%d): %d\n", i, pprf(i));
219+
}
220+
221+
}
222+
}
223+
224+
//
225+
void
226+
ASDCP::JP2K::Accessor::CPF::Dump(FILE* stream) const
227+
{
228+
if ( stream == 0 )
229+
stream = stderr;
230+
231+
fprintf(stream, "CPF: \n");
232+
233+
if (N() == 0) {
234+
235+
fprintf(stream, " N/A");
236+
237+
} else {
238+
239+
for (ui16_t i = 1; i <= N(); i++) {
240+
fprintf(stream, "pcpf(%d): %d\n", i, pcpf(i));
241+
}
242+
243+
}
244+
}
245+
246+
247+
//
248+
void
249+
ASDCP::JP2K::Accessor::CAP::Dump(FILE* stream) const
250+
{
251+
if ( stream == 0 )
252+
stream = stderr;
253+
254+
fprintf(stream, "CAP: \n");
255+
256+
ui32_t pcap = this->pcap();
257+
258+
if (pcap == 0) {
259+
260+
fprintf(stream, " None");
261+
262+
} else {
263+
264+
for (i32_t b = 32, i = 1; b > 0; b--) {
265+
266+
if ((pcap >> (32 - b)) & 0x1) {
267+
268+
fprintf(stream, " ccap(%d): %d\n", b, this->ccap(i++));
269+
270+
}
271+
}
272+
}
273+
}
230274

231275
//-------------------------------------------------------------------------------------------------------
232276
//
@@ -274,6 +318,9 @@ ASDCP::JP2K::GetMarkerString(Marker_t m)
274318
case MRK_EPH: return "EPH: End of packet header"; break;
275319
case MRK_CRG: return "CRG: Component registration"; break;
276320
case MRK_COM: return "COM: Comment"; break;
321+
case MRK_CPF: return "CPF: Corresponding profile"; break;
322+
case MRK_CAP: return "CAP: Capabilities"; break;
323+
case MRK_PRF: return "PRF: Profile"; break;
277324
}
278325

279326
return "Unknown marker code";

src/JP2K.h

+82
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,12 @@ namespace JP2K
5454
MRK_SOT = 0xff90, // Start of tile-part
5555
MRK_SOD = 0xff93, // Start of data
5656
MRK_EOC = 0xffd9, // End of codestream
57+
MRK_CAP = 0xff50, // Extended capabilities
5758
MRK_SIZ = 0xff51, // Image and tile size
5859
MRK_COD = 0xff52, // Coding style default
5960
MRK_COC = 0xff53, // Coding style component
61+
MRK_PRF = 0xff56, // Profile
62+
MRK_CPF = 0xff59, // Corresponding profile
6063
MRK_RGN = 0xff5e, // Region of interest
6164
MRK_QCD = 0xff5c, // Quantization default
6265
MRK_QCC = 0xff5d, // Quantization component
@@ -219,6 +222,85 @@ namespace JP2K
219222
inline ui32_t CommentSize() const { return m_DataSize; }
220223
void Dump(FILE* stream = 0) const;
221224
};
225+
226+
// Corresponding Profile
227+
class CPF {
228+
229+
const ui16_t* m_Data;
230+
ui16_t m_N;
231+
232+
KM_NO_COPY_CONSTRUCT(CPF);
233+
CPF();
234+
235+
public:
236+
CPF(const Marker& M) {
237+
assert(M.m_Type == MRK_CPF);
238+
239+
m_Data = (ui16_t*) M.m_Data;
240+
m_N = M.m_DataSize >> 1;
241+
}
242+
243+
~CPF() {}
244+
245+
inline ui16_t N() const { return m_N; }
246+
247+
inline ui16_t pcpf(ui16_t i) const { return KM_i16_BE(m_Data[2 * (i - 1)]); }
248+
249+
void Dump(FILE* stream = 0) const;
250+
};
251+
252+
// Profile
253+
class PRF {
254+
255+
const ui16_t* m_Data;
256+
ui16_t m_N;
257+
258+
KM_NO_COPY_CONSTRUCT(PRF);
259+
PRF();
260+
261+
public:
262+
PRF(const Marker& M) {
263+
assert(M.m_Type == MRK_CPF);
264+
265+
m_Data = (ui16_t*) M.m_Data;
266+
m_N = M.m_DataSize >> 1;
267+
}
268+
269+
~PRF() {}
270+
271+
inline ui16_t N() const { return m_N; }
272+
273+
inline ui16_t pprf(ui16_t i) const { return KM_i16_BE(m_Data[2 * (i - 1)]); }
274+
275+
void Dump(FILE* stream = 0) const;
276+
};
277+
278+
// Extended capabilities
279+
class CAP {
280+
281+
const ui16_t* m_Data;
282+
283+
ui32_t m_Pcap;
284+
285+
KM_NO_COPY_CONSTRUCT(CAP);
286+
CAP();
287+
288+
public:
289+
CAP(const Marker& M) {
290+
assert(M.m_Type == MRK_CAP);
291+
292+
m_Data = (ui16_t *) (M.m_Data + 4);
293+
m_Pcap = KM_i32_BE(*(ui32_t*)(M.m_Data));
294+
}
295+
296+
~CAP() {}
297+
298+
inline ui32_t pcap() const { return m_Pcap; }
299+
300+
inline ui16_t ccap(ui16_t i) const { return KM_i16_BE(m_Data[2 * (i - 1)]); }
301+
302+
void Dump(FILE* stream = 0) const;
303+
};
222304
} // namespace Accessor
223305
} // namespace JP2K
224306
} // namespace ASDCP

0 commit comments

Comments
 (0)