Program: 110194
Project: 110194
Buggy source:
/** 
 * Attempts to extract the next sample in the current mdat atom. <p> If there are no more samples in the current mdat atom then the parser state is transitioned to   {@link #STATE_READING_ATOM_HEADER} and {@code false} is returned.<p> It is possible for a sample to be extracted in part in the case that an exception is thrown. In this case the method can be called again to extract the remainder of the sample.
 * @param input The {@link ExtractorInput} from which to read data.
 * @return Whether a sample was extracted.
 * @throws IOException If an error occurs reading from the input.
 * @throws InterruptedException If the thread is interrupted.
 */
private boolean readSample(ExtractorInput input) throws IOException, InterruptedException {
  if (parserState == STATE_READING_SAMPLE_START) {
    if (currentTrackBundle == null) {
      TrackBundle currentTrackBundle=getNextFragmentRun(trackBundles);
      if (currentTrackBundle == null) {
        int bytesToSkip=(int)(endOfMdatPosition - input.getPosition());
        if (bytesToSkip < 0) {
          throw new ParserException("String_Node_Str");
        }
        input.skipFully(bytesToSkip);
        enterReadingAtomHeaderState();
        return false;
      }
      long nextDataPosition=currentTrackBundle.fragment.trunDataPosition[currentTrackBundle.currentTrackRunIndex];
      int bytesToSkip=(int)(nextDataPosition - input.getPosition());
      if (bytesToSkip < 0) {
        Log.w(TAG,"String_Node_Str");
        bytesToSkip=0;
      }
      input.skipFully(bytesToSkip);
      this.currentTrackBundle=currentTrackBundle;
    }
    sampleSize=currentTrackBundle.fragment.sampleSizeTable[currentTrackBundle.currentSampleIndex];
    if (currentTrackBundle.fragment.definesEncryptionData) {
      sampleBytesWritten=appendSampleEncryptionData(currentTrackBundle);
      sampleSize+=sampleBytesWritten;
    }
 else {
      sampleBytesWritten=0;
    }
    if (currentTrackBundle.track.sampleTransformation == Track.TRANSFORMATION_CEA608_CDAT) {
      sampleSize-=Atom.HEADER_SIZE;
      input.skipFully(Atom.HEADER_SIZE);
    }
    parserState=STATE_READING_SAMPLE_CONTINUE;
    sampleCurrentNalBytesRemaining=0;
  }
  TrackFragment fragment=currentTrackBundle.fragment;
  Track track=currentTrackBundle.track;
  TrackOutput output=currentTrackBundle.output;
  int sampleIndex=currentTrackBundle.currentSampleIndex;
  if (track.nalUnitLengthFieldLength != 0) {
    byte[] nalPrefixData=nalPrefix.data;
    nalPrefixData[0]=0;
    nalPrefixData[1]=0;
    nalPrefixData[2]=0;
    int nalUnitPrefixLength=track.nalUnitLengthFieldLength + 1;
    int nalUnitLengthFieldLengthDiff=4 - track.nalUnitLengthFieldLength;
    while (sampleBytesWritten < sampleSize) {
      if (sampleCurrentNalBytesRemaining == 0) {
        input.readFully(nalPrefixData,nalUnitLengthFieldLengthDiff,nalUnitPrefixLength);
        nalPrefix.setPosition(0);
        sampleCurrentNalBytesRemaining=nalPrefix.readUnsignedIntToInt() - 1;
        nalStartCode.setPosition(0);
        output.sampleData(nalStartCode,4);
        output.sampleData(nalPrefix,1);
        processSeiNalUnitPayload=cea608TrackOutputs.length > 0 && NalUnitUtil.isNalUnitSei(track.format.sampleMimeType,nalPrefixData[4]);
        sampleBytesWritten+=5;
        sampleSize+=nalUnitLengthFieldLengthDiff;
      }
 else {
        int writtenBytes;
        if (processSeiNalUnitPayload) {
          nalBuffer.reset(sampleCurrentNalBytesRemaining);
          input.readFully(nalBuffer.data,0,sampleCurrentNalBytesRemaining);
          output.sampleData(nalBuffer,sampleCurrentNalBytesRemaining);
          writtenBytes=sampleCurrentNalBytesRemaining;
          int unescapedLength=NalUnitUtil.unescapeStream(nalBuffer.data,nalBuffer.limit());
          nalBuffer.setPosition(MimeTypes.VIDEO_H265.equals(track.format.sampleMimeType) ? 1 : 0);
          nalBuffer.setLimit(unescapedLength);
          CeaUtil.consume(fragment.getSamplePresentationTime(sampleIndex) * 1000L,nalBuffer,cea608TrackOutputs);
        }
 else {
          writtenBytes=output.sampleData(input,sampleCurrentNalBytesRemaining,false);
        }
        sampleBytesWritten+=writtenBytes;
        sampleCurrentNalBytesRemaining-=writtenBytes;
      }
    }
  }
 else {
    while (sampleBytesWritten < sampleSize) {
      int writtenBytes=output.sampleData(input,sampleSize - sampleBytesWritten,false);
      sampleBytesWritten+=writtenBytes;
    }
  }
  long sampleTimeUs=fragment.getSamplePresentationTime(sampleIndex) * 1000L;
  if (timestampAdjuster != null) {
    sampleTimeUs=timestampAdjuster.adjustSampleTimestamp(sampleTimeUs);
  }
  @C.BufferFlags int sampleFlags=fragment.sampleIsSyncFrameTable[sampleIndex] ? C.BUFFER_FLAG_KEY_FRAME : 0;
  TrackOutput.CryptoData cryptoData=null;
  if (fragment.definesEncryptionData) {
    sampleFlags|=C.BUFFER_FLAG_ENCRYPTED;
    TrackEncryptionBox encryptionBox=fragment.trackEncryptionBox != null ? fragment.trackEncryptionBox : track.getSampleDescriptionEncryptionBox(fragment.header.sampleDescriptionIndex);
    cryptoData=encryptionBox.cryptoData;
  }
  output.sampleMetadata(sampleTimeUs,sampleFlags,sampleSize,0,cryptoData);
  outputPendingMetadataSamples(sampleTimeUs);
  currentTrackBundle.currentSampleIndex++;
  currentTrackBundle.currentSampleInTrackRun++;
  if (currentTrackBundle.currentSampleInTrackRun == fragment.trunLength[currentTrackBundle.currentTrackRunIndex]) {
    currentTrackBundle.currentTrackRunIndex++;
    currentTrackBundle.currentSampleInTrackRun=0;
    currentTrackBundle=null;
  }
  parserState=STATE_READING_SAMPLE_START;
  return true;
}

Fixed version (ground truth):
/** 
 * Attempts to extract the next sample in the current mdat atom. <p> If there are no more samples in the current mdat atom then the parser state is transitioned to   {@link #STATE_READING_ATOM_HEADER} and {@code false} is returned.<p> It is possible for a sample to be extracted in part in the case that an exception is thrown. In this case the method can be called again to extract the remainder of the sample.
 * @param input The {@link ExtractorInput} from which to read data.
 * @return Whether a sample was extracted.
 * @throws IOException If an error occurs reading from the input.
 * @throws InterruptedException If the thread is interrupted.
 */
private boolean readSample(ExtractorInput input) throws IOException, InterruptedException {
  if (parserState == STATE_READING_SAMPLE_START) {
    if (currentTrackBundle == null) {
      TrackBundle currentTrackBundle=getNextFragmentRun(trackBundles);
      if (currentTrackBundle == null) {
        int bytesToSkip=(int)(endOfMdatPosition - input.getPosition());
        if (bytesToSkip < 0) {
          throw new ParserException("String_Node_Str");
        }
        input.skipFully(bytesToSkip);
        enterReadingAtomHeaderState();
        return false;
      }
      long nextDataPosition=currentTrackBundle.fragment.trunDataPosition[currentTrackBundle.currentTrackRunIndex];
      int bytesToSkip=(int)(nextDataPosition - input.getPosition());
      if (bytesToSkip < 0) {
        Log.w(TAG,"String_Node_Str");
        bytesToSkip=0;
      }
      input.skipFully(bytesToSkip);
      this.currentTrackBundle=currentTrackBundle;
    }
    sampleSize=currentTrackBundle.fragment.sampleSizeTable[currentTrackBundle.currentSampleIndex];
    if (currentTrackBundle.track.sampleTransformation == Track.TRANSFORMATION_CEA608_CDAT) {
      sampleSize-=Atom.HEADER_SIZE;
      input.skipFully(Atom.HEADER_SIZE);
    }
    if (currentTrackBundle.fragment.definesEncryptionData) {
      sampleBytesWritten=appendSampleEncryptionData(currentTrackBundle);
      sampleSize+=sampleBytesWritten;
    }
 else {
      sampleBytesWritten=0;
    }
    parserState=STATE_READING_SAMPLE_CONTINUE;
    sampleCurrentNalBytesRemaining=0;
  }
  TrackFragment fragment=currentTrackBundle.fragment;
  Track track=currentTrackBundle.track;
  TrackOutput output=currentTrackBundle.output;
  int sampleIndex=currentTrackBundle.currentSampleIndex;
  if (track.nalUnitLengthFieldLength != 0) {
    byte[] nalPrefixData=nalPrefix.data;
    nalPrefixData[0]=0;
    nalPrefixData[1]=0;
    nalPrefixData[2]=0;
    int nalUnitPrefixLength=track.nalUnitLengthFieldLength + 1;
    int nalUnitLengthFieldLengthDiff=4 - track.nalUnitLengthFieldLength;
    while (sampleBytesWritten < sampleSize) {
      if (sampleCurrentNalBytesRemaining == 0) {
        input.readFully(nalPrefixData,nalUnitLengthFieldLengthDiff,nalUnitPrefixLength);
        nalPrefix.setPosition(0);
        sampleCurrentNalBytesRemaining=nalPrefix.readUnsignedIntToInt() - 1;
        nalStartCode.setPosition(0);
        output.sampleData(nalStartCode,4);
        output.sampleData(nalPrefix,1);
        processSeiNalUnitPayload=cea608TrackOutputs.length > 0 && NalUnitUtil.isNalUnitSei(track.format.sampleMimeType,nalPrefixData[4]);
        sampleBytesWritten+=5;
        sampleSize+=nalUnitLengthFieldLengthDiff;
      }
 else {
        int writtenBytes;
        if (processSeiNalUnitPayload) {
          nalBuffer.reset(sampleCurrentNalBytesRemaining);
          input.readFully(nalBuffer.data,0,sampleCurrentNalBytesRemaining);
          output.sampleData(nalBuffer,sampleCurrentNalBytesRemaining);
          writtenBytes=sampleCurrentNalBytesRemaining;
          int unescapedLength=NalUnitUtil.unescapeStream(nalBuffer.data,nalBuffer.limit());
          nalBuffer.setPosition(MimeTypes.VIDEO_H265.equals(track.format.sampleMimeType) ? 1 : 0);
          nalBuffer.setLimit(unescapedLength);
          CeaUtil.consume(fragment.getSamplePresentationTime(sampleIndex) * 1000L,nalBuffer,cea608TrackOutputs);
        }
 else {
          writtenBytes=output.sampleData(input,sampleCurrentNalBytesRemaining,false);
        }
        sampleBytesWritten+=writtenBytes;
        sampleCurrentNalBytesRemaining-=writtenBytes;
      }
    }
  }
 else {
    while (sampleBytesWritten < sampleSize) {
      int writtenBytes=output.sampleData(input,sampleSize - sampleBytesWritten,false);
      sampleBytesWritten+=writtenBytes;
    }
  }
  long sampleTimeUs=fragment.getSamplePresentationTime(sampleIndex) * 1000L;
  if (timestampAdjuster != null) {
    sampleTimeUs=timestampAdjuster.adjustSampleTimestamp(sampleTimeUs);
  }
  @C.BufferFlags int sampleFlags=fragment.sampleIsSyncFrameTable[sampleIndex] ? C.BUFFER_FLAG_KEY_FRAME : 0;
  TrackOutput.CryptoData cryptoData=null;
  if (fragment.definesEncryptionData) {
    sampleFlags|=C.BUFFER_FLAG_ENCRYPTED;
    TrackEncryptionBox encryptionBox=fragment.trackEncryptionBox != null ? fragment.trackEncryptionBox : track.getSampleDescriptionEncryptionBox(fragment.header.sampleDescriptionIndex);
    cryptoData=encryptionBox.cryptoData;
  }
  output.sampleMetadata(sampleTimeUs,sampleFlags,sampleSize,0,cryptoData);
  outputPendingMetadataSamples(sampleTimeUs);
  currentTrackBundle.currentSampleIndex++;
  currentTrackBundle.currentSampleInTrackRun++;
  if (currentTrackBundle.currentSampleInTrackRun == fragment.trunLength[currentTrackBundle.currentTrackRunIndex]) {
    currentTrackBundle.currentTrackRunIndex++;
    currentTrackBundle.currentSampleInTrackRun=0;
    currentTrackBundle=null;
  }
  parserState=STATE_READING_SAMPLE_START;
  return true;
}