Exemplo n.º 1
0
static stts_t* stts_create(mp4_context_t const* mp4_context,
													 samples_t const* first, samples_t const* last)
{
	unsigned int entries = 0;
	unsigned int samples = last - first;
	stts_t* stts = stts_init();
	stts->table_ = (stts_table_t*) realloc(stts->table_, samples * sizeof(stts_table_t));

	while(first != last)
	{
		unsigned int sample_count = 1;
		unsigned int sample_duration =
			(unsigned int)(first[1].pts_ - first[0].pts_);
		while(++first != last)
		{
			if((first[1].pts_ - first[0].pts_) != sample_duration)
				break;
			++sample_count;
		}

		stts->table_[entries].sample_count_ = sample_count;
		stts->table_[entries].sample_duration_ = sample_duration;
		++entries;
	}
	stts->entries_ = entries;

	if(stts_get_samples(stts) != samples)
	{
		MP4_WARNING("ERROR: stts_get_samples=%d, should be %d\n",
			stts_get_samples(stts), samples);
	}
	return stts;
}
static void trak_update_index(struct mp4_context_t const* mp4_context,
                              struct trak_t* trak,
                              unsigned int start, unsigned int end)
{
  // write samples [start,end>

  // stts = [entries * [sample_count, sample_duration]
  {
    struct stts_t* stts = trak->mdia_->minf_->stbl_->stts_;

    unsigned int entries = 0;
    unsigned int s = start;

    while(s != end)
    {
      unsigned int sample_count = 1;
      unsigned int sample_duration =
        (unsigned int)(trak->samples_[s + 1].pts_ - trak->samples_[s].pts_);
      while(++s != end)
      {
        if((trak->samples_[s + 1].pts_ - trak->samples_[s].pts_) != sample_duration)
          break;
        ++sample_count;
      }
// TODO: entries may be empty when we read a fragmented movie file. use
// output_mov() instead.
//      if(entries + 1 > stts->entries_)
//      {
//        stts->table_ = (stts_table_t*)
//          realloc(stts->table_, (entries + 1) * sizeof(stts_table_t));
//      }

      stts->table_[entries].sample_count_ = sample_count;
      stts->table_[entries].sample_duration_ = sample_duration;
      ++entries;
    }
    stts->entries_ = entries;

    if(stts_get_samples(stts) != end - start)
    {
      MP4_WARNING("ERROR: stts_get_samples=%d, should be %d\n",
             stts_get_samples(stts), end - start);
    }
  }

  // ctts = [entries * [sample_count, sample_offset]
  {
    struct ctts_t* ctts = trak->mdia_->minf_->stbl_->ctts_;
    if(ctts)
    {
      unsigned int entries = 0;
      unsigned int s = start;

      while(s != end)
      {
        unsigned int sample_count = 1;
        unsigned int sample_offset = trak->samples_[s].cto_;
        while(++s != end)
        {
          if(trak->samples_[s].cto_ != sample_offset)
            break;
          ++sample_count;
        }
        // write entry
        ctts->table_[entries].sample_count_ = sample_count;
        ctts->table_[entries].sample_offset_ = sample_offset;
        ++entries;
      }
      ctts->entries_ = entries;
      if(ctts_get_samples(ctts) != end - start)
      {
        MP4_WARNING("ERROR: ctts_get_samples=%d, should be %d\n",
               ctts_get_samples(ctts), end - start);
      }
    }
  }

  // process chunkmap:
  {
    struct stsc_t* stsc = trak->mdia_->minf_->stbl_->stsc_;
    if(stsc != NULL)
    {
      unsigned int i;

      for(i = 0; i != trak->chunks_size_; ++i)
      {
        if(trak->chunks_[i].sample_ + trak->chunks_[i].size_ > start)
          break;
      }

      {
        unsigned int stsc_entries = 0;
        unsigned int chunk_start = i;
        unsigned int chunk_end;
        // problem.mp4: reported by Jin-seok Lee. Second track contains no samples
        if(trak->chunks_size_ != 0)
        {
          unsigned int samples =
            trak->chunks_[i].sample_ + trak->chunks_[i].size_ - start;
          unsigned int id = trak->chunks_[i].id_;

          // write entry [chunk,samples,id]
          stsc->table_[stsc_entries].chunk_ = 0;
          stsc->table_[stsc_entries].samples_ = samples;
          stsc->table_[stsc_entries].id_ = id;
          ++stsc_entries;

          if(i != trak->chunks_size_)
          {
            for(i += 1; i != trak->chunks_size_; ++i)
            {
              unsigned int next_size = trak->chunks_[i].size_;
              if(trak->chunks_[i].sample_ + trak->chunks_[i].size_ > end)
              {
                next_size = end - trak->chunks_[i].sample_;
              }

              if(next_size != samples)
              {
                samples = next_size;
                id = trak->chunks_[i].id_;
                stsc->table_[stsc_entries].chunk_ = i - chunk_start;
                stsc->table_[stsc_entries].samples_ = samples;
                stsc->table_[stsc_entries].id_ = id;
                ++stsc_entries;
              }

              if(trak->chunks_[i].sample_ + next_size == end)
              {
                break;
              }
            }
          }
        }
        chunk_end = i + 1;
        stsc->entries_ = stsc_entries;

        {
          struct stco_t* stco = trak->mdia_->minf_->stbl_->stco_;
          unsigned int entries = 0;
          for(i = chunk_start; i != chunk_end; ++i)
          {
            stco->chunk_offsets_[entries] = stco->chunk_offsets_[i];
            ++entries;
          }
          stco->entries_ = entries;

          // patch first chunk with correct sample offset
          stco->chunk_offsets_[0] = (uint32_t)trak->samples_[start].pos_;
        }
      }
    }
  }

  // process sync samples:
  if(trak->mdia_->minf_->stbl_->stss_)
  {
    struct stss_t* stss = trak->mdia_->minf_->stbl_->stss_;
    unsigned int entries = 0;
    unsigned int stss_start;
    unsigned int i;

    for(i = 0; i != stss->entries_; ++i)
    {
      if(stss->sample_numbers_[i] >= start + 1)
        break;
    }
    stss_start = i;
    for(; i != stss->entries_; ++i)
    {
      unsigned int sync_sample = stss->sample_numbers_[i];
      if(sync_sample >= end + 1)
        break;
      stss->sample_numbers_[entries] = sync_sample - start;
      ++entries;
    }
    stss->entries_ = entries;
  }

  // process sample sizes
  {
    struct stsz_t* stsz = trak->mdia_->minf_->stbl_->stsz_;
    if(stsz != NULL)
    {
      if(stsz->sample_size_ == 0)
      {
        unsigned int entries = 0;
        unsigned int i;
        for(i = start; i != end; ++i)
        {
          stsz->sample_sizes_[entries] = stsz->sample_sizes_[i];
          ++entries;
        }
      }
      stsz->entries_ = end - start;
    }
  }
}