Error HeifFile::parse_heif_file()

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;
}