in libheif/box.cc [447:822]
Error Box::read(BitstreamRange& range, std::shared_ptr<Box>* result)
{
BoxHeader hdr;
Error err = hdr.parse_header(range);
if (err) {
return err;
}
if (range.error()) {
return range.get_error();
}
std::shared_ptr<Box> box;
switch (hdr.get_short_type()) {
case fourcc("ftyp"):
box = std::make_shared<Box_ftyp>();
break;
case fourcc("meta"):
box = std::make_shared<Box_meta>();
break;
case fourcc("hdlr"):
box = std::make_shared<Box_hdlr>();
break;
case fourcc("pitm"):
box = std::make_shared<Box_pitm>();
break;
case fourcc("iloc"):
box = std::make_shared<Box_iloc>();
break;
case fourcc("iinf"):
box = std::make_shared<Box_iinf>();
break;
case fourcc("infe"):
box = std::make_shared<Box_infe>();
break;
case fourcc("iprp"):
box = std::make_shared<Box_iprp>();
break;
case fourcc("ipco"):
box = std::make_shared<Box_ipco>();
break;
case fourcc("ipma"):
box = std::make_shared<Box_ipma>();
break;
case fourcc("ispe"):
box = std::make_shared<Box_ispe>();
break;
case fourcc("auxC"):
box = std::make_shared<Box_auxC>();
break;
case fourcc("irot"):
box = std::make_shared<Box_irot>();
break;
case fourcc("imir"):
box = std::make_shared<Box_imir>();
break;
case fourcc("clap"):
box = std::make_shared<Box_clap>();
break;
case fourcc("iref"):
box = std::make_shared<Box_iref>();
break;
case fourcc("hvcC"):
box = std::make_shared<Box_hvcC>();
break;
case fourcc("av1C"):
box = std::make_shared<Box_av1C>();
break;
case fourcc("vvcC"):
box = std::make_shared<Box_vvcC>();
break;
case fourcc("idat"):
box = std::make_shared<Box_idat>();
break;
case fourcc("grpl"):
box = std::make_shared<Box_grpl>();
break;
case fourcc("pymd"):
box = std::make_shared<Box_pymd>();
break;
case fourcc("altr"):
box = std::make_shared<Box_EntityToGroup>();
break;
case fourcc("ster"):
box = std::make_shared<Box_ster>();
break;
case fourcc("dinf"):
box = std::make_shared<Box_dinf>();
break;
case fourcc("dref"):
box = std::make_shared<Box_dref>();
break;
case fourcc("url "):
box = std::make_shared<Box_url>();
break;
case fourcc("colr"):
box = std::make_shared<Box_colr>();
break;
case fourcc("pixi"):
box = std::make_shared<Box_pixi>();
break;
case fourcc("pasp"):
box = std::make_shared<Box_pasp>();
break;
case fourcc("lsel"):
box = std::make_shared<Box_lsel>();
break;
case fourcc("a1op"):
box = std::make_shared<Box_a1op>();
break;
case fourcc("a1lx"):
box = std::make_shared<Box_a1lx>();
break;
case fourcc("clli"):
box = std::make_shared<Box_clli>();
break;
case fourcc("mdcv"):
box = std::make_shared<Box_mdcv>();
break;
case fourcc("cmin"):
box = std::make_shared<Box_cmin>();
break;
case fourcc("cmex"):
box = std::make_shared<Box_cmex>();
break;
case fourcc("udes"):
box = std::make_shared<Box_udes>();
break;
case fourcc("jpgC"):
box = std::make_shared<Box_jpgC>();
break;
#if WITH_UNCOMPRESSED_CODEC
case fourcc("cmpd"):
box = std::make_shared<Box_cmpd>();
break;
case fourcc("uncC"):
box = std::make_shared<Box_uncC>();
break;
case fourcc("cmpC"):
box = std::make_shared<Box_cmpC>();
break;
case fourcc("icbr"):
box = std::make_shared<Box_icbr>();
break;
#endif
// --- JPEG 2000
case fourcc("j2kH"):
box = std::make_shared<Box_j2kH>();
break;
case fourcc("cdef"):
box = std::make_shared<Box_cdef>();
break;
case fourcc("cmap"):
box = std::make_shared<Box_cmap>();
break;
case fourcc("pclr"):
box = std::make_shared<Box_pclr>();
break;
case fourcc("j2kL"):
box = std::make_shared<Box_j2kL>();
break;
// --- mski
case fourcc("mskC"):
box = std::make_shared<Box_mskC>();
break;
// --- AVC (H.264)
case fourcc("avcC"):
box = std::make_shared<Box_avcC>();
break;
case fourcc("mdat"):
// avoid generating a 'Box_other'
box = std::make_shared<Box>();
break;
case fourcc("uuid"):
if (hdr.get_uuid_type() == std::vector<uint8_t>{0x22, 0xcc, 0x04, 0xc7, 0xd6, 0xd9, 0x4e, 0x07, 0x9d, 0x90, 0x4e, 0xb6, 0xec, 0xba, 0xf3, 0xa3}) {
box = std::make_shared<Box_cmin>();
}
else if (hdr.get_uuid_type() == std::vector<uint8_t>{0x43, 0x63, 0xe9, 0x14, 0x5b, 0x7d, 0x4a, 0xab, 0x97, 0xae, 0xbe, 0xa6, 0x98, 0x03, 0xb4, 0x34}) {
box = std::make_shared<Box_cmex>();
}
else {
box = std::make_shared<Box_other>(hdr.get_short_type());
}
break;
case fourcc("moov"):
box = std::make_shared<Box_moov>();
break;
case fourcc("mvhd"):
box = std::make_shared<Box_mvhd>();
break;
case fourcc("trak"):
box = std::make_shared<Box_trak>();
break;
case fourcc("tkhd"):
box = std::make_shared<Box_tkhd>();
break;
case fourcc("mdia"):
box = std::make_shared<Box_mdia>();
break;
case fourcc("mdhd"):
box = std::make_shared<Box_mdhd>();
break;
case fourcc("minf"):
box = std::make_shared<Box_minf>();
break;
case fourcc("vmhd"):
box = std::make_shared<Box_vmhd>();
break;
case fourcc("stbl"):
box = std::make_shared<Box_stbl>();
break;
case fourcc("stsd"):
box = std::make_shared<Box_stsd>();
break;
case fourcc("hvc1"):
box = std::make_shared<Box_hvc1>();
break;
case fourcc("ccst"):
box = std::make_shared<Box_ccst>();
break;
case fourcc("stsz"):
box = std::make_shared<Box_stsz>();
break;
case fourcc("stts"):
box = std::make_shared<Box_stts>();
break;
case fourcc("stsc"):
box = std::make_shared<Box_stsc>();
break;
case fourcc("stco"):
box = std::make_shared<Box_stco>();
break;
case fourcc("stss"):
box = std::make_shared<Box_stss>();
break;
default:
box = std::make_shared<Box_other>(hdr.get_short_type());
break;
}
box->set_short_header(hdr);
if (hdr.has_fixed_box_size() && hdr.get_box_size() < hdr.get_header_size()) {
std::stringstream sstr;
sstr << "Box size (" << hdr.get_box_size() << " bytes) smaller than header size ("
<< hdr.get_header_size() << " bytes)";
// Sanity check.
return Error(heif_error_Invalid_input,
heif_suberror_Invalid_box_size,
sstr.str());
}
if (range.get_nesting_level() > MAX_BOX_NESTING_LEVEL) {
return Error(heif_error_Memory_allocation_error,
heif_suberror_Security_limit_exceeded,
"Security limit for maximum nesting of boxes has been exceeded");
}
if (hdr.has_fixed_box_size()) {
auto status = range.wait_for_available_bytes(hdr.get_box_size() - hdr.get_header_size());
if (status != StreamReader::size_reached) {
// TODO: return recoverable error at timeout
return Error(heif_error_Invalid_input,
heif_suberror_End_of_data);
}
}
// Security check: make sure that box size does not exceed int64 size.
if (hdr.get_box_size() > (uint64_t) std::numeric_limits<int64_t>::max()) {
return Error(heif_error_Invalid_input,
heif_suberror_Invalid_box_size);
}
int64_t box_size = static_cast<int64_t>(hdr.get_box_size());
int64_t box_size_without_header = hdr.has_fixed_box_size() ? (box_size - hdr.get_header_size()) : (int64_t)range.get_remaining_bytes();
// Box size may not be larger than remaining bytes in parent box.
if ((int64_t)range.get_remaining_bytes() < box_size_without_header) {
return Error(heif_error_Invalid_input,
heif_suberror_Invalid_box_size);
}
// Create child bitstream range and read box from that range.
BitstreamRange boxrange(range.get_istream(),
box_size_without_header,
&range);
err = box->parse(boxrange);
if (err == Error::Ok) {
*result = std::move(box);
}
boxrange.skip_to_end_of_box();
return err;
}