void
ebml_chapters_converter_c::fix_edition_entry(KaxEditionEntry &eentry)
  const {
  bool atom_found = false;

  KaxEditionUID *euid = nullptr;
  for (auto element : eentry)
    if (dynamic_cast<KaxEditionUID *>(element)) {
      euid = static_cast<KaxEditionUID *>(element);
      if (!is_unique_number(uint64(*euid), UNIQUE_EDITION_IDS)) {
        mxwarn(boost::format(Y("Chapter parser: The EditionUID %1% is not unique and could not be reused. A new one will be created.\n")) % uint64(*euid));
        *static_cast<EbmlUInteger *>(euid) = create_unique_number(UNIQUE_EDITION_IDS);
      }

    } else if (dynamic_cast<KaxChapterAtom *>(element)) {
      atom_found = true;
      fix_atom(static_cast<KaxChapterAtom &>(*element));
    }

  if (!atom_found)
    throw conversion_x{Y("At least one <ChapterAtom> element is needed.")};

  if (!euid) {
    euid                               = new KaxEditionUID;
    *static_cast<EbmlUInteger *>(euid) = create_unique_number(UNIQUE_EDITION_IDS);
    eentry.PushElement(*euid);
  }
}
void
ebml_chapters_converter_c::fix_atom(KaxChapterAtom &atom)
  const {
  for (auto element : atom)
    if (dynamic_cast<KaxChapterAtom *>(element))
      fix_atom(*static_cast<KaxChapterAtom *>(element));

  if (!FindChild<KaxChapterTimeStart>(atom))
    throw conversion_x{Y("<ChapterAtom> is missing the <ChapterTimeStart> child.")};

  if (!FindChild<KaxChapterUID>(atom)) {
    KaxChapterUID *cuid                = new KaxChapterUID;
    *static_cast<EbmlUInteger *>(cuid) = create_unique_number(UNIQUE_CHAPTER_IDS);
    atom.PushElement(*cuid);
  }

  KaxChapterTrack *ctrack = FindChild<KaxChapterTrack>(atom);
  if (ctrack && !FindChild<KaxChapterTrackNumber>(ctrack))
    throw conversion_x{Y("<ChapterTrack> is missing the <ChapterTrackNumber> child.")};

  KaxChapterDisplay *cdisplay = FindChild<KaxChapterDisplay>(atom);
  if (cdisplay)
    fix_display(*cdisplay);
}
void
generic_packetizer_c::set_headers() {
  if (0 < m_connected_to) {
    mxerror(boost::format("generic_packetizer_c::set_headers(): connected_to > 0 (type: %1%). %2%\n") % typeid(*this).name() % BUGMSG);
    return;
  }

  bool found = false;
  size_t idx;
  for (idx = 0; ptzrs_in_header_order.size() > idx; ++idx)
    if (this == ptzrs_in_header_order[idx]) {
      found = true;
      break;
    }

  if (!found)
    ptzrs_in_header_order.push_back(this);

  if (!m_track_entry) {
    m_track_entry    = !g_kax_last_entry ? &GetChild<KaxTrackEntry>(*g_kax_tracks) : &GetNextChild<KaxTrackEntry>(*g_kax_tracks, *g_kax_last_entry);
    g_kax_last_entry = m_track_entry;
    m_track_entry->SetGlobalTimecodeScale((int64_t)g_timecode_scale);
  }

  GetChild<KaxTrackNumber>(m_track_entry).SetValue(m_hserialno);

  if (0 == m_huid)
    m_huid = create_unique_number(UNIQUE_TRACK_IDS);

  GetChild<KaxTrackUID>(m_track_entry).SetValue(m_huid);

  if (-1 != m_htrack_type)
    GetChild<KaxTrackType>(m_track_entry).SetValue(m_htrack_type);

  if (!m_hcodec_id.empty())
    GetChild<KaxCodecID>(m_track_entry).SetValue(m_hcodec_id);

  if (m_hcodec_private)
    GetChild<KaxCodecPrivate>(*m_track_entry).CopyBuffer(static_cast<binary *>(m_hcodec_private->get_buffer()), m_hcodec_private->get_size());

  if (!outputting_webm()) {
    if (-1 != m_htrack_min_cache)
      GetChild<KaxTrackMinCache>(m_track_entry).SetValue(m_htrack_min_cache);

    if (-1 != m_htrack_max_cache)
      GetChild<KaxTrackMaxCache>(m_track_entry).SetValue(m_htrack_max_cache);

    if (-1 != m_htrack_max_add_block_ids)
      GetChild<KaxMaxBlockAdditionID>(m_track_entry).SetValue(m_htrack_max_add_block_ids);
  }

  if (m_timestamp_factory)
    m_htrack_default_duration = (int64_t)m_timestamp_factory->get_default_duration(m_htrack_default_duration);
  if (-1.0 != m_htrack_default_duration)
    GetChild<KaxTrackDefaultDuration>(m_track_entry).SetValue(m_htrack_default_duration);

  idx = TRACK_TYPE_TO_DEFTRACK_TYPE(m_htrack_type);

  if (boost::logic::indeterminate(m_ti.m_default_track))
    set_as_default_track(idx, DEFAULT_TRACK_PRIORITY_FROM_TYPE);
  else if (m_ti.m_default_track)
    set_as_default_track(idx, DEFAULT_TRACK_PRIORITY_CMDLINE);
  else if (g_default_tracks[idx] == m_hserialno)
    g_default_tracks[idx] = 0;

  GetChild<KaxTrackLanguage>(m_track_entry).SetValue(m_ti.m_language != "" ? m_ti.m_language : g_default_language.c_str());

  if (!m_ti.m_track_name.empty())
    GetChild<KaxTrackName>(m_track_entry).SetValueUTF8(m_ti.m_track_name);

  if (!boost::logic::indeterminate(m_ti.m_forced_track))
    GetChild<KaxTrackFlagForced>(m_track_entry).SetValue(m_ti.m_forced_track ? 1 : 0);

  if (!boost::logic::indeterminate(m_ti.m_enabled_track))
    GetChild<KaxTrackFlagEnabled>(m_track_entry).SetValue(m_ti.m_enabled_track ? 1 : 0);

  if (m_seek_pre_roll.valid())
    GetChild<KaxSeekPreRoll>(m_track_entry).SetValue(m_seek_pre_roll.to_ns());

  if (m_codec_delay.valid())
    GetChild<KaxCodecDelay>(m_track_entry).SetValue(m_codec_delay.to_ns());

  if (track_video == m_htrack_type) {
    KaxTrackVideo &video = GetChild<KaxTrackVideo>(m_track_entry);

    if (-1 != m_hvideo_interlaced_flag)
      GetChild<KaxVideoFlagInterlaced>(GetChild<KaxTrackVideo>(*m_track_entry)).SetValue(m_hvideo_interlaced_flag);

    if ((-1 != m_hvideo_pixel_height) && (-1 != m_hvideo_pixel_width)) {
      if ((-1 == m_hvideo_display_width) || (-1 == m_hvideo_display_height) || m_ti.m_aspect_ratio_given || m_ti.m_display_dimensions_given) {
        if (m_ti.m_display_dimensions_given) {
          m_hvideo_display_width  = m_ti.m_display_width;
          m_hvideo_display_height = m_ti.m_display_height;

        } else {
          if (!m_ti.m_aspect_ratio_given)
            m_ti.m_aspect_ratio = (float)m_hvideo_pixel_width                       / (float)m_hvideo_pixel_height;

          else if (m_ti.m_aspect_ratio_is_factor)
            m_ti.m_aspect_ratio = (float)m_hvideo_pixel_width * m_ti.m_aspect_ratio / (float)m_hvideo_pixel_height;

          if (m_ti.m_aspect_ratio > ((float)m_hvideo_pixel_width / (float)m_hvideo_pixel_height)) {
            m_hvideo_display_width  = std::llround(m_hvideo_pixel_height * m_ti.m_aspect_ratio);
            m_hvideo_display_height = m_hvideo_pixel_height;

          } else {
            m_hvideo_display_width  = m_hvideo_pixel_width;
            m_hvideo_display_height = std::llround(m_hvideo_pixel_width / m_ti.m_aspect_ratio);
          }
        }
      }

      GetChild<KaxVideoPixelWidth   >(video).SetValue(m_hvideo_pixel_width);
      GetChild<KaxVideoPixelHeight  >(video).SetValue(m_hvideo_pixel_height);

      GetChild<KaxVideoDisplayWidth >(video).SetValue(m_hvideo_display_width);
      GetChild<KaxVideoDisplayHeight>(video).SetValue(m_hvideo_display_height);

      GetChild<KaxVideoDisplayWidth >(video).SetDefaultSize(4);
      GetChild<KaxVideoDisplayHeight>(video).SetDefaultSize(4);

      if (m_ti.m_pixel_cropping) {
        auto crop = m_ti.m_pixel_cropping.get();
        GetChild<KaxVideoPixelCropLeft  >(video).SetValue(crop.left);
        GetChild<KaxVideoPixelCropTop   >(video).SetValue(crop.top);
        GetChild<KaxVideoPixelCropRight >(video).SetValue(crop.right);
        GetChild<KaxVideoPixelCropBottom>(video).SetValue(crop.bottom);
      }

      if (m_ti.m_stereo_mode && (stereo_mode_c::unspecified != m_ti.m_stereo_mode.get()))
        set_video_stereo_mode_impl(video, m_ti.m_stereo_mode.get());
    }

  } else if (track_audio == m_htrack_type) {
    KaxTrackAudio &audio = GetChild<KaxTrackAudio>(m_track_entry);

    if (-1   != m_haudio_sampling_freq)
      GetChild<KaxAudioSamplingFreq>(audio).SetValue(m_haudio_sampling_freq);

    if (-1.0 != m_haudio_output_sampling_freq)
      GetChild<KaxAudioOutputSamplingFreq>(audio).SetValue(m_haudio_output_sampling_freq);

    if (-1   != m_haudio_channels)
      GetChild<KaxAudioChannels>(audio).SetValue(m_haudio_channels);

    if (-1   != m_haudio_bit_depth)
      GetChild<KaxAudioBitDepth>(audio).SetValue(m_haudio_bit_depth);

  } else if (track_buttons == m_htrack_type) {
    if ((-1 != m_hvideo_pixel_height) && (-1 != m_hvideo_pixel_width)) {
      KaxTrackVideo &video = GetChild<KaxTrackVideo>(m_track_entry);

      GetChild<KaxVideoPixelWidth >(video).SetValue(m_hvideo_pixel_width);
      GetChild<KaxVideoPixelHeight>(video).SetValue(m_hvideo_pixel_height);
    }

  }

  if ((COMPRESSION_UNSPECIFIED != m_hcompression) && (COMPRESSION_NONE != m_hcompression)) {
    KaxContentEncoding &c_encoding = GetChild<KaxContentEncoding>(GetChild<KaxContentEncodings>(m_track_entry));

    GetChild<KaxContentEncodingOrder>(c_encoding).SetValue(0); // First modification.
    GetChild<KaxContentEncodingType >(c_encoding).SetValue(0); // It's a compression.
    GetChild<KaxContentEncodingScope>(c_encoding).SetValue(1); // Only the frame contents have been compresed.

    m_compressor = compressor_c::create(m_hcompression);
    m_compressor->set_track_headers(c_encoding);
  }

  if (g_no_lacing)
    m_track_entry->EnableLacing(false);

  set_tag_track_uid();
  if (m_ti.m_tags) {
    while (m_ti.m_tags->ListSize() != 0) {
      KaxTag *tag = (KaxTag *)(*m_ti.m_tags)[0];
      add_tags(tag);
      m_ti.m_tags->Remove(0);
    }
  }
}