func: static int ogg_buffer_data(AVFormatContext *s, AVStream *st,
  
                             uint8_t *data, unsigned size, int64_t granule,
  
                             int header)
  
  {
  
      OGGStreamContext *oggstream = st->priv_data;
  
      OGGContext *ogg = s->priv_data;
  
      int total_segments = size / 255 + 1;
  
      uint8_t *p = data;
  
      int i, segments, len, flush = 0;
  
  
  
      // Handles VFR by flushing page because this frame needs to have a timestamp
  
      // For theora, keyframes also need to have a timestamp to correctly mark
  
      // them as such, otherwise seeking will not work correctly at the very
  
      // least with old libogg versions.
  
      // Do not try to flush header packets though, that will create broken files.
  
      if (st->codec->codec_id == AV_CODEC_ID_THEORA && !header &&
  
          (ogg_granule_to_timestamp(oggstream, granule) >
  
           ogg_granule_to_timestamp(oggstream, oggstream->last_granule) + 1 ||
  
           ogg_key_granule(oggstream, granule))) {
  
          if (oggstream->page.granule != -1)
  
              ogg_buffer_page(s, oggstream);
  
          flush = 1;
  
      }
  
  
  
      // avoid a continued page
  
      if (!header && oggstream->page.size > 0 &&
  
          MAX_PAGE_SIZE - oggstream->page.size < size) {
  
          ogg_buffer_page(s, oggstream);
  
      }
  
  
  
      for (i = 0; i < total_segments; ) {
  
          OGGPage *page = &oggstream->page;
  
  
  
          segments = FFMIN(total_segments - i, 255 - page->segments_count);
  
  
  
          if (i && !page->segments_count)
  
              page->flags |= 1; // continued packet
  
  
  
          memset(page->segments+page->segments_count, 255, segments - 1);
  
          page->segments_count += segments - 1;
  
  
  
          len = FFMIN(size, segments*255);
  
          page->segments[page->segments_count++] = len - (segments-1)*255;
  
          memcpy(page->data+page->size, p, len);
  
          p += len;
  
          size -= len;
  
          i += segments;
  
          page->size += len;
  
  
  
          if (i == total_segments)
  
              page->granule = granule;
  
  
  
          if (!header) {
  
              AVStream *st = s->streams[page->stream_index];
  
  
  
              int64_t start = av_rescale_q(page->start_granule, st->time_base,
  
                                           AV_TIME_BASE_Q);
  
              int64_t next  = av_rescale_q(page->granule, st->time_base,
  
                                           AV_TIME_BASE_Q);
  
  
  
              if (page->segments_count == 255 ||
  
                  (ogg->pref_size     > 0 && page->size   >= ogg->pref_size) ||
  
                  (ogg->pref_duration > 0 && next - start >= ogg->pref_duration)) {
  
                  ogg_buffer_page(s, oggstream);
  
              }
  
          }
  
      }
  
  
  
      if (flush && oggstream->page.granule != -1)
  
          ogg_buffer_page(s, oggstream);
  
  
  
      return 0;
  
  }
  