Exemple #1
0
int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
  unsigned char *header=og->header;
  unsigned char *body=og->body;
  long           bodysize=og->body_len;
  int            segptr=0;

  int version=ogg_page_version(og);
  int continued=ogg_page_continued(og);
  int bos=ogg_page_bos(og);
  int eos=ogg_page_eos(og);
  ogg_int64_t granulepos=ogg_page_granulepos(og);
  int serialno=ogg_page_serialno(og);
  long pageno=ogg_page_pageno(og);
  int segments=header[26];
  
  /* clean up 'returned data' */
  {
    long lr=os->lacing_returned;
    long br=os->body_returned;

    /* body data */
    if(br){
      os->body_fill-=br;
      if(os->body_fill)
	memmove(os->body_data,os->body_data+br,os->body_fill);
      os->body_returned=0;
    }

    if(lr){
      /* segment table */
      if(os->lacing_fill-lr){
	memmove(os->lacing_vals,os->lacing_vals+lr,
		(os->lacing_fill-lr)*sizeof(*os->lacing_vals));
	memmove(os->granule_vals,os->granule_vals+lr,
		(os->lacing_fill-lr)*sizeof(*os->granule_vals));
      }
      os->lacing_fill-=lr;
      os->lacing_packet-=lr;
      os->lacing_returned=0;
    }
  }

  /* check the serial number */
  if(serialno!=os->serialno)return(-1);
  if(version>0)return(-1);

  _os_lacing_expand(os,segments+1);

  /* are we in sequence? */
  if(pageno!=os->pageno){
    int i;

    /* unroll previous partial packet (if any) */
    for(i=os->lacing_packet;i<os->lacing_fill;i++)
      os->body_fill-=os->lacing_vals[i]&0xff;
    os->lacing_fill=os->lacing_packet;

    /* make a note of dropped data in segment table */
    if(os->pageno!=-1){
      os->lacing_vals[os->lacing_fill++]=0x400;
      os->lacing_packet++;
    }
  }

  /* are we a 'continued packet' page?  If so, we may need to skip
     some segments */
  if(continued){
    if(os->lacing_fill<1 || 
       os->lacing_vals[os->lacing_fill-1]==0x400){
      bos=0;
      for(;segptr<segments;segptr++){
	int val=header[27+segptr];
	body+=val;
	bodysize-=val;
	if(val<255){
	  segptr++;
	  break;
	}
      }
    }
  }
  
  if(bodysize){
    _os_body_expand(os,bodysize);
    memcpy(os->body_data+os->body_fill,body,bodysize);
    os->body_fill+=bodysize;
  }

  {
    int saved=-1;
    while(segptr<segments){
      int val=header[27+segptr];
      os->lacing_vals[os->lacing_fill]=val;
      os->granule_vals[os->lacing_fill]=-1;
      
      if(bos){
	os->lacing_vals[os->lacing_fill]|=0x100;
	bos=0;
      }
      
      if(val<255)saved=os->lacing_fill;
      
      os->lacing_fill++;
      segptr++;
      
      if(val<255)os->lacing_packet=os->lacing_fill;
    }
  
    /* set the granulepos on the last granuleval of the last full packet */
    if(saved!=-1){
      os->granule_vals[saved]=granulepos;
    }

  }

  if(eos){
    os->e_o_s=1;
    if(os->lacing_fill>0)
      os->lacing_vals[os->lacing_fill-1]|=0x200;
  }

  os->pageno=pageno+1;

  return(0);
}
Exemple #2
0
int main () {
  ogg_sync_state   oy; /* sync and verify incoming physical bitstream */
  ogg_stream_state os; /* take physical pages, weld into a logical
                          stream of packets */
  ogg_page         og; /* one Ogg bitstream page. Vorbis packets are inside */
  ogg_packet       op; /* one raw packet of data for decode */

  struct stream *st = NULL;

  int r;
  char *buffer;
  int  bytes;
  int eos = 0;
  int i;
  int bufferSize = 4096;

  r = ogg_sync_init(&oy); /* Now we can read pages */
  assert(r == 0);

  while (1) { /* we repeat if the bitstream is chained */

    /* submit a 4k block to the libogg sync layer */
    buffer = ogg_sync_buffer(&oy, bufferSize);
    bytes = fread(buffer, 1, bufferSize, stdin);
    if (bytes == 0) {
      fprintf(stderr, "Got stdin EOF.\n");
      r = 0; break;
    }

    r = ogg_sync_wrote(&oy, bytes);
    assert(r == 0);

    /* Get the first page. */
    r = ogg_sync_pageout(&oy, &og);
    if (r == 0) {
      fprintf(stderr, "Need more data.\n");
      continue;
    } else if (r < 1) {
      /* have we simply run out of data?  If so, we're done. */
      if (bytes < bufferSize) break;

      /* error case.  Must not be Vorbis data */
      fprintf(stderr, "Input does not appear to be an Ogg bitstream.\n");
      r = 1; break;
    }
    assert(r == 1);

    /* Get the serial number and set up the rest of decode. */
    /* serialno first; use it to set up a logical stream */
    int serialno = ogg_page_serialno(&og);
    int packets = ogg_page_packets(&og);
    fprintf(stderr, "version: %d\n", ogg_page_version(&og));
    fprintf(stderr, "continued: %d\n", ogg_page_continued(&og));
    fprintf(stderr, "pageno: %ld\n", ogg_page_pageno(&og));
    fprintf(stderr, "serialno: %d\n", serialno);
    fprintf(stderr, "packets: %d\n", packets);
    fprintf(stderr, "granulepos: %lld\n", ogg_page_granulepos(&og));
    fprintf(stderr, "eos: %d\n", ogg_page_eos(&og));
    fprintf(stderr, "bos: %d\n", ogg_page_bos(&og));


    /* we need to get the correct "ogg_stream_state" struct based on the serialno */
    struct stream *s = st;
    while (1) {
      if (s == NULL) {
        fprintf(stderr, "creating struct stream for %d\n", serialno);
        s = malloc(sizeof(struct stream));
        s->next = NULL;
        s->serialno = serialno;
        ogg_stream_init(&s->os, serialno);
        if (st == NULL) {
          st = s;
        } else {
          /* have to set "s" to the last element of the "st" linked list */
          struct stream *t = st;
          while (1) {
            if (t->next == NULL) {
              t->next = s;
              break;
            } else {
              t = t->next;
            }
          }
        }
        break;
      }
      if (s->serialno == serialno) {
        break;
      }
      s = s->next;
    }
    assert(s->serialno == serialno);
    fprintf(stderr, "using struct stream %d\n", s->serialno);
    /* holy shit that sucked... */


    if (ogg_stream_pagein(&s->os, &og) < 0) {
      /* error; stream version mismatch perhaps */
      fprintf(stderr, "Error reading page of Ogg bitstream data.\n");
      r = 1; break;
    }

    /* iterate though the "packets" in the page */
    for (i=0; i<packets; i++) {
      fprintf(stderr, "  Reading packet %d.\n", i);
      r = ogg_stream_packetout(&s->os, &op);
      fprintf(stderr, "  Reading packet result %d.\n", r);
      if (r != 1) {
        /* no page? must not be vorbis */
        fprintf(stderr, "  Error reading packet.\n");
        r = 1; break;
      }

      /**
       * At this point, you'd pass the raw packet data to the vorbis decoder or
       * whatever your destination is....
       */
      fprintf(stderr, "    bytes: %ld\n", op.bytes);
      fprintf(stderr, "    b_o_s: %ld\n", op.b_o_s);
      fprintf(stderr, "    e_o_s: %ld\n", op.e_o_s);
      fprintf(stderr, "    granulepos: %lld\n", op.granulepos);
      fprintf(stderr, "    packetno: %lld\n", op.packetno);
    }

    fprintf(stderr, "\n");
  }

  /* OK, clean up the framer */
  ogg_sync_clear(&oy);

  fprintf(stderr,"\nDone.\n");
  return r;
}
Exemple #3
0
// the main page reading hook (stream friendly)
ssize_t
OggReader::ReadPage(bool first_page)
{
//	TRACE("OggReader::ReadPage\n");
	int read_size = (first_page ? 4096 : 4*B_PAGE_SIZE);
	BAutolock autolock(fSyncLock);
	ogg_page page;
retry:
	int result = ogg_sync_pageout(&fSync, &page); // first read leftovers
	while (result == 0) {
		char * buffer = ogg_sync_buffer(&fSync, read_size);
		ssize_t bytes = Source()->Read(buffer, read_size);
		if (bytes == 0) {
			TRACE("OggReader::GetPage: Read: no data\n");
			return B_LAST_BUFFER_ERROR;
		}
		if (bytes < 0) {
			TRACE("OggReader::GetPage: Read: error\n");
			return bytes;
		}
		if (ogg_sync_wrote(&fSync, bytes) != 0) {
			TRACE("OggReader::GetPage: ogg_sync_wrote failed?: error\n");
			return B_ERROR;
		}
		result = ogg_sync_pageout(&fSync, &page);
		if (first_page && (result != 1)) {
			TRACE("OggReader::GetPage: short first page not found: error\n");
			return B_ERROR;
		}
	}
	if (result == -1) {
		TRACE("OggReader::GetPage: ogg_sync_pageout: not synced: error\n");
		return B_ERROR;
	}
	if (ogg_page_version(&page) != 0) {
		TRACE("OggReader::GetPage: ogg_page_version: error in page encoding: error\n");
		return B_ERROR;
	}
	long serialno = ogg_page_serialno(&page);
	bool new_serialno = fTracks.find(serialno) == fTracks.end();
	if (new_serialno) {
		// this is an unknown serialno
		if (ogg_page_bos(&page) == 0) {
			TRACE("OggReader::GetPage: non-bos page with unknown serialno\n");
#ifdef STRICT_OGG
			return B_ERROR;
#else
			// silently discard non-bos packets with unknown serialno
			goto retry;
#endif
		}
#ifdef STRICT_OGG
		if (ogg_page_continued(&page) != 0) {
			TRACE("oggReader::GetPage: ogg_page_continued: continued page: not ogg\n");
			return B_ERROR;
		}
#endif //STRICT_OGG
		// this is a beginning of stream page
		ogg_stream_state stream;
		if (ogg_stream_init(&stream, serialno) != 0) {
			TRACE("oggReader::GetPage: ogg_stream_init failed?: error\n");
			return B_ERROR;
		}
		if (ogg_stream_pagein(&stream, &page) != 0) {
			TRACE("oggReader::GetPage: ogg_stream_pagein: failed: error\n");
			return B_ERROR;
		}
		ogg_packet packet;
		if (ogg_stream_packetout(&stream, &packet) != 1) {
#ifdef STRICT_OGG
			return B_ERROR;
#endif //STRICT_OGG
		}
		if (fSeekable) {
			fTracks[serialno] = OggSeekable::makeOggSeekable(fSeekable, &fSeekableLock, serialno, packet);
		} else {
			class Interface : public StreamInterface {
			private:
				OggReader * reader;
			public:
				Interface(OggReader * reader) {
					this->reader = reader;
				}
				virtual ssize_t ReadPage() {
					return reader->ReadPage();
				}
			};
			fTracks[serialno] = OggStream::makeOggStream(new Interface(this), serialno, packet);
		}
		fCookies.push_back(serialno);
	}
	// this check ensures that we only push the initial pages into OggSeekables.
	if (!fSeekable || new_serialno) {
		status_t status = fTracks[serialno]->AddPage(fPosition, page);
		if (status != B_OK) {
			return status;
		}
		fPosition += page.header_len + page.body_len;
	}
	return page.header_len + page.body_len;
}
Exemple #4
0
ComponentResult process_stream_page__speex(OggImportGlobals *globals, StreamInfo *si, ogg_page *opg)
{
    ComponentResult ret = noErr;
    int ovret = 0;
    Boolean loop = true;
    Boolean movie_changed = false;

    TimeValue movieTS = GetMovieTimeScale(globals->theMovie);
    TimeValue mediaTS = 0;
    TimeValue mediaTS_fl = 0.0;

    ogg_packet op;

    switch(si->si_speex.state) {
    case kSStateReadingComments:
    case kSStateReadingAdditionalHeaders:
        ogg_stream_pagein(&si->os, opg);
        break;
    default:
        break;
    }

    do {
        switch(si->si_speex.state) {
        case kSStateReadingComments:
            ovret = ogg_stream_packetout(&si->os, &op);
            if (ovret < 0) {
                loop = false;
                ret = invalidMedia;
            } else if (ovret < 1) {
                loop = false;
            } else {
                unsigned long atomhead[2] = { EndianU32_NtoB(op.bytes + sizeof(atomhead)), EndianU32_NtoB(kCookieTypeSpeexComments) };

                PtrAndHand(atomhead, si->soundDescExtension, sizeof(atomhead));
                PtrAndHand(op.packet, si->soundDescExtension, op.bytes);

                ret = CreateTrackAndMedia(globals, si, opg);
                if (ret != noErr) {
                    dbg_printf("??? -- CreateTrackAndMedia failed?: %ld\n", (long)ret);
                }

                unpack_vorbis_comments(&si->si_speex.vc, op.packet, op.bytes);
                /*err =*/ DecodeCommentsQT(globals, si, &si->si_speex.vc);
                //NotifyMovieChanged(globals);

                si->si_speex.state = kSStateReadingAdditionalHeaders;
            }

            break;

        case kSStateReadingAdditionalHeaders:
            if (si->si_speex.skipped_headers >= si->si_speex.header.extra_headers) {
                unsigned long endAtom[2] = { EndianU32_NtoB(sizeof(endAtom)), EndianU32_NtoB(kAudioTerminatorAtomType) };

                ret = PtrAndHand(endAtom, si->soundDescExtension, sizeof(endAtom));
                if (ret == noErr) {
                    ret = AddSoundDescriptionExtension((SoundDescriptionHandle) si->sampleDesc,
                                                       si->soundDescExtension, siDecompressionParams);
                    //dbg_printf("??? -- Adding extension: %ld\n", ret);
                } else {
                    //dbg_printf("??? -- Hmm, something went wrong: %ld\n", ret);
                }

                si->insertTime = 0;
                si->streamOffset = globals->currentGroupOffset;
                mediaTS = GetMediaTimeScale(si->theMedia);
                mediaTS_fl = (Float64) mediaTS;
                si->streamOffsetSamples = (TimeValue) (mediaTS_fl * globals->currentGroupOffsetSubSecond) -
                    ((globals->currentGroupOffset % movieTS) * mediaTS / movieTS);
                dbg_printf("---/  / streamOffset: [%ld, %ld], %lg\n", si->streamOffset, si->streamOffsetSamples, globals->currentGroupOffsetSubSecond);
                si->incompleteCompensation = 0;
                si->si_speex.state = kSStateReadingFirstPacket;

                loop = false; // ??!
                break;
            }

            ovret = ogg_stream_packetout(&si->os, &op);
            if (ovret < 0) {
                loop = false;
                ret = invalidMedia;
            } else if (ovret < 1) {
                loop = false;
            } else {
                // not much here so far, basically just skip the extra header packet
                unsigned long atomhead[2] = { EndianU32_NtoB(op.bytes + sizeof(atomhead)), EndianU32_NtoB(kCookieTypeSpeexExtraHeader) };
                PtrAndHand(atomhead, si->soundDescExtension, sizeof(atomhead));
                PtrAndHand(op.packet, si->soundDescExtension, op.bytes);

                si->si_speex.skipped_headers += 1;
            }

            break;

        case kSStateReadingFirstPacket:
            if (ogg_page_pageno(opg) > 2) {
                si->lastGranulePos = ogg_page_granulepos(opg);
                dbg_printf("----==< skipping: %llx, %lx\n", si->lastGranulePos, ogg_page_pageno(opg));
                loop = false;

                if (si->lastGranulePos < 0)
                    si->lastGranulePos = 0;
            }
            si->si_speex.state = kSStateReadingPackets;
            break;

        case kVStateReadingPackets:
            {
                ogg_int64_t pos       = ogg_page_granulepos(opg);
                int         len       = opg->header_len + opg->body_len;
                TimeValue   duration  = pos - si->lastGranulePos;
                short       smp_flags = 0;

                if (ogg_page_continued(opg) || si->incompleteCompensation != 0)
                    smp_flags |= mediaSampleNotSync;

                if (duration <= 0) {
                    duration = INCOMPLETE_PAGE_DURATION;
                    si->incompleteCompensation -= INCOMPLETE_PAGE_DURATION;
                } else if (si->incompleteCompensation != 0) {
                    duration += si->incompleteCompensation;
                    si->incompleteCompensation = 0;
                    if (duration <= 0) {
                        ret = badFileFormat;
                        loop = false;
                        break;
                    }
                }

                if (si->insertTime == 0 && si->streamOffsetSamples > 0) {
                    dbg_printf("   -   :++: increasing duration (%ld) by sampleOffset: %ld\n", duration, si->streamOffsetSamples);
                    duration += si->streamOffsetSamples;
                }

                ret = _store_sample_reference(si, &globals->dataOffset, len, duration, smp_flags);
                if (ret != noErr) {
                    loop = false;
                    break;
                }

                if (!globals->usingIdle) {
                    if (si->sample_refs_count >= kSSRefsInitial)
                        ret = _commit_srefs(globals, si, &movie_changed);
                }

                if (pos != -1)
                    si->lastGranulePos = pos;
            }
            loop = false;
            break;

        default:
            loop = false;
        }
    } while(loop);

    if (movie_changed)
        NotifyMovieChanged(globals, false);

    return ret;
};
Exemple #5
0
ComponentResult process_stream_page__flac(OggImportGlobals *globals, StreamInfo *si, ogg_page *opg)
{
    ComponentResult ret = noErr;
    int ovret = 0;
    Boolean loop = true;
    Boolean movie_changed = false;

    TimeValue movieTS = GetMovieTimeScale(globals->theMovie);
    TimeValue mediaTS = 0;
    TimeValue mediaTS_fl = 0.0;

    ogg_packet op;

    switch(si->si_flac.state) {
    case kFStateReadingComments:
    case kFStateReadingAdditionalMDBlocks:
        ogg_stream_pagein(&si->os, opg);
        break;
    default:
        break;
    }

    do {
        switch(si->si_flac.state) {
        case kFStateReadingComments:
            ovret = ogg_stream_packetout(&si->os, &op);
            if (ovret < 0) {
                loop = false;
                ret = invalidMedia;
            } else if (ovret < 1) {
                loop = false;
            } else {
                ret = CreateTrackAndMedia(globals, si, opg);
                if (ret != noErr) {
                    dbg_printf("??? -- CreateTrackAndMedia failed?: %ld\n", (long)ret);
                    loop = false;
                    break;
                }

                if (si->si_flac.metablocks == 0 && (*((unsigned char*) op.packet) == 0xff)) {
                    si->si_flac.metablocks = si->si_flac.skipped;
                    si->si_flac.state = kFStateReadingAdditionalMDBlocks;
                    break;
                }

                {
                    unsigned long atomhead[2] = { EndianU32_NtoB(op.bytes + sizeof(atomhead)), EndianU32_NtoB(kCookieTypeFLACMetadata) };

                    PtrAndHand(atomhead, si->soundDescExtension, sizeof(atomhead));
                    PtrAndHand(op.packet, si->soundDescExtension, op.bytes);
                }

                if (((* (char *) op.packet) & 0x7f) == 4) {
                    dbg_printf("!  > - flac_stream_page - mb: %ld, skipped: %ld, h: %02x\n", si->si_flac.metablocks, si->si_flac.skipped,
                               (*(char *) op.packet) & 0x7f);
                    unpack_vorbis_comments(&si->si_flac.vc, ((char *) op.packet) + 4, op.bytes - 4);
                    /*err =*/ DecodeCommentsQT(globals, si, &si->si_flac.vc);
                    //NotifyMovieChanged(globals);
                }

                si->si_flac.skipped += 1;
                si->si_flac.state = kFStateReadingAdditionalMDBlocks;
            }

            break;

        case kFStateReadingAdditionalMDBlocks:
            dbg_printf("! -- - flac_stream_page - mb: %ld, skipped: %ld\n", si->si_flac.metablocks, si->si_flac.skipped);
            if (si->si_flac.metablocks > 0 && si->si_flac.skipped >= si->si_flac.metablocks) {
                unsigned long endAtom[2] = { EndianU32_NtoB(sizeof(endAtom)), EndianU32_NtoB(kAudioTerminatorAtomType) };

                ret = PtrAndHand(endAtom, si->soundDescExtension, sizeof(endAtom));
                if (ret == noErr) {
                    ret = AddSoundDescriptionExtension((SoundDescriptionHandle) si->sampleDesc,
                                                       si->soundDescExtension, siDecompressionParams);
                    //dbg_printf("??? -- Adding extension: %ld\n", ret);
                } else {
                    //dbg_printf("??? -- Hmm, something went wrong: %ld\n", ret);
                }

                si->insertTime = 0;
                si->streamOffset = globals->currentGroupOffset;
                mediaTS = GetMediaTimeScale(si->theMedia);
                mediaTS_fl = (Float64) mediaTS;
                si->streamOffsetSamples = (TimeValue) (mediaTS_fl * globals->currentGroupOffsetSubSecond) -
                    ((globals->currentGroupOffset % movieTS) * mediaTS / movieTS);
                dbg_printf("---/  / streamOffset: [%ld, %ld], %lg\n", si->streamOffset, si->streamOffsetSamples, globals->currentGroupOffsetSubSecond);
                si->incompleteCompensation = 0;
                si->si_flac.state = kFStateReadingFirstPacket;

                loop = false; // the audio data is supposed to start on a fresh page
                break;
            }

            ovret = ogg_stream_packetout(&si->os, &op);
            dbg_printf("! -- - flac_stream_page - ovret: %d\n", ovret);
            if (ovret < 0) {
                loop = false;
                ret = invalidMedia;
            } else if (ovret < 1) {
                loop = false;
            } else {
                // not much here so far, basically just skip the extra header packet
                unsigned long atomhead[2] = { EndianU32_NtoB(op.bytes + sizeof(atomhead)), EndianU32_NtoB(kCookieTypeFLACMetadata) };

                if (si->si_flac.metablocks == 0 && (* (unsigned char*) op.packet) == 0xff) {
                    si->si_flac.metablocks = si->si_flac.skipped;
                    break;
                }

                PtrAndHand(atomhead, si->soundDescExtension, sizeof(atomhead));
                PtrAndHand(op.packet, si->soundDescExtension, op.bytes);

                if (((* (unsigned char *) op.packet) & 0x7f) == 4) {
                    dbg_printf("!  > - flac_stream_page - mb: %ld, skipped: %ld, h: %02x\n", si->si_flac.metablocks, si->si_flac.skipped,
                               (*(char *) op.packet) & 0x7f);
                    unpack_vorbis_comments(&si->si_flac.vc, ((char *) op.packet) + 4, op.bytes - 4);
                    /*err =*/ DecodeCommentsQT(globals, si, &si->si_flac.vc);
                    //NotifyMovieChanged(globals);
                }

                si->si_flac.skipped += 1;
            }

            break;

        case kFStateReadingFirstPacket:
            // what to do with this one? is it needed at all??
            if (ogg_page_pageno(opg) > 2 && false) {
                si->lastGranulePos = ogg_page_granulepos(opg);
                dbg_printf("----==< skipping: %llx, %lx\n", si->lastGranulePos, ogg_page_pageno(opg));
                loop = false;

                if (si->lastGranulePos < 0)
                    si->lastGranulePos = 0;
            }
            si->si_flac.state = kFStateReadingPackets;
            break;

        case kFStateReadingPackets:
            {
                ogg_int64_t pos       = ogg_page_granulepos(opg);
                int         len       = opg->header_len + opg->body_len;
                TimeValue   duration  = pos - si->lastGranulePos;
                short       smp_flags = 0;

                if (ogg_page_continued(opg) || si->incompleteCompensation != 0)
                    smp_flags |= mediaSampleNotSync;

                if (duration <= 0) {
                    duration = INCOMPLETE_PAGE_DURATION;
                    si->incompleteCompensation -= INCOMPLETE_PAGE_DURATION;
                } else if (si->incompleteCompensation != 0) {
                    duration += si->incompleteCompensation;
                    si->incompleteCompensation = 0;
                    if (duration <= 0) {
                        ret = badFileFormat;
                        loop = false;
                        break;
                    }
                }

                if (si->insertTime == 0 && si->streamOffsetSamples > 0) {
                    dbg_printf("   -   :++: increasing duration (%ld) by sampleOffset: %ld\n", duration, si->streamOffsetSamples);
                    duration += si->streamOffsetSamples;
                }

                ret = _store_sample_reference(si, &globals->dataOffset, len, duration, smp_flags);
                if (ret != noErr) {
                    loop = false;
                    break;
                }

                if (!globals->usingIdle) {
#if !defined(XIPHQT_FORCE_SINGLE_SAMPLE_REF)
                    if (si->sample_refs_count >= si->sample_refs_size)
                    //if (si->sample_refs_count >= kFSRefsInitial)
#endif
                    {
                        ret = _commit_srefs(globals, si, &movie_changed);
                    }
                }

                if (pos != -1)
                    si->lastGranulePos = pos;
            }
            loop = false;
            break;

        default:
            loop = false;
        }
    } while(loop);

    if (movie_changed)
        NotifyMovieChanged(globals, false);

    return ret;
};