in libheif/file.cc [351:590]
Error HeifFile::parse_heif_file(BitstreamRange& range)
{
// --- read all top-level boxes
for (;;) {
std::shared_ptr<Box> box;
Error error = Box::read(range, &box);
if (range.error() || range.eof()) {
break;
}
// When an EOF error is returned, this is not really a fatal exception,
// but simply the indication that we reached the end of the file.
// TODO: this design should be cleaned up
if (error.error_code == heif_error_Invalid_input && error.sub_error_code == heif_suberror_End_of_data) {
break;
}
if (error != Error::Ok) {
return error;
}
m_top_level_boxes.push_back(box);
// extract relevant boxes (ftyp, meta)
if (box->get_short_type() == fourcc("meta")) {
m_meta_box = std::dynamic_pointer_cast<Box_meta>(box);
}
if (box->get_short_type() == fourcc("ftyp")) {
m_ftyp_box = std::dynamic_pointer_cast<Box_ftyp>(box);
}
if (box->get_short_type() == fourcc("moov")) {
m_moov_box = std::dynamic_pointer_cast<Box_moov>(box);
}
}
// --- check whether this is a HEIF file and its structural format
if (!m_ftyp_box) {
return Error(heif_error_Invalid_input,
heif_suberror_No_ftyp_box);
}
if (
!m_ftyp_box->has_compatible_brand(fourcc("hevc")) &&
!m_ftyp_box->has_compatible_brand(fourcc("hevx")) &&
!m_ftyp_box->has_compatible_brand(fourcc("msf1")) &&
!m_ftyp_box->has_compatible_brand(heif_brand2_heic) &&
!m_ftyp_box->has_compatible_brand(heif_brand2_heix) &&
!m_ftyp_box->has_compatible_brand(heif_brand2_mif1) &&
!m_ftyp_box->has_compatible_brand(heif_brand2_avif) &&
!m_ftyp_box->has_compatible_brand(heif_brand2_1pic) &&
!m_ftyp_box->has_compatible_brand(heif_brand2_jpeg)) {
std::stringstream sstr;
sstr << "File does not include any supported brands.\n";
return Error(heif_error_Unsupported_filetype,
heif_suberror_Unspecified,
sstr.str());
}
if((m_ftyp_box->has_compatible_brand(fourcc("hevc"))||m_ftyp_box->has_compatible_brand(fourcc("hevx"))) && m_moov_box)
{
// if(m_tkhd_box && (m_tkhd_box->get_flags()&0x01))
set_moov_flag(true);
// else
// set_moov_flag(false);
}
else
{
set_moov_flag(false);
}
if (!m_meta_box) {
return Error(heif_error_Invalid_input,
heif_suberror_No_meta_box);
}
m_hdlr_box = std::dynamic_pointer_cast<Box_hdlr>(m_meta_box->get_child_box(fourcc("hdlr")));
if (STRICT_PARSING && !m_hdlr_box) {
return Error(heif_error_Invalid_input,
heif_suberror_No_hdlr_box);
}
if (m_hdlr_box &&
m_hdlr_box->get_handler_type() != fourcc("pict")) {
return Error(heif_error_Invalid_input,
heif_suberror_No_pict_handler);
}
// --- find mandatory boxes needed for image decoding
m_pitm_box = std::dynamic_pointer_cast<Box_pitm>(m_meta_box->get_child_box(fourcc("pitm")));
if (!m_pitm_box) {
return Error(heif_error_Invalid_input,
heif_suberror_No_pitm_box);
}
m_iprp_box = std::dynamic_pointer_cast<Box_iprp>(m_meta_box->get_child_box(fourcc("iprp")));
if (!m_iprp_box) {
return Error(heif_error_Invalid_input,
heif_suberror_No_iprp_box);
}
m_ipco_box = std::dynamic_pointer_cast<Box_ipco>(m_iprp_box->get_child_box(fourcc("ipco")));
if (!m_ipco_box) {
return Error(heif_error_Invalid_input,
heif_suberror_No_ipco_box);
}
auto ipma_boxes = m_iprp_box->get_typed_child_boxes<Box_ipma>(fourcc("ipma"));
if (ipma_boxes.empty()) {
return Error(heif_error_Invalid_input,
heif_suberror_No_ipma_box);
}
for (size_t i=1;i<ipma_boxes.size();i++) {
ipma_boxes[0]->insert_entries_from_other_ipma_box(*ipma_boxes[i]);
}
m_ipma_box = ipma_boxes[0];
m_iloc_box = std::dynamic_pointer_cast<Box_iloc>(m_meta_box->get_child_box(fourcc("iloc")));
if (!m_iloc_box) {
return Error(heif_error_Invalid_input,
heif_suberror_No_iloc_box);
}
m_idat_box = std::dynamic_pointer_cast<Box_idat>(m_meta_box->get_child_box(fourcc("idat")));
m_iref_box = std::dynamic_pointer_cast<Box_iref>(m_meta_box->get_child_box(fourcc("iref")));
if (m_iref_box) {
Error error = check_for_ref_cycle(get_primary_image_ID(), m_iref_box);
if (error) {
return error;
}
}
m_iinf_box = std::dynamic_pointer_cast<Box_iinf>(m_meta_box->get_child_box(fourcc("iinf")));
if (!m_iinf_box) {
return Error(heif_error_Invalid_input,
heif_suberror_No_iinf_box);
}
if(m_moov_box)
{
m_mvhd_box = std::dynamic_pointer_cast<Box_mvhd>(m_moov_box->get_child_box(fourcc("mvhd")));
if (!m_mvhd_box) {
return Error(heif_error_Invalid_input, heif_suberror_No_mvhd_box);
}
m_trak_box = std::dynamic_pointer_cast<Box_trak>(m_moov_box->get_child_box(fourcc("trak")));
if (!m_mvhd_box) {
return Error(heif_error_Invalid_input, heif_suberror_No_mvhd_box);
}
m_tkhd_box = std::dynamic_pointer_cast<Box_tkhd>(m_trak_box->get_child_box(fourcc("tkhd")));
if (!m_tkhd_box) {
return Error(heif_error_Invalid_input, heif_suberror_No_tkhd_box);
}
m_mdia_box = std::dynamic_pointer_cast<Box_mdia>(m_trak_box->get_child_box(fourcc("mdia")));
if (!m_mdia_box) {
return Error(heif_error_Invalid_input, heif_suberror_No_mdia_box);
}
m_mdhd_box = std::dynamic_pointer_cast<Box_mdhd>(m_mdia_box->get_child_box(fourcc("mdhd")));
if (!m_mdhd_box) {
return Error(heif_error_Invalid_input, heif_suberror_No_mdhd_box);
}
m_minf_box = std::dynamic_pointer_cast<Box_minf>(m_mdia_box->get_child_box(fourcc("minf")));
if (!m_minf_box) {
return Error(heif_error_Invalid_input, heif_suberror_No_minf_box);
}
m_vmhd_box = std::dynamic_pointer_cast<Box_vmhd>(m_minf_box->get_child_box(fourcc("vmhd")));
if (!m_vmhd_box) {
return Error(heif_error_Invalid_input, heif_suberror_No_vmhd_box);
}
m_stbl_box = std::dynamic_pointer_cast<Box_stbl>(m_minf_box->get_child_box(fourcc("stbl")));
if (!m_stbl_box) {
return Error(heif_error_Invalid_input, heif_suberror_No_stbl_box);
}
m_stsd_box = std::dynamic_pointer_cast<Box_stsd>(m_stbl_box->get_child_box(fourcc("stsd")));
if (!m_stsd_box) {
return Error(heif_error_Invalid_input, heif_suberror_No_stbl_box);
}
m_hvc1_box = std::dynamic_pointer_cast<Box_hvc1>(m_stsd_box->get_child_box(fourcc("hvc1")));
if (!m_hvc1_box) {
return Error(heif_error_Invalid_input, heif_suberror_No_hvc1_box);
}
m_hvcC_box = std::dynamic_pointer_cast<Box_hvcC>(m_hvc1_box->get_child_box(fourcc("hvcC")));
if (!m_hvcC_box) {
return Error(heif_error_Invalid_input, heif_suberror_No_hvcC_moov_box);
}
m_ccst_box = std::dynamic_pointer_cast<Box_ccst>(m_hvc1_box->get_child_box(fourcc("ccst")));
if (!m_ccst_box) {
return Error(heif_error_Invalid_input, heif_suberror_No_ccst_box);
}
m_stsz_box = std::dynamic_pointer_cast<Box_stsz>(m_stbl_box->get_child_box(fourcc("stsz")));
if (!m_stsz_box) {
return Error(heif_error_Invalid_input, heif_suberror_No_stsz_box);
}
m_stts_box = std::dynamic_pointer_cast<Box_stts>(m_stbl_box->get_child_box(fourcc("stts")));
if (!m_stts_box) {
return Error(heif_error_Invalid_input, heif_suberror_No_stts_box);
}
m_stsc_box = std::dynamic_pointer_cast<Box_stsc>(m_stbl_box->get_child_box(fourcc("stsc")));
if (!m_stsc_box) {
return Error(heif_error_Invalid_input, heif_suberror_No_stsc_box);
}
m_stco_box = std::dynamic_pointer_cast<Box_stco>(m_stbl_box->get_child_box(fourcc("stco")));
if (!m_stco_box) {
return Error(heif_error_Invalid_input, heif_suberror_No_stco_box);
}
m_stss_box = std::dynamic_pointer_cast<Box_stss>(m_stbl_box->get_child_box(fourcc("stss")));
if (!m_stss_box) {
return Error(heif_error_Invalid_input, heif_suberror_No_stss_box);
}
}
// --- build list of images
std::vector<std::shared_ptr<Box>> infe_boxes = m_iinf_box->get_child_boxes(fourcc("infe"));
for (auto& box : infe_boxes) {
std::shared_ptr<Box_infe> infe_box = std::dynamic_pointer_cast<Box_infe>(box);
if (!infe_box) {
return Error(heif_error_Invalid_input,
heif_suberror_No_infe_box);
}
m_infe_boxes.insert(std::make_pair(infe_box->get_item_ID(), infe_box));
}
return Error::Ok;
}