/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.android.exoplayer2.extractor.ts;

import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.TimestampAdjuster;
import com.google.android.exoplayer2.util.Util;
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;

/**
 * A {@link SectionPayloadReader} that directly outputs the section bytes as sample data.
 *
 * <p>Timestamp adjustment is provided through {@link Format#subsampleOffsetUs}.
 */
public final class PassthroughSectionPayloadReader implements SectionPayloadReader {

  private final String mimeType;
  private @MonotonicNonNull TimestampAdjuster timestampAdjuster;
  private @MonotonicNonNull TrackOutput output;
  private boolean formatOutputWithTimestampAdjustment;

  /**
   * Create a new PassthroughSectionPayloadReader.
   *
   * @param mimeType The MIME type set as {@link Format#sampleMimeType} on the created output track.
   */
  public PassthroughSectionPayloadReader(String mimeType) {
    this.mimeType = mimeType;
  }

  @Override
  public void init(
      TimestampAdjuster timestampAdjuster,
      ExtractorOutput extractorOutput,
      TsPayloadReader.TrackIdGenerator idGenerator) {
    this.timestampAdjuster = timestampAdjuster;
    idGenerator.generateNewId();
    output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_METADATA);
    // Eagerly output an incomplete format (missing timestamp offset) to ensure source preparation
    // is not blocked waiting for potentially sparse metadata.
    output.format(new Format.Builder().setSampleMimeType(mimeType).build());
  }

  @Override
  public void consume(ParsableByteArray sectionData) {
    assertInitialized();
    if (!formatOutputWithTimestampAdjustment) {
      if (timestampAdjuster.getTimestampOffsetUs() == C.TIME_UNSET) {
        // There is not enough information to initialize the timestamp adjuster.
        return;
      }
      output.format(
          new Format.Builder()
              .setSampleMimeType(mimeType)
              .setSubsampleOffsetUs(timestampAdjuster.getTimestampOffsetUs())
              .build());
      formatOutputWithTimestampAdjustment = true;
    }
    int sampleSize = sectionData.bytesLeft();
    output.sampleData(sectionData, sampleSize);
    output.sampleMetadata(
        timestampAdjuster.getLastAdjustedTimestampUs(),
        C.BUFFER_FLAG_KEY_FRAME,
        sampleSize,
        0,
        null);
  }

  @EnsuresNonNull({"timestampAdjuster", "output"})
  private void assertInitialized() {
    Assertions.checkStateNotNull(timestampAdjuster);
    Util.castNonNull(output);
  }
}

@@ -1516,29 +1516,21 @@
 ate 
-final String mimeType
+Format format
 ;%0A  
@@ -1643,63 +1643,8 @@
 put;
-%0A  private boolean formatOutputWithTimestampAdjustment;
 %0A%0A  
@@ -1883,27 +1883,64 @@
 his.
-m
+format = new Format.Builder().setSampleM
 imeType
- = 
+(
 mimeType
 ;%0A  
@@ -1935,16 +1935,25 @@
 mimeType
+).build()
 ;%0A  %7D%0A%0A 
@@ -2469,64 +2469,14 @@
 mat(
-new Format.Builder().setSampleMimeType(mimeType).build()
+format
 );%0A 
@@ -2579,62 +2579,33 @@
     
-if (!formatOutputWithTimestampAdjustment) %7B%0A      if (
+long subsampleOffsetUs = 
 time
@@ -2640,16 +2640,43 @@
 fsetUs()
+;%0A    if (subsampleOffsetUs
  == C.TI
@@ -2697,85 +2697,66 @@
     
-  
 // 
-There is not enough information to initialize the timestamp adjuster.%0A  
+Don't output samples without a known subsample offset.%0A
     
@@ -2765,18 +2765,16 @@
 return;%0A
-  
     %7D%0A  
@@ -2779,173 +2779,133 @@
     
-  output.format(%0A          new F
+if (subsampleOffsetUs != format.subsampleOffsetUs) %7B%0A      format = f
 ormat.
-B
+b
 uild
-er()%0A              .setSampleMimeType(mimeType)%0A              .setSubsampleOffsetUs(timestampAdjuster.getTimest
+Upon().setSubsampleOffsetUs(subs
 amp
+le
 OffsetUs
 ())%0A
@@ -2904,34 +2904,17 @@
 etUs
-())%0A              
+)
 .build()
 );%0A 
@@ -2913,17 +2913,16 @@
 ld()
-)
 ;%0A      
 form
@@ -2921,50 +2921,29 @@
     
-formatOutputWithTimestampAdjustment = true
+output.format(format)
 ;%0A  

Tweak PassthroughSectionPayloadReader to allow timestamp to change