<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/formats/mp4/track_run_iterator.h"

#include <algorithm>

#include "media/base/buffers.h"
#include "media/base/stream_parser_buffer.h"
#include "media/formats/mp4/rcheck.h"
#include "media/formats/mp4/sample_to_group_iterator.h"

namespace media {
namespace mp4 {

struct SampleInfo {
  int size;
  int duration;
  int cts_offset;
  bool is_keyframe;
  bool is_random_access_point;
  uint32 cenc_group_description_index;
};

struct TrackRunInfo {
  uint32 track_id;
  std::vector<SampleInfo> samples;
  int64 timescale;
  int64 start_dts;
  int64 sample_start_offset;

  bool is_audio;
  const AudioSampleEntry* audio_description;
  const VideoSampleEntry* video_description;

  int64 aux_info_start_offset;  // Only valid if aux_info_total_size > 0.
  int aux_info_default_size;
  std::vector<uint8> aux_info_sizes;  // Populated if default_size == 0.
  int aux_info_total_size;

  std::vector<CencSampleEncryptionInfoEntry> sample_encryption_info;

  TrackRunInfo();
  ~TrackRunInfo();
};

TrackRunInfo::TrackRunInfo()
    : track_id(0),
      timescale(-1),
      start_dts(-1),
      sample_start_offset(-1),
      is_audio(false),
      aux_info_start_offset(-1),
      aux_info_default_size(-1),
      aux_info_total_size(-1) {
}
TrackRunInfo::~TrackRunInfo() {}

TimeDelta TimeDeltaFromRational(int64 numer, int64 denom) {
  // To avoid overflow, split the following calculation:
  // (numer * base::Time::kMicrosecondsPerSecond) / denom
  // into:
  //  (numer / denom) * base::Time::kMicrosecondsPerSecond +
  // ((numer % denom) * base::Time::kMicrosecondsPerSecond) / denom
  int64 a = numer / denom;
  DCHECK_LE((a > 0 ? a : -a), kint64max / base::Time::kMicrosecondsPerSecond);
  int64 timea_in_us = a * base::Time::kMicrosecondsPerSecond;

  int64 b = numer % denom;
  DCHECK_LE((b > 0 ? b : -b), kint64max / base::Time::kMicrosecondsPerSecond);
  int64 timeb_in_us = (b * base::Time::kMicrosecondsPerSecond) / denom;

  DCHECK((timeb_in_us < 0) || (timea_in_us <= kint64max - timeb_in_us));
  DCHECK((timeb_in_us > 0) || (timea_in_us >= kint64min - timeb_in_us));
  return TimeDelta::FromMicroseconds(timea_in_us + timeb_in_us);
}

TrackRunIterator::TrackRunIterator(const Movie* moov,
                                   const LogCB& log_cb)
    : moov_(moov), log_cb_(log_cb), sample_offset_(0) {
  CHECK(moov);
}

TrackRunIterator::~TrackRunIterator() {}

static void PopulateSampleInfo(const TrackExtends& trex,
                               const TrackFragmentHeader& tfhd,
                               const TrackFragmentRun& trun,
                               const int64 edit_list_offset,
                               const uint32 i,
                               SampleInfo* sample_info,
                               const SampleDependsOn sdtp_sample_depends_on,
                               bool is_sync_sample) {
  if (i < trun.sample_sizes.size()) {
    sample_info->size = trun.sample_sizes[i];
  } else if (tfhd.default_sample_size > 0) {
    sample_info->size = tfhd.default_sample_size;
  } else {
    sample_info->size = trex.default_sample_size;
  }

  if (i < trun.sample_durations.size()) {
    sample_info->duration = trun.sample_durations[i];
  } else if (tfhd.default_sample_duration > 0) {
    sample_info->duration = tfhd.default_sample_duration;
  } else {
    sample_info->duration = trex.default_sample_duration;
  }

  if (i < trun.sample_composition_time_offsets.size()) {
    sample_info->cts_offset = trun.sample_composition_time_offsets[i];
  } else {
    sample_info->cts_offset = 0;
  }
  sample_info->cts_offset += edit_list_offset;

  uint32 flags;
  if (i < trun.sample_flags.size()) {
    flags = trun.sample_flags[i];
  } else if (tfhd.has_default_sample_flags) {
    flags = tfhd.default_sample_flags;
  } else {
    flags = trex.default_sample_flags;
  }

  SampleDependsOn sample_depends_on =
      static_cast<SampleDependsOn>((flags >> 24) & 0x3);

  if (sample_depends_on == kSampleDependsOnUnknown)
    sample_depends_on = sdtp_sample_depends_on;

  // ISO/IEC 14496-12  Section 8.8.3.1 : The flag |sample_is_non_sync_sample|
  // provides the same information as the sync sample table [8.6.2]. When this
  // value is set 0 for a sample, it is the same as if the sample were not in a
  // movie fragment and marked with an entry in the sync sample table
  // (or, if all samples are sync samples, the sync sample table were absent).
  bool sample_is_non_sync_sample = flags & kSampleIsNonSyncSample;
  sample_info->is_random_access_point = !sample_is_non_sync_sample;

  switch (sample_depends_on) {
    case kSampleDependsOnUnknown:
      sample_info->is_keyframe = !sample_is_non_sync_sample;
      break;

    case kSampleDependsOnOthers:
      sample_info->is_keyframe = false;
      break;
<commit_msg>Fix compilation error for https://codereview.chromium.org/282513004<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/formats/mp4/track_run_iterator.h"

#include <algorithm>

#include "media/base/buffers.h"
#include "media/base/stream_parser_buffer.h"
#include "media/formats/mp4/rcheck.h"
#include "media/formats/mp4/sample_to_group_iterator.h"

namespace media {
namespace mp4 {

struct SampleInfo {
  int size;
  int duration;
  int cts_offset;
  bool is_keyframe;
  bool is_random_access_point;
  uint32 cenc_group_description_index;
};

struct TrackRunInfo {
  uint32 track_id;
  std::vector<SampleInfo> samples;
  int64 timescale;
  int64 start_dts;
  int64 sample_start_offset;

  bool is_audio;
  const AudioSampleEntry* audio_description;
  const VideoSampleEntry* video_description;

  int64 aux_info_start_offset;  // Only valid if aux_info_total_size > 0.
  int aux_info_default_size;
  std::vector<uint8> aux_info_sizes;  // Populated if default_size == 0.
  int aux_info_total_size;

  std::vector<CencSampleEncryptionInfoEntry> sample_encryption_info;

  TrackRunInfo();
  ~TrackRunInfo();
};

TrackRunInfo::TrackRunInfo()
    : track_id(0),
      timescale(-1),
      start_dts(-1),
      sample_start_offset(-1),
      is_audio(false),
      aux_info_start_offset(-1),
      aux_info_default_size(-1),
      aux_info_total_size(-1) {
}
TrackRunInfo::~TrackRunInfo() {}

TimeDelta TimeDeltaFromRational(int64 numer, int64 denom) {
  // To avoid overflow, split the following calculation:
  // (numer * base::Time::kMicrosecondsPerSecond) / denom
  // into:
  //  (numer / denom) * base::Time::kMicrosecondsPerSecond +
  // ((numer % denom) * base::Time::kMicrosecondsPerSecond) / denom
  int64 a = numer / denom;
  DCHECK_LE((a > 0 ? a : -a), kint64max / base::Time::kMicrosecondsPerSecond);
  int64 timea_in_us = a * base::Time::kMicrosecondsPerSecond;

  int64 b = numer % denom;
  DCHECK_LE((b > 0 ? b : -b), kint64max / base::Time::kMicrosecondsPerSecond);
  int64 timeb_in_us = (b * base::Time::kMicrosecondsPerSecond) / denom;

  DCHECK((timeb_in_us < 0) || (timea_in_us <= kint64max - timeb_in_us));
  DCHECK((timeb_in_us > 0) || (timea_in_us >= kint64min - timeb_in_us));
  return TimeDelta::FromMicroseconds(timea_in_us + timeb_in_us);
}

TrackRunIterator::TrackRunIterator(const Movie* moov,
                                   const LogCB& log_cb)
    : moov_(moov), log_cb_(log_cb), sample_offset_(0) {
  CHECK(moov);
}

TrackRunIterator::~TrackRunIterator() {}

static void PopulateSampleInfo(const TrackExtends& trex,
                               const TrackFragmentHeader& tfhd,
                               const TrackFragmentRun& trun,
                               const int64 edit_list_offset,
                               const uint32 i,
                               SampleInfo* sample_info,
                               const SampleDependsOn sdtp_sample_depends_on,
                               bool is_sync_sample) {
  if (i < trun.sample_sizes.size()) {
    sample_info->size = trun.sample_sizes[i];
  } else if (tfhd.default_sample_size > 0) {
    sample_info->size = tfhd.default_sample_size;
  } else {
    sample_info->size = trex.default_sample_size;
  }

  if (i < trun.sample_durations.size()) {
    sample_info->duration = trun.sample_durations[i];
  } else if (tfhd.default_sample_duration > 0) {
    sample_info->duration = tfhd.default_sample_duration;
  } else {
    sample_info->duration = trex.default_sample_duration;
  }

  if (i < trun.sample_composition_time_offsets.size()) {
    sample_info->cts_offset = trun.sample_composition_time_offsets[i];
  } else {
    sample_info->cts_offset = 0;
  }
  sample_info->cts_offset += edit_list_offset;

  uint32 flags;
  if (i < trun.sample_flags.size()) {
    flags = trun.sample_flags[i];
  } else if (tfhd.has_default_sample_flags) {
    flags = tfhd.default_sample_flags;
  } else {
    flags = trex.default_sample_flags;
  }

  SampleDependsOn sample_depends_on =
      static_cast<SampleDependsOn>((flags >> 24) & 0x3);

  if (sample_depends_on == kSampleDependsOnUnknown)
    sample_depends_on = sdtp_sample_depends_on;

  // ISO/IEC 14496-12  Section 8.8.3.1 : The negation of |sample_is_sync_sample|
  // provides the same information as the sync sample table [8.6.2]. When
  // |sample_is_sync_sample| is true for a sample, it is the same as if the
  // sample were not in a movie fragment and marked with an entry in the sync
  // sample table (or, if all samples are sync samples, the sync sample table
  // were absent).
  bool sample_is_sync_sample = !(flags & kSampleIsNonSyncSample);
  sample_info->is_random_access_point = sample_is_sync_sample;

  switch (sample_depends_on) {
    case kSampleDependsOnUnknown:
      sample_info->is_keyframe = sample_is_sync_sample;
      break;

    case kSampleDependsOnOthers:
      sample_info->is_keyframe = false;
      break;

{'fraction_non_alphanumeric': 0.10392333033842467, 'fraction_numerical': 0.01737047020065888, 'mean_word_length': 3.413215859030837, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 55, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '236775', 'n_tokens_mistral': 3496, 'n_tokens_neox': 3374, 'n_words': 709}