text:
<?xml version="1.0" encoding="UTF-8"?>

<recipeml version="0.5">
  <recipe>
    <head>
      <title>Asparagus and Mushroom Stew</title>
      <categories>
        <cat>Vegetarian</cat></categories>
      <yield>4</yield></head>
    <ingredients>
      <ing>
        <amt>
          <qty>1/3</qty>
          <unit>ounces</unit></amt>
        <item>Dried porcini mushrooms</item></ing>
      <ing>
        <amt>
          <qty>1</qty>
          <unit>tablespoon</unit></amt>
        <item>Oil</item></ing>
      <ing>
        <amt>
          <qty>3</qty>
          <unit/></amt>
        <item>Cloves garlic; minced</item></ing>
      <ing>
        <amt>
          <qty>1/2</qty>
          <unit>pounds</unit></amt>
        <item>Mushrooms; portobello or shitake, chopped</item></ing>
      <ing>
        <amt>
          <qty>1/2</qty>
          <unit>cups</unit></amt>
        <item>Sherry</item></ing>
      <ing>
        <amt>
          <qty>1/2</qty>
          <unit>teaspoons</unit></amt>
        <item>Salt</item></ing>
      <ing>
        <amt>
          <qty>1</qty>
          <unit>pound</unit></amt>
        <item>Asparagus spear; 1" diagonals</item></ing>
      <ing>
        <amt>
          <qty>1</qty>
          <unit>medium</unit></amt>
        <item>Red bell pepper; julienned</item></ing>
      <ing>
        <amt>
          <qty>1</qty>
          <unit>teaspoon</unit></amt>
        <item>Cornstarch dissolved in</item></ing>
      <ing>
        <amt>
          <qty>1</qty>
          <unit>tablespoon</unit></amt>
        <item>Water</item></ing>
      <ing>
        <amt>
          <qty>1</qty>
          <unit>teaspoon</unit></amt>
        <item>Red wine vinegar</item></ing>
      <ing>
        <amt>
          <qty/>
          <unit/></amt>
        <item>Salt and pepper; to taste</item></ing></ingredients>
    <directions>
      <step>  Place dried mushrooms in small heat proof bowl and cover with boiling
  water. Let soak 15 minutes. Meanwhile, in large skillet, heat oil over
  medium heat. Add garlic and fresh mushrooms and cook, stirring often, until
  mushrooms are tender. Add sherry, salt and mushroom liquid. Add asparagus,
  bell pepper and dried mushrooms. Simmer, uncovered until asparagus are
  tender, about 7 minutes. Add dissolved cornstarch and vinegar. Bring
  mixture to a boil and simmer until it thickens slightly, about 30 seconds.
  Serve asparagus mixture over herbed quinoa recipe.

  Recipe by: Vegetarian Times, april 1998

  Posted to MC-Recipe Digest by Cbotwin <Cbotwin@aol.com> on Apr 16, 1998

</step></directions></recipe></recipeml>


text:
package org.jets3t.gui;

import java.awt.Dialog;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.KeyStroke;

/**
 * Dialog box for a user to enter authentication information for HTTP communication, such as
 * NT or Basic authentication.
 *
 * @author James Murty
 */
public class AuthenticationDialog extends JDialog implements ActionListener {
    private static final long serialVersionUID = -8112836668013270984L;

    private final Insets insetsDefault = new Insets(5, 7, 5, 7);
    private JTextField domainField = null;
    private JTextField usernameField = null;
    private JPasswordField passwordField = null;

    private boolean isNtAuthentication = false;

    private String domain = "";
    private String user = "";
    private String password = "";

    /**
     * Construct modal dialog for display over a Frame.
     *
     * @param owner     Frame over which this dialog will be displayed and centred.
     * @param title     the dialog's title text
     * @param question  the question/statement to prompt the user for their password, may be html
     *                  compatible with {@link JHtmlLabel}
     * @param isNtAuthentication   if true a domain name is required in addition to the username and password.
     */
    public AuthenticationDialog(Frame owner, String title, String question, boolean isNtAuthentication) {
        super(owner, title, true);
        this.isNtAuthentication = isNtAuthentication;
        initGui(question);
    }

    /**
     * Construct modal dialog for display over another Dialog.
     *
     * @param owner     Dialog over which this dialog will be displayed and centred.
     * @param title     the dialog's title text
     * @param question  the question/statement to prompt the user for their password
     * @param isNtAuthentication   if true a domain name is required in addition to the username and password.
     */
    public AuthenticationDialog(Dialog owner, String title, String question, boolean isNtAuthentication) {
        super(owner, title, true);
        this.isNtAuthentication = isNtAuthentication;
        initGui(question);
    }

    /**
     * Initialises all GUI elements.
     *
     * @param question  the question/statement to prompt the user for their password
     */
    private void initGui(String question) {
        this.setResizable(false);
        this.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);

        int rowIndex = 0;

        JPanel container = new JPanel(new GridBagLayout());
        JHtmlLabel questionLabel = new JHtmlLabel(question, null);
        container.add(questionLabel, new GridBagConstraints(0, rowIndex++, 2, 1, 0, 0,
            GridBagConstraints.CENTER, GridBagConstraints.NONE, insetsDefault, 0, 0));

        domainField = new JTextField();
        usernameField = new JTextField();
        passwordField = new JPasswordField();

        if (isNtAuthentication) {
            container.add(new JLabel("Domain:"), new GridBagConstraints(0, rowIndex, 1, 1, 0, 0,
                GridBagConstraints.EAST, GridBagConstraints.NONE, insetsDefault, 0, 0));
            container.add(domainField, new GridBagConstraints(1, rowIndex++, 1, 1, 1, 0,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, insetsDefault, 0, 0));
        }

        container.add(new JLabel("User:"), new GridBagConstraints(0, rowIndex, 1, 1, 0, 0,
            GridBagConstraints.EAST, GridBagConstraints.NONE, insetsDefault, 0, 0));
        container.add(usernameField, new GridBagConstraints(1, rowIndex++, 1, 1, 1, 0,
            GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, insetsDefault, 0, 0));
        container.add(new JLabel("Password:"), new GridBagConstraints(0, rowIndex, 1, 1, 0, 0,
            GridBagConstraints.EAST, GridBagConstraints.NONE, insetsDefault, 0, 0));
        container.add(passwordField, new GridBagConstraints(1, rowIndex++, 1, 1, 1, 0,
            GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, insetsDefault, 0, 0));

        JPanel buttonsContainer = new JPanel(new GridBagLayout());
        final JButton cancelButton = new JButton("Cancel");
        cancelButton.setActionCommand("Cancel");
        cancelButton.addActionListener(this);
        JButton okButton = new JButton("Authenticate me");
        okButton.setActionCommand("OK");
        okButton.setDefaultCapable(true);
        okButton.addActionListener(this);
        buttonsContainer.add(cancelButton, new GridBagConstraints(0, 0, 1, 1, 0, 0,
            GridBagConstraints.CENTER, GridBagConstraints.NONE, insetsDefault, 0, 0));
        buttonsContainer.add(okButton, new GridBagConstraints(1, 0, 1, 1, 0, 0,
            GridBagConstraints.CENTER, GridBagConstraints.NONE, insetsDefault, 0, 0));

        container.add(buttonsContainer, new GridBagConstraints(0, rowIndex++, 2, 1, 0, 0,
            GridBagConstraints.CENTER, GridBagConstraints.NONE, insetsDefault, 0, 0));

        // Set default ENTER and ESCAPE buttons.
        this.getRootPane().setDefaultButton(okButton);
        this.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
            .put(KeyStroke.getKeyStroke("ESCAPE"), "ESCAPE");
        this.getRootPane().getActionMap().put("ESCAPE", new AbstractAction() {
            private static final long serialVersionUID = 3717631976908670386L;

            public void actionPerformed(ActionEvent actionEvent) {
                cancelButton.doClick();
            }
        });

        this.getContentPane().add(container);
        this.pack();
        this.setLocationRelativeTo(this.getOwner());
    }

    /**
     * Event handler for this dialog.
     */
    public void actionPerformed(ActionEvent e) {
        if ("OK".equals(e.getActionCommand())) {
            if (isNtAuthentication) {
                this.domain = domainField.getText();
            }
            this.user = usernameField.getText();
            this.password = new String(passwordField.getPassword());
        } else if ("Cancel".equals(e.getActionCommand())) {
            this.domain = "";
            this.user = "";
            this.password = "";
        }
        this.setVisible(false);
    }

    /**
     * @return
     * the domain entered by the user, or null if the dialog was cancelled or NT authentication wasn't used.
     */
    public String getDomain() {
        return domain;
    }

    /**
     * @return
     * the user name entered by the user, or null if the dialog was cancelled.
     */
    public String getUser() {
        return user;
    }

    /**
     * @return
     * the password entered by the user, or null if the dialog was cancelled.
     */
    public String getPassword() {
        return password;
    }

}

redpajama_set_name: RedPajamaGithub


text:
let _ = require('../mindash');
let log = require('../core/logger');
let invariant = require('invariant');
let timeout = require('../core/utils/timeout');
let deferred = require('../core/utils/deferred');
let renderToString = require('./renderToString');
let FetchDiagnostics = require('./fetchDiagnostics');
let createDispatcher = require('../core/createDispatcher');
let UnknownStoreError = require('../errors/unknownStoreError');

let DEFAULT_TIMEOUT = 1000;

let SERIALIZED_WINDOW_OBJECT = '__marty';
let WINDOW_STATE_ID = renderToString.stateId;
let WINDOW_STATE_ATTR = renderToString.stateAttr;

module.exports = function (React) {
  class Application {
    constructor(options) {
      options = options || {};

      let dispatcher = createDispatcher();

      // Needed because we don't have access to actual Application type
      this.__isApplication = true;
      this.__isCoreType = true;
      this.__types = {};

      Object.defineProperty(this, 'dispatcher', {
        get() {
          return dispatcher;
        }
      });

      this.req = options.req;
      this.res = options.res;

      if (options.register) {
        this.register(options.register);
      }

      currentApplicationIs(this);
    }

    static __getCurrentApplication(cb) {
      return getCurrentApplication(cb);
    }

    getAll(type) {
      return this.__types[type] || {};
    }

    getAllStores() {
      return this.getAll('Store');
    }

    register(id, ctor) {
      if (!this.dispatcher) {
        throw new Error('`super()` must be called before you can register anything');
      }

      if (!id) {
        throw new Error('Must specify a id or an object');
      }

      if (_.isString(id)) {
        if (!_.isFunction(ctor)) {
          throw new Error('Must pass in a instantiable object');
        }

        let obj = new ctor({
          app: this,
          id: id
        });

        obj.id = id;

        let type = obj.__type;

        if (type) {
          if (!this.__types[type]) {
            this.__types[type] = {};
          }

          this.__types[type][id] = obj;
        }

        if (id.indexOf('.') === -1) {
          this[id] = obj;
        } else {
          var container = this;
          var parts = id.split('.');

          _.each(_.initial(parts), (part) => {
            if (_.isUndefined(container[part])) {
              container[part] = {};
            }

            container = container[part];
          });

          container[_.last(parts)] = obj;
        }
      }

      if (_.isObject(id)) {
        let registerObject = (obj, prefix) => {
          _.each(obj, (ctor, id) => {
            if (prefix) {
              id = `${prefix}.${id}`;
            }

            if (_.isFunction(ctor)) {
              this.register(id, ctor);
            } else if (_.isObject(ctor)) {
              registerObject(ctor, id);
            }
          });
        };

        registerObject(id);
      }
    }

    fetch(cb, options) {
      let fetchFinished;

      options = _.defaults(options || {}, {
        timeout: DEFAULT_TIMEOUT
      });

      this.__deferredFetchFinished = deferred();
      fetchFinished = this.__deferredFetchFinished.promise;
      this.__diagnostics = new FetchDiagnostics(options.prevDiagnostics);

      try {
        cb.call(this);
      } catch (e) {
        this.__deferredFetchFinished.reject(e);

        return fetchFinished;
      }

      if (!this.__diagnostics.hasPendingFetches) {
        this.__deferredFetchFinished.resolve();
      }

      return Promise
        .race([fetchFinished, timeout(options.timeout)])
        .then(() => this.__diagnostics);
    }

    fetchStarted(storeId, fetchId) {
      let diagnostics = this.__diagnostics;

      if (diagnostics) {
        diagnostics.fetchStarted(storeId, fetchId);
      }
    }

    fetchFinished(storeId, fetchId, status, options) {
      let diagnostics = this.__diagnostics;

      if (diagnostics) {
        diagnostics.fetchFinished(storeId, fetchId, status, options);

        if (!diagnostics.hasPendingFetches) {
          this.__deferredFetchFinished.resolve();
        }
      }
    }

    clearState() {
      _.invoke(this.getAllStores(), 'clear');
    }

    replaceState(states) {
      _.each(this.getAllStores(), (store, id) => {
        if (states[id]) {
          store.replaceState(states[id]);
        }
      });
    }

    rehydrate(storeStates) {
      let stores = this.getAllStores();

      storeStates = storeStates || getStoreStatesFromWindow();

      _.each(storeStates, (dehydratedStore, storeId) => {
        let store = stores[storeId];
        let state = dehydratedStore.state;

        if (!store) {
          throw new UnknownStoreError(storeId);
        }

        store.__fetchHistory = dehydratedStore.fetchHistory;

        if (_.isFunction(store.rehydrate)) {
          store.rehydrate(state);
        } else {
          try {
            store.replaceState(state);
          } catch (e) {
            log.error(
              `Failed to rehydrate the state of ${storeId}. You might be able ` +
              `to solve this problem by implementing Store#rehydrate()`
            );

            throw e;
          }
        }
      });

      function getStoreStatesFromWindow() {
        if (!window) {
          return;
        }

        // Old-style method of setting up stores.
        let hasSerializedObjectStores =
          window[SERIALIZED_WINDOW_OBJECT] &&
          window[SERIALIZED_WINDOW_OBJECT].stores;
        if (hasSerializedObjectStores) {
          return window[SERIALIZED_WINDOW_OBJECT].stores;
        }

        if (!window.document) {
          return;
        }

        let stateElement = window.document.getElementById(WINDOW_STATE_ID);
        if (!stateElement) {
          return;
        }

        let serializedState = stateElement.getAttribute(WINDOW_STATE_ATTR);
        if (!serializedState) {
          return;
        }

        return JSON.parse(serializedState);
      }
    }

    dehydrate() {
      let dehydratedStores = {};
      let stores = this.getAllStores();

      _.each(stores, (store, id) => {
        dehydratedStores[id] = {
          fetchHistory: store.__fetchHistory,
          state: (store.dehydrate || store.getState).call(store)
        };
      });

      // TODO: Remove code-based implementation of dehydrate.
      dehydratedStores.toString = function () {
        return `(window.__marty||(window.__marty={})).stores=${JSON.stringify(dehydratedStores)}`;
      };

      dehydratedStores.toJSON = function () {
        return _.omit(dehydratedStores, 'toString', 'toJSON');
      };

      return dehydratedStores;
    }

    renderToString(element, options) {
      return renderToString(
        this,
        React.renderToString,
        () => elementWithApp(element, this),
        options
      );
    }

    renderToStaticMarkup(element, options) {
      return renderToString(
        this,
        React.renderToStaticMarkup,
        () => elementWithApp(element, this),
        options
      );
    }
  }

  // Internal API used by DevTools to access the current application
  let currentApplication;
  let currentApplicationRequests = [];

  function currentApplicationIs(app) {
    currentApplication = app;
    _.each(currentApplicationRequests, cb => cb(app));
    currentApplicationRequests = [];
  }

  function getCurrentApplication(cb) {
    if (currentApplication) {
      cb(currentApplication);
    } else {
      currentApplicationRequests.push(cb);
    }
  }

  function elementWithApp(element, app) {
    invariant(
      element &&
      (typeof element.type === 'function' || typeof element.type === 'string'),
      'Must pass in a React component'
    );

    return React.cloneElement(element, {
      app: app
    });
  }

  return Application;
};


text:
The public cloud provides a web-based service management platform. You can access TMS through the management console or HTTPS-compliant application programming interfaces \(APIs\). These two access modes differ as follows:

-   Using APIs

    If you need to integrate TMS on the public cloud into a third-party system for secondary development, use APIs to access TMS. For details, see the Tag Management Service API Reference.

-   Through the management console

    The management console is a web user interface for you to manage your compute, storage, and other cloud resources. Tenants and users who have registered on the cloud platform can access TMS by selecting  **Tag Management Service**  under  **Management & Deployment**  on the management console.


text:
<?php

namespace Admin\Navigation;

use Zend\Navigation\Service\DefaultNavigationFactory;

class NavigationFactory extends DefaultNavigationFactory
{
    /**
     * @return string
     */
    protected function getName()
    {
        return 'admin_navigation';
    }

}


text:
module ActionCost
  class SqlParser
    attr_reader :table_name, :operation, :join_tables, :invalid

    VALID_OPERATIONS = %w{ select insert update delete }

    def initialize(sql)
      @invalid  = false
      @sql      = sql
      @join_tables = []
    end

    def parse
      if @sql =~ /^\s*(\w+)/
        op = $1.downcase
        unless VALID_OPERATIONS.include?(op)
          Rails.logger.error "action_cost: unknown operation [#{op}]"
          @invalid = true
          return false
        end
        @operation = op
      else
        Rails.logger.error "action_cost: could not parse [#{@sql}]"
        @invalid = true
        return false
      end

      case @operation
      when 'select' then parse_select
      when 'insert' then parse_insert
      when 'update' then parse_update
      when 'delete' then parse_delete
      end

      return !@invalid
    end

    def log
      if @invalid
        Rails.logger.debug "action_cost: non parsable query"
      else
        Rails.logger.debug "action_cost: operation=#{@operation} table_name=#{@table_name} " +
                           "join_tables=#{@join_tables.inspect}"
      end
    end

   private

    def parse_select
      if @sql =~ /from ["`']?(\w+)["`']?\b/i
        @table_name = $1.downcase
      else
        @invalid = true
        return
      end

      @sql.scan(/join ["`']?(\w+)["`']?\b/i) do |arr|
        arr.each do |t|
          @join_tables << t.downcase
        end
      end
    end

    def parse_insert
      if @sql =~ /insert into ["`']?(\w+)["`']?\b/i
        @table_name = $1.downcase
      else
        @invalid = true
      end
    end

    def parse_update
      if @sql =~ /^update ["`']?(\w+)["`']?\b/i
        @table_name = $1.downcase
      else
        @invalid = true
      end
    end

    def parse_delete
      if @sql =~ /^delete from ["`']?(\w+)["`']?\b/
        @table_name = $1.downcase
      else
        @invalid = true
      end
    end
  end
end


text:
import os
import errno
import requests

url='http://www.fiatusa.com/hostd/getlocatedealers.json?zipCode=60202&zipDistance=2000'

directory_name=os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..',  '..', 'data'))

try:
    os.makedirs(directory_name)
except OSError as exc:
    if exc.errno == errno.EEXIST and os.path.isdir(directory_name):
        pass
    else:
        raise

file_name=os.path.join(directory_name, 'fiat.json')

response = requests.get(url, stream=True)

with open(file_name, 'wb') as fd:
    for chunk in response.iter_content(chunk_size=1024):
        fd.write(chunk)


text:
package androidx.camera.video.internal.encoder;

import static androidx.camera.video.internal.encoder.EncoderImpl.InternalState.CONFIGURED;
import static androidx.camera.video.internal.encoder.EncoderImpl.InternalState.ERROR;
import static androidx.camera.video.internal.encoder.EncoderImpl.InternalState.PAUSED;
import static androidx.camera.video.internal.encoder.EncoderImpl.InternalState.PENDING_RELEASE;
import static androidx.camera.video.internal.encoder.EncoderImpl.InternalState.PENDING_START;
import static androidx.camera.video.internal.encoder.EncoderImpl.InternalState.PENDING_START_PAUSED;
import static androidx.camera.video.internal.encoder.EncoderImpl.InternalState.RELEASED;
import static androidx.camera.video.internal.encoder.EncoderImpl.InternalState.STARTED;
import static androidx.camera.video.internal.encoder.EncoderImpl.InternalState.STOPPING;

import static java.util.Objects.requireNonNull;

import android.annotation.SuppressLint;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.os.Bundle;
import android.util.Range;
import android.view.Surface;

import androidx.annotation.DoNotInline;
import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.camera.core.Logger;
import androidx.camera.core.impl.Timebase;
import androidx.camera.core.impl.annotation.ExecutedBy;
import androidx.camera.core.impl.utils.executor.CameraXExecutors;
import androidx.camera.core.impl.utils.futures.FutureCallback;
import androidx.camera.core.impl.utils.futures.Futures;
import androidx.camera.video.internal.DebugUtils;
import androidx.camera.video.internal.compat.quirk.AudioEncoderIgnoresInputTimestampQuirk;
import androidx.camera.video.internal.compat.quirk.CameraUseInconsistentTimebaseQuirk;
import androidx.camera.video.internal.compat.quirk.DeviceQuirks;
import androidx.camera.video.internal.compat.quirk.EncoderNotUsePersistentInputSurfaceQuirk;
import androidx.camera.video.internal.compat.quirk.VideoEncoderSuspendDoesNotIncludeSuspendTimeQuirk;
import androidx.camera.video.internal.workaround.EncoderFinder;
import androidx.camera.video.internal.workaround.VideoTimebaseConverter;
import androidx.concurrent.futures.CallbackToFutureAdapter;
import androidx.concurrent.futures.CallbackToFutureAdapter.Completer;
import androidx.core.util.Preconditions;

import com.google.common.util.concurrent.ListenableFuture;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * The encoder implementation.
 *
 *
An encoder could be either a video encoder or an audio encoder.
 */
@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
public class EncoderImpl implements Encoder {

    enum InternalState {
        /**
         * The initial state.
         */
        CONFIGURED,

        /**
         * The state is when encoder is in {@link InternalState#CONFIGURED} state and {@link #start}
         * is called.
         */
        STARTED,

        /**
         * The state is when encoder is in {@link InternalState#STARTED} state and {@link #pause}
         * is called.
         */
        PAUSED,

        /**
         * The state is when encoder is in {@link InternalState#STARTED} state and {@link #stop} is
         * called.
         */
        STOPPING,

        /**
         * The state is when the encoder is in {@link InternalState#STOPPING} state and a
         * {@link #start} is called. It is an extension of {@link InternalState#STOPPING}.
         */
        PENDING_START,

        /**
         * The state is when the encoder is in {@link InternalState#STOPPING} state, then
         * {@link #start} and {@link #pause} is called. It is an extension of
         * {@link InternalState#STOPPING}.
         */
        PENDING_START_PAUSED,

        /**
         * The state is when the encoder is in {@link InternalState#STOPPING} state and a
         * {@link #release} is called. It is an extension of {@link InternalState#STOPPING}.
         */
        PENDING_RELEASE,

        /**
         * Then state is when the encoder encounter error. Error state is a transitional state
         * where encoder user is supposed to wait for {@link EncoderCallback#onEncodeStop} or
         * {@link EncoderCallback#onEncodeError}. Any method call during this state should be
         * ignore except {@link #release}.
         */
        ERROR,

        /** The state is when the encoder is released. */
        RELEASED,
    }

    private static final boolean DEBUG = false;
    private static final long NO_LIMIT_LONG = Long.MAX_VALUE;
    private static final Range<Long> NO_RANGE = Range.create(NO_LIMIT_LONG, NO_LIMIT_LONG);
    private static final long STOP_TIMEOUT_MS = 1000L;
    private static final long TIMESTAMP_ANY = -1;
    private static final int FAKE_BUFFER_INDEX = -9999;

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    final String mTag;
    @SuppressWarnings("WeakerAccess") // synthetic accessor
    final Object mLock = new Object();
    @SuppressWarnings("WeakerAccess") // synthetic accessor
    final boolean mIsVideoEncoder;
    private final MediaFormat mMediaFormat;
    @SuppressWarnings("WeakerAccess") // synthetic accessor
    final MediaCodec mMediaCodec;
    @SuppressWarnings("WeakerAccess") // synthetic accessor
    final EncoderInput mEncoderInput;
    private final EncoderInfo mEncoderInfo;
    @SuppressWarnings("WeakerAccess") // synthetic accessor
    final Executor mEncoderExecutor;
    private final ListenableFuture<Void> mReleasedFuture;
    private final Completer<Void> mReleasedCompleter;
    @SuppressWarnings("WeakerAccess") // synthetic accessor
    final Queue<Integer> mFreeInputBufferIndexQueue = new ArrayDeque<>();
    private final Queue<Completer<InputBuffer>> mAcquisitionQueue = new ArrayDeque<>();
    private final Set<InputBuffer> mInputBufferSet = new HashSet<>();
    @SuppressWarnings("WeakerAccess") // synthetic accessor
    final Set<EncodedDataImpl> mEncodedDataSet = new HashSet<>();
    /*
     * mActivePauseResumeTimeRanges is a queue used to track all active pause/resume time ranges.
     * An active pause/resume range means the latest output buffer still has not exceeded this
     * range, so this range is still needed to check for later output buffers. The first element
     * in the queue is the oldest range and the last element is the newest.
     */
    @SuppressWarnings("WeakerAccess") // synthetic accessor
    final Deque<Range<Long>> mActivePauseResumeTimeRanges = new ArrayDeque<>();
    final Timebase mInputTimebase;
    final TimeProvider mTimeProvider = new SystemTimeProvider();

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    @GuardedBy("mLock")
    EncoderCallback mEncoderCallback = EncoderCallback.EMPTY;
    @SuppressWarnings("WeakerAccess") // synthetic accessor
    @GuardedBy("mLock")
    Executor mEncoderCallbackExecutor = CameraXExecutors.directExecutor();
    @SuppressWarnings("WeakerAccess") // synthetic accessor
    InternalState mState;
    @SuppressWarnings("WeakerAccess") // synthetic accessor
    Range<Long> mStartStopTimeRangeUs = NO_RANGE;
    @SuppressWarnings("WeakerAccess") // synthetic accessor
    long mTotalPausedDurationUs = 0L;
    @SuppressWarnings("WeakerAccess") // synthetic accessor
    boolean mPendingCodecStop = false;
    // The data timestamp that an encoding stops at. If this timestamp is null, it means the
    // encoding hasn't receiving enough data to be stopped.
    @SuppressWarnings("WeakerAccess") // synthetic accessor
    Long mLastDataStopTimestamp = null;
    @SuppressWarnings("WeakerAccess") // synthetic accessor
    Future<?> mStopTimeoutFuture = null;
    private MediaCodecCallback mMediaCodecCallback = null;

    private boolean mIsFlushedAfterEndOfStream = false;
    private boolean mSourceStoppedSignalled = false;
    boolean mMediaCodecEosSignalled = false;

    final EncoderFinder mEncoderFinder = new EncoderFinder();

    /**
     * Creates the encoder with a {@link EncoderConfig}
     *
     * @param executor      the executor suitable for background task
     * @param encoderConfig the encoder config
     * @throws InvalidConfigException when the encoder cannot be configured.
     */
    public EncoderImpl(@NonNull Executor executor, @NonNull EncoderConfig encoderConfig)
            throws InvalidConfigException {
        Preconditions.checkNotNull(executor);
        Preconditions.checkNotNull(encoderConfig);

        mEncoderExecutor = CameraXExecutors.newSequentialExecutor(executor);

        if (encoderConfig instanceof AudioEncoderConfig) {
            mTag = "AudioEncoder";
            mIsVideoEncoder = false;
            mEncoderInput = new ByteBufferInput();
        } else if (encoderConfig instanceof VideoEncoderConfig) {
            mTag = "VideoEncoder";
            mIsVideoEncoder = true;
            mEncoderInput = new SurfaceInput();
        } else {
            throw new InvalidConfigException("Unknown encoder config type");
        }

        mInputTimebase = encoderConfig.getInputTimebase();
        Logger.d(mTag, "mInputTimebase = " + mInputTimebase);
        mMediaFormat = encoderConfig.toMediaFormat();
        Logger.d(mTag, "mMediaFormat = " + mMediaFormat);
        mMediaCodec = mEncoderFinder.findEncoder(mMediaFormat);
        Logger.i(mTag, "Selected encoder: " + mMediaCodec.getName());
        mEncoderInfo = createEncoderInfo(mIsVideoEncoder, mMediaCodec.getCodecInfo(),
                encoderConfig.getMimeType());
        try {
            reset();
        } catch (MediaCodec.CodecException e) {
            throw new InvalidConfigException(e);
        }

        AtomicReference<Completer<Void>> releaseFutureRef = new AtomicReference<>();
        mReleasedFuture = Futures.nonCancellationPropagating(
                CallbackToFutureAdapter.getFuture(completer -> {
                    releaseFutureRef.set(completer);
                    return "mReleasedFuture";
                }));
        mReleasedCompleter = Preconditions.checkNotNull(releaseFutureRef.get());

        setState(CONFIGURED);
    }

    @ExecutedBy("mEncoderExecutor")
    private void reset() {
        mStartStopTimeRangeUs = NO_RANGE;
        mTotalPausedDurationUs = 0L;
        mActivePauseResumeTimeRanges.clear();
        mFreeInputBufferIndexQueue.clear();

        // Cancel incomplete acquisitions if exists.
        for (Completer<InputBuffer> completer : mAcquisitionQueue) {
            completer.setCancelled();
        }
        mAcquisitionQueue.clear();

        mMediaCodec.reset();
        mIsFlushedAfterEndOfStream = false;
        mSourceStoppedSignalled = false;
        mMediaCodecEosSignalled = false;
        mPendingCodecStop = false;
        if (mStopTimeoutFuture != null) {
            mStopTimeoutFuture.cancel(true);
            mStopTimeoutFuture = null;
        }
        if (mMediaCodecCallback != null) {
            mMediaCodecCallback.stop();
        }
        mMediaCodecCallback = new MediaCodecCallback();
        mMediaCodec.setCallback(mMediaCodecCallback);

        mMediaCodec.configure(mMediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);

        if (mEncoderInput instanceof SurfaceInput) {
            ((SurfaceInput) mEncoderInput).resetSurface();
        }
    }

    /** Gets the {@link EncoderInput} of the encoder */
    @Override
    @NonNull
    public EncoderInput getInput() {
        return mEncoderInput;
    }

    @NonNull
    @Override
    public EncoderInfo getEncoderInfo() {
        return mEncoderInfo;
    }

    /**
     * Starts the encoder.
     *
     *
If the encoder is not started yet, it will first trigger
     * {@link EncoderCallback#onEncodeStart}. Then continually invoke the
     * {@link EncoderCallback#onEncodedData} callback until the encoder is paused, stopped or
     * released. It can call {@link #pause} to pause the encoding after started. If the encoder is
     * in paused state, then calling this method will resume the encoding.
     */
    @SuppressWarnings("StatementWithEmptyBody") // to better organize the logic and comments
    @Override
    public void start() {
        final long startTriggerTimeUs = generatePresentationTimeUs();
        mEncoderExecutor.execute(() -> {
            switch (mState) {
                case CONFIGURED:
                    mLastDataStopTimestamp = null;

                    Logger.d(mTag, "Start on " + DebugUtils.readableUs(startTriggerTimeUs));
                    try {
                        if (mIsFlushedAfterEndOfStream) {
                            // If the codec is flushed after an end-of-stream, it was never
                            // signalled that the source stopped, so we will reset the codec
                            // before starting it again.
                            reset();
                        }
                        mStartStopTimeRangeUs = Range.create(startTriggerTimeUs, NO_LIMIT_LONG);
                        mMediaCodec.start();
                    } catch (MediaCodec.CodecException e) {
                        handleEncodeError(e);
                        return;
                    }
                    if (mEncoderInput instanceof ByteBufferInput) {
                        ((ByteBufferInput) mEncoderInput).setActive(true);
                    }
                    setState(STARTED);
                    break;
                case PAUSED:
                    // Resume

                    // The Encoder has been resumed, so reset the stop timestamp flags.
                    mLastDataStopTimestamp = null;

                    final Range<Long> pauseRange = mActivePauseResumeTimeRanges.removeLast();
                    Preconditions.checkState(
                            pauseRange != null && pauseRange.getUpper() == NO_LIMIT_LONG,
                            "There should be a \"pause\" before \"resume\"");
                    final long pauseTimeUs = pauseRange.getLower();
                    mActivePauseResumeTimeRanges.addLast(
                            Range.create(pauseTimeUs, startTriggerTimeUs));
                    // Do not update total paused duration here since current output buffer may
                    // still before the pause range.

                    Logger.d(mTag, "Resume on " + DebugUtils.readableUs(startTriggerTimeUs)
                            + "\nPaused duration = " + DebugUtils.readableUs(
                            (startTriggerTimeUs - pauseTimeUs))
                    );

                    if (!mIsVideoEncoder && DeviceQuirks.get(
                            AudioEncoderIgnoresInputTimestampQuirk.class) != null) {
                        // Do nothing. Since we keep handling audio data in the codec after
                        // paused, we don't have to resume the codec and the input source.
                    } else if (mIsVideoEncoder && DeviceQuirks.get(
                            VideoEncoderSuspendDoesNotIncludeSuspendTimeQuirk.class) != null) {
                        // Do nothing. Since we don't pause the codec when paused, we don't have
                        // to resume the codec.
                    } else {
                        setMediaCodecPaused(false);
                        if (mEncoderInput instanceof ByteBufferInput) {
                            ((ByteBufferInput) mEncoderInput).setActive(true);
                        }
                    }
                    // If this is a video encoder, then request a key frame in order to complete
                    // the resume process as soon as possible in MediaCodec.Callback
                    // .onOutputBufferAvailable().
                    if (mIsVideoEncoder) {
                        requestKeyFrameToMediaCodec();
                    }
                    setState(STARTED);
                    break;
                case STARTED:
                case ERROR:
                case PENDING_START:
                    // Do nothing
                    break;
                case STOPPING:
                case PENDING_START_PAUSED:
                    setState(PENDING_START);
                    break;
                case PENDING_RELEASE:
                case RELEASED:
                    throw new IllegalStateException("Encoder is released");
                default:
                    throw new IllegalStateException("Unknown state: " + mState);
            }
        });
    }

    /**
     * Stops the encoder.
     *
     *
It will trigger {@link EncoderCallback#onEncodeStop} after the last encoded data. It can
     * call {@link #start} to start again.
     */
    @Override
    public void stop() {
        stop(TIMESTAMP_ANY);
    }

    /**
     * Stops the encoder with an expected stop time.
     *
     *
It will trigger {@link EncoderCallback#onEncodeStop} after the last encoded data. It can
     * call {@link #start} to start again.
     *
     *
The encoder will try to provide the last {@link EncodedData} with a timestamp as close
     * as to the given stop timestamp.
     *
     *
Use {@link #stop()} to stop the encoder without specifying expected stop time and let
     * the Encoder to decide.
     *
     * @param expectedStopTimeUs The desired stop time.
     */
    @Override
    public void stop(long expectedStopTimeUs) {
        final long stopTriggerTimeUs = generatePresentationTimeUs();
        mEncoderExecutor.execute(() -> {
            switch (mState) {
                case CONFIGURED:
                case STOPPING:
                case ERROR:
                    // Do nothing
                    break;
                case STARTED:
                case PAUSED:
                    InternalState currentState = mState;
                    setState(STOPPING);
                    final long startTimeUs = mStartStopTimeRangeUs.getLower();
                    if (startTimeUs == NO_LIMIT_LONG) {
                        throw new AssertionError("There should be a \"start\" before \"stop\"");
                    }
                    long stopTimeUs;
                    if (expectedStopTimeUs == TIMESTAMP_ANY) {
                        stopTimeUs = stopTriggerTimeUs;
                    } else if (expectedStopTimeUs < startTimeUs) {
                        // If the recording is stopped immediately after started, it's possible
                        // that the expected stop time is less than the start time because the
                        // encoder is run on different executor. Ignore the expected stop time in
                        // this case so that the recording can be stopped correctly.
                        Logger.w(mTag, "The expected stop time is less than the start time. Use "
                                + "current time as stop time.");
                        stopTimeUs = stopTriggerTimeUs;
                    } else {
                        stopTimeUs = expectedStopTimeUs;
                    }
                    if (stopTimeUs < startTimeUs) {
                        throw new AssertionError("The start time should be before the stop time.");
                    }
                    // Store the stop time. The codec will be stopped after receiving the data
                    // that has a timestamp equal or greater than the stop time.
                    mStartStopTimeRangeUs = Range.create(startTimeUs, stopTimeUs);
                    Logger.d(mTag, "Stop on " + DebugUtils.readableUs(stopTimeUs));
                    // If the Encoder is paused and has received enough data, directly signal
                    // the codec to stop.
                    if (currentState == PAUSED && mLastDataStopTimestamp != null) {
                        signalCodecStop();
                    } else {
                        mPendingCodecStop = true;
                        // If somehow the data doesn't reach the expected timestamp before it
                        // times out, stop the codec so that the Encoder can at least be stopped.
                        // Set mDataStopTimeStamp to be null in order to catch this issue in test.
                        mStopTimeoutFuture =
                                CameraXExecutors.mainThreadExecutor().schedule(
                                        () -> mEncoderExecutor.execute(() -> {
                                            if (mPendingCodecStop) {
                                                Logger.w(mTag,
                                                        "The data didn't reach the expected "
                                                                + "timestamp before timeout, stop"
                                                                + " the codec.");
                                                mLastDataStopTimestamp = null;
                                                signalCodecStop();
                                                mPendingCodecStop = false;
                                            }
                                        }), STOP_TIMEOUT_MS, TimeUnit.MILLISECONDS);
                    }
                    break;
                case PENDING_START:
                case PENDING_START_PAUSED:
                    setState(CONFIGURED);
                    break;
                case PENDING_RELEASE:
                case RELEASED:
                    throw new IllegalStateException("Encoder is released");
                default:
                    throw new IllegalStateException("Unknown state: " + mState);
            }
        });
    }

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    @ExecutedBy("mEncoderExecutor")
    void signalCodecStop() {
        if (mEncoderInput instanceof ByteBufferInput) {
            ((ByteBufferInput) mEncoderInput).setActive(false);
            // Wait for all issued input buffer done to avoid input loss.
            List<ListenableFuture<Void>> futures = new ArrayList<>();
            for (InputBuffer inputBuffer : mInputBufferSet) {
                futures.add(inputBuffer.getTerminationFuture());
            }
            Futures.successfulAsList(futures).addListener(this::signalEndOfInputStream,
                    mEncoderExecutor);
        } else if (mEncoderInput instanceof SurfaceInput) {
            try {
                mMediaCodec.signalEndOfInputStream();
                // On some devices, MediaCodec#signalEndOfInputStream() doesn't work.
                // See b/255209101.
                mMediaCodecEosSignalled = true;
            } catch (MediaCodec.CodecException e) {
                handleEncodeError(e);
            }
        }
    }

    /**
     * Pauses the encoder.
     *
     *
{@code pause} only work between {@link #start} and {@link #stop}. Once the encoder is
     * paused, it will drop the input data until {@link #start} is invoked again.
     */
    @Override
    public void pause() {
        final long pauseTriggerTimeUs = generatePresentationTimeUs();
        mEncoderExecutor.execute(() -> {
            switch (mState) {
                case CONFIGURED:
                case PAUSED:
                case ERROR:
                case STOPPING:
                case PENDING_START_PAUSED:
                    // Do nothing
                    break;
                case PENDING_START:
                    setState(PENDING_START_PAUSED);
                    break;
                case STARTED:
                    // Create and insert a pause/resume range.
                    Logger.d(mTag, "Pause on " + DebugUtils.readableUs(pauseTriggerTimeUs));
                    mActivePauseResumeTimeRanges.addLast(
                            Range.create(pauseTriggerTimeUs, NO_LIMIT_LONG));
                    setState(PAUSED);
                    break;
                case PENDING_RELEASE:
                case RELEASED:
                    throw new IllegalStateException("Encoder is released");
                default:
                    throw new IllegalStateException("Unknown state: " + mState);
            }
        });
    }

    /**
     * Releases the encoder.
     *
     *
Once the encoder is released, it cannot be used anymore. Any other method call after
     * the encoder is released will get {@link IllegalStateException}. If it is in encoding, make
     * sure call {@link #stop} before {@code release} to normally end the stream, or it may get
     * uncertain result if call {@code release} while encoding.
     */
    @Override
    public void release() {
        mEncoderExecutor.execute(() -> {
            switch (mState) {
                case CONFIGURED:
                case STARTED:
                case PAUSED:
                case ERROR:
                    releaseInternal();
                    break;
                case STOPPING:
                case PENDING_START:
                case PENDING_START_PAUSED:
                    setState(PENDING_RELEASE);
                    break;
                case PENDING_RELEASE:
                case RELEASED:
                    // Do nothing
                    break;
                default:
                    throw new IllegalStateException("Unknown state: " + mState);
            }
        });
    }

    /** {@inheritDoc} */
    @NonNull
    @Override
    public ListenableFuture<Void> getReleasedFuture() {
        return mReleasedFuture;
    }

    /**
     * Sends a hint to the encoder that the source has stopped producing data.
     *
     *
This will allow the encoder to reset when it is stopped and no more input data is
     * incoming. This can optimize the time needed to start the next session with
     * {@link #start()} and can regenerate a {@link Surface} on devices that don't support
     * persistent input surfaces.
     */
    public void signalSourceStopped() {
        mEncoderExecutor.execute(() -> {
            mSourceStoppedSignalled = true;
            if (mIsFlushedAfterEndOfStream) {
                mMediaCodec.stop();
                reset();
            }
        });
    }

    @ExecutedBy("mEncoderExecutor")
    private void releaseInternal() {
        if (mIsFlushedAfterEndOfStream) {
            mMediaCodec.stop();
            mIsFlushedAfterEndOfStream = false;
        }

        mMediaCodec.release();

        if (mEncoderInput instanceof SurfaceInput) {
            ((SurfaceInput) mEncoderInput).releaseSurface();
        }

        setState(RELEASED);

        mReleasedCompleter.set(null);
    }

    /**
     * Sets callback to encoder.
     *
     * @param encoderCallback the encoder callback
     * @param executor the callback executor
     */
    @Override
    public void setEncoderCallback(
            @NonNull EncoderCallback encoderCallback,
            @NonNull Executor executor) {
        synchronized (mLock) {
            mEncoderCallback = encoderCallback;
            mEncoderCallbackExecutor = executor;
        }
    }

    /** {@inheritDoc} */
    @Override
    public void requestKeyFrame() {
        mEncoderExecutor.execute(() -> {
            switch (mState) {
                case STARTED:
                    requestKeyFrameToMediaCodec();
                    break;
                case CONFIGURED:
                case PAUSED:
                case ERROR:
                case STOPPING:
                case PENDING_START:
                case PENDING_START_PAUSED:
                    // No-op
                    break;
                case RELEASED:
                case PENDING_RELEASE:
                    throw new IllegalStateException("Encoder is released");
            }
        });
    }

    @ExecutedBy("mEncoderExecutor")
    private void setState(InternalState state) {
        if (mState == state) {
            return;
        }
        Logger.d(mTag, "Transitioning encoder internal state: " + mState + " --> " + state);
        mState = state;
    }

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    @ExecutedBy("mEncoderExecutor")
    void setMediaCodecPaused(boolean paused) {
        Bundle bundle = new Bundle();
        bundle.putInt(MediaCodec.PARAMETER_KEY_SUSPEND, paused ? 1 : 0);
        mMediaCodec.setParameters(bundle);
    }

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    @ExecutedBy("mEncoderExecutor")
    void requestKeyFrameToMediaCodec() {
        Bundle bundle = new Bundle();
        bundle.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
        mMediaCodec.setParameters(bundle);
    }

    @ExecutedBy("mEncoderExecutor")
    private void signalEndOfInputStream() {
        Futures.addCallback(acquireInputBuffer(),
                new FutureCallback<InputBuffer>() {
                    @Override
                    public void onSuccess(InputBuffer inputBuffer) {
                        inputBuffer.setPresentationTimeUs(generatePresentationTimeUs());
                        inputBuffer.setEndOfStream(true);
                        inputBuffer.submit();

                        Futures.addCallback(inputBuffer.getTerminationFuture(),
                                new FutureCallback<Void>() {
                                    @ExecutedBy("mEncoderExecutor")
                                    @Override
                                    public void onSuccess(@Nullable Void result) {
                                        // Do nothing.
                                    }

                                    @ExecutedBy("mEncoderExecutor")
                                    @Override
                                    public void onFailure(@NonNull Throwable t) {
                                        if (t instanceof MediaCodec.CodecException) {
                                            handleEncodeError(
                                                    (MediaCodec.CodecException) t);
                                        } else {
                                            handleEncodeError(EncodeException.ERROR_UNKNOWN,
                                                    t.getMessage(), t);
                                        }
                                    }
                                }, mEncoderExecutor);
                    }

                    @Override
                    public void onFailure(@NonNull Throwable t) {
                        handleEncodeError(EncodeException.ERROR_UNKNOWN,
                                "Unable to acquire InputBuffer.", t);
                    }
                }, mEncoderExecutor);
    }

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    @ExecutedBy("mEncoderExecutor")
    void handleEncodeError(@NonNull MediaCodec.CodecException e) {
        handleEncodeError(EncodeException.ERROR_CODEC, e.getMessage(), e);
    }

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    @ExecutedBy("mEncoderExecutor")
    void handleEncodeError(@EncodeException.ErrorType int error, @Nullable String message,
            @Nullable Throwable throwable) {
        switch (mState) {
            case CONFIGURED:
                // Unable to start MediaCodec. This is a fatal error. Try to reset the encoder.
                notifyError(error, message, throwable);
                reset();
                break;
            case STARTED:
            case PAUSED:
            case STOPPING:
            case PENDING_START_PAUSED:
            case PENDING_START:
            case PENDING_RELEASE:
                setState(ERROR);
                stopMediaCodec(() -> notifyError(error, message, throwable));
                break;
            case ERROR:
                //noinspection ConstantConditions
                Logger.w(mTag, "Get more than one error: " + message + "(" + error + ")",
                        throwable);
                break;
            case RELEASED:
                // Do nothing
                break;
        }
    }

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    void notifyError(@EncodeException.ErrorType int error, @Nullable String message,
            @Nullable Throwable throwable) {
        EncoderCallback callback;
        Executor executor;
        synchronized (mLock) {
            callback = mEncoderCallback;
            executor = mEncoderCallbackExecutor;
        }
        try {
            executor.execute(
                    () -> callback.onEncodeError(new EncodeException(error, message, throwable)));
        } catch (RejectedExecutionException e) {
            Logger.e(mTag, "Unable to post to the supplied executor.", e);
        }
    }

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    @ExecutedBy("mEncoderExecutor")
    void stopMediaCodec(@Nullable Runnable afterStop) {
        /*
         * MediaCodec#stop will free all its input/output ByteBuffers. Therefore, before calling
         * MediaCodec#stop, it must ensure all dispatched EncodedData(output ByteBuffers) and
         * InputBuffer(input ByteBuffers) are complete. Otherwise, the ByteBuffer receiver will
         * get buffer overflow when accessing the ByteBuffers.
         */
        List<ListenableFuture<Void>> futures = new ArrayList<>();
        for (EncodedDataImpl dataToClose : mEncodedDataSet) {
            futures.add(dataToClose.getClosedFuture());
        }
        for (InputBuffer inputBuffer : mInputBufferSet) {
            futures.add(inputBuffer.getTerminationFuture());
        }
        if (!futures.isEmpty()) {
            Logger.d(mTag, "Waiting for resources to return."
                    + " encoded data = " + mEncodedDataSet.size()
                    + ", input buffers = " + mInputBufferSet.size());
        }
        Futures.successfulAsList(futures).addListener(() -> {
            if (!futures.isEmpty()) {
                Logger.d(mTag, "encoded data and input buffers are returned");
            }
            if (mEncoderInput instanceof SurfaceInput && !mSourceStoppedSignalled) {
                // For a SurfaceInput, the codec is in control of de-queuing buffers from the
                // underlying BufferQueue. If we stop the codec, then it will stop de-queuing
                // buffers and the BufferQueue may run out of input buffers, causing the camera
                // pipeline to stall. Instead of stopping, we will flush the codec. Since the
                // codec is operating in asynchronous mode, this will cause the codec to continue
                // to discard buffers. We should have already received the end-of-stream signal on
                // an output buffer at this point, so those buffers are not needed anyways. We will
                // defer resetting the codec until just before starting the codec again.
                mMediaCodec.flush();
                mIsFlushedAfterEndOfStream = true;
            } else {
                // Non-SurfaceInputs give us more control over input buffers. We can directly
                // stop the codec instead of flushing.
                // Additionally, if we already received a signal that the source is stopped, then
                // there shouldn't be new buffers being produced, and we don't need to flush.
                mMediaCodec.stop();
            }
            if (afterStop != null) {
                afterStop.run();
            }
            handleStopped();
        }, mEncoderExecutor);
    }

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    @ExecutedBy("mEncoderExecutor")
    void handleStopped() {
        if (mState == PENDING_RELEASE) {
            releaseInternal();
        } else {
            InternalState oldState = mState;
            if (!mIsFlushedAfterEndOfStream) {
                // Only reset if the codec is stopped (not flushed). If the codec is flushed, we
                // want it to continue to discard buffers. We will reset before starting the
                // codec again.
                reset();
            }
            setState(CONFIGURED);
            if (oldState == PENDING_START || oldState == PENDING_START_PAUSED) {
                start();
                if (oldState == PENDING_START_PAUSED) {
                    pause();
                }
            }
        }
    }

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    @ExecutedBy("mEncoderExecutor")
    void updateTotalPausedDuration(long bufferPresentationTimeUs) {
        while (!mActivePauseResumeTimeRanges.isEmpty()) {
            Range<Long> pauseRange = mActivePauseResumeTimeRanges.getFirst();
            if (bufferPresentationTimeUs > pauseRange.getUpper()) {
                // Later than current pause, remove this pause and update total paused duration.
                mActivePauseResumeTimeRanges.removeFirst();
                mTotalPausedDurationUs += (pauseRange.getUpper() - pauseRange.getLower());
                Logger.d(mTag,
                        "Total paused duration = " + DebugUtils.readableUs(mTotalPausedDurationUs));
            } else {
                break;
            }
        }
    }

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    @ExecutedBy("mEncoderExecutor")
    long getAdjustedTimeUs(@NonNull BufferInfo bufferInfo) {
        long adjustedTimeUs;
        if (mTotalPausedDurationUs > 0L) {
            adjustedTimeUs = bufferInfo.presentationTimeUs - mTotalPausedDurationUs;
        } else {
            adjustedTimeUs = bufferInfo.presentationTimeUs;
        }
        return adjustedTimeUs;
    }

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    @ExecutedBy("mEncoderExecutor")
    boolean isInPauseRange(long timeUs) {
        for (Range<Long> range : mActivePauseResumeTimeRanges) {
            if (range.contains(timeUs)) {
                return true;
            } else if (timeUs < range.getLower()) {
                // Earlier than pause range.
                return false;
            }
            // Later than current pause, keep searching.
        }
        return false;
    }

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    @ExecutedBy("mEncoderExecutor")
    @NonNull
    ListenableFuture<InputBuffer> acquireInputBuffer() {
        switch (mState) {
            case CONFIGURED:
                return Futures.immediateFailedFuture(new IllegalStateException(
                        "Encoder is not started yet."));
            case STARTED:
            case PAUSED:
            case STOPPING:
            case PENDING_START:
            case PENDING_START_PAUSED:
            case PENDING_RELEASE:
                AtomicReference<Completer<InputBuffer>> ref = new AtomicReference<>();
                ListenableFuture<InputBuffer> future = CallbackToFutureAdapter.getFuture(
                        completer -> {
                            ref.set(completer);
                            return "acquireInputBuffer";
                        });
                Completer<InputBuffer> completer = Preconditions.checkNotNull(ref.get());
                mAcquisitionQueue.offer(completer);
                completer.addCancellationListener(() -> mAcquisitionQueue.remove(completer),
                        mEncoderExecutor);
                matchAcquisitionsAndFreeBufferIndexes();
                return future;
            case ERROR:
                return Futures.immediateFailedFuture(new IllegalStateException(
                        "Encoder is in error state."));
            case RELEASED:
                return Futures.immediateFailedFuture(new IllegalStateException(
                        "Encoder is released."));
            default:
                throw new IllegalStateException("Unknown state: " + mState);
        }
    }

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    @ExecutedBy("mEncoderExecutor")
    void matchAcquisitionsAndFreeBufferIndexes() {
        while (!mAcquisitionQueue.isEmpty() && !mFreeInputBufferIndexQueue.isEmpty()) {
            Completer<InputBuffer> completer = requireNonNull(mAcquisitionQueue.poll());
            int bufferIndex = requireNonNull(mFreeInputBufferIndexQueue.poll());

            InputBufferImpl inputBuffer;
            try {
                inputBuffer = new InputBufferImpl(mMediaCodec, bufferIndex);
            } catch (MediaCodec.CodecException e) {
                handleEncodeError(e);
                return;
            }
            if (completer.set(inputBuffer)) {
                mInputBufferSet.add(inputBuffer);
                inputBuffer.getTerminationFuture().addListener(
                        () -> mInputBufferSet.remove(inputBuffer), mEncoderExecutor);
            } else {
                inputBuffer.cancel();
            }
        }
    }

    @NonNull
    private static EncoderInfo createEncoderInfo(boolean isVideoEncoder,
            @NonNull MediaCodecInfo codecInfo, @NonNull String mime) throws InvalidConfigException {
        return isVideoEncoder ? new VideoEncoderInfoImpl(codecInfo, mime)
                : new AudioEncoderInfoImpl(codecInfo, mime);
    }

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    long generatePresentationTimeUs() {
        return mTimeProvider.uptimeUs();
    }

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    static boolean isKeyFrame(@NonNull BufferInfo bufferInfo) {
        return (bufferInfo.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) != 0;
    }

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    static boolean hasEndOfStreamFlag(@NonNull BufferInfo bufferInfo) {
        return (bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
    }

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
    class MediaCodecCallback extends MediaCodec.Callback {
        @Nullable
        private final VideoTimebaseConverter mVideoTimestampConverter;

        private boolean mHasSendStartCallback = false;
        private boolean mHasFirstData = false;
        private boolean mHasEndData = false;
        /** The last presentation time of BufferInfo without modified. */
        private long mLastPresentationTimeUs = 0L;
        /**
         * The last sent presentation time of BufferInfo. The value could be adjusted by total
         * pause duration.
         */
        private long mLastSentAdjustedTimeUs = 0L;
        private boolean mIsOutputBufferInPauseState = false;
        private boolean mIsKeyFrameRequired = false;
        private boolean mStopped = false;

        MediaCodecCallback() {
            if (mIsVideoEncoder) {
                Timebase inputTimebase;
                if (DeviceQuirks.get(CameraUseInconsistentTimebaseQuirk.class) != null) {
                    inputTimebase = null;
                } else {
                    inputTimebase = mInputTimebase;
                }
                mVideoTimestampConverter = new VideoTimebaseConverter(mTimeProvider, inputTimebase);
            } else {
                mVideoTimestampConverter = null;
            }
        }

        @Override
        public void onInputBufferAvailable(MediaCodec mediaCodec, int index) {
            mEncoderExecutor.execute(() -> {
                if (mStopped) {
                    Logger.w(mTag, "Receives input frame after codec is reset.");
                    return;
                }
                switch (mState) {
                    case STARTED:
                    case PAUSED:
                    case STOPPING:
                    case PENDING_START:
                    case PENDING_START_PAUSED:
                    case PENDING_RELEASE:
                        mFreeInputBufferIndexQueue.offer(index);
                        matchAcquisitionsAndFreeBufferIndexes();
                        break;
                    case CONFIGURED:
                    case ERROR:
                    case RELEASED:
                        // Do nothing
                        break;
                    default:
                        throw new IllegalStateException("Unknown state: " + mState);
                }
            });
        }

        @Override
        public void onOutputBufferAvailable(@NonNull MediaCodec mediaCodec, int index,
                @NonNull BufferInfo bufferInfo) {
            mEncoderExecutor.execute(() -> {
                if (mStopped) {
                    Logger.w(mTag, "Receives frame after codec is reset.");
                    return;
                }
                switch (mState) {
                    case STARTED:
                    case PAUSED:
                    case STOPPING:
                    case PENDING_START:
                    case PENDING_START_PAUSED:
                    case PENDING_RELEASE:
                        final EncoderCallback encoderCallback;
                        final Executor executor;
                        synchronized (mLock) {
                            encoderCallback = mEncoderCallback;
                            executor = mEncoderCallbackExecutor;
                        }

                        if (DEBUG) {
                            Logger.d(mTag, DebugUtils.readableBufferInfo(bufferInfo));
                        }

                        // Handle start of stream
                        if (!mHasSendStartCallback) {
                            mHasSendStartCallback = true;
                            try {
                                executor.execute(encoderCallback::onEncodeStart);
                            } catch (RejectedExecutionException e) {
                                Logger.e(mTag, "Unable to post to the supplied executor.", e);
                            }
                        }

                        if (checkBufferInfo(bufferInfo)) {
                            if (!mHasFirstData) {
                                mHasFirstData = true;
                            }
                            BufferInfo outBufferInfo = resolveOutputBufferInfo(bufferInfo);
                            mLastSentAdjustedTimeUs = outBufferInfo.presentationTimeUs;
                            try {
                                EncodedDataImpl encodedData = new EncodedDataImpl(mediaCodec, index,
                                        outBufferInfo);
                                sendEncodedData(encodedData, encoderCallback, executor);
                            } catch (MediaCodec.CodecException e) {
                                handleEncodeError(e);
                                return;
                            }
                        } else {
                            // Not necessary to return fake buffer
                            if (index != FAKE_BUFFER_INDEX) {
                                try {
                                    mMediaCodec.releaseOutputBuffer(index, false);
                                } catch (MediaCodec.CodecException e) {
                                    handleEncodeError(e);
                                    return;
                                }
                            }
                        }

                        // Handle end of stream
                        if (!mHasEndData && isEndOfStream(bufferInfo)) {
                            mHasEndData = true;
                            stopMediaCodec(() -> {
                                if (mState == ERROR) {
                                    // Error occur during stopping.
                                    return;
                                }
                                try {
                                    executor.execute(encoderCallback::onEncodeStop);
                                } catch (RejectedExecutionException e) {
                                    Logger.e(mTag, "Unable to post to the supplied executor.", e);
                                }
                            });
                        }
                        break;
                    case CONFIGURED:
                    case ERROR:
                    case RELEASED:
                        // Do nothing
                        break;
                    default:
                        throw new IllegalStateException("Unknown state: " + mState);
                }
            });
        }

        @ExecutedBy("mEncoderExecutor")
        @NonNull
        private BufferInfo resolveOutputBufferInfo(@NonNull BufferInfo bufferInfo) {
            long adjustedTimeUs = getAdjustedTimeUs(bufferInfo);
            if (bufferInfo.presentationTimeUs == adjustedTimeUs) {
                return bufferInfo;
            }

            // If adjusted time <= last sent time, the buffer should have been detected and
            // dropped in checkBufferInfo().
            Preconditions.checkState(adjustedTimeUs > mLastSentAdjustedTimeUs);
            if (DEBUG) {
                Logger.d(mTag, "Adjust bufferInfo.presentationTimeUs to "
                        + DebugUtils.readableUs(adjustedTimeUs));
            }
            BufferInfo newBufferInfo = new BufferInfo();
            newBufferInfo.set(bufferInfo.offset, bufferInfo.size, adjustedTimeUs, bufferInfo.flags);
            return newBufferInfo;
        }

        @ExecutedBy("mEncoderExecutor")
        private void sendEncodedData(@NonNull EncodedDataImpl encodedData,
                @NonNull EncoderCallback callback, @NonNull Executor executor) {
            mEncodedDataSet.add(encodedData);
            Futures.addCallback(encodedData.getClosedFuture(),
                    new FutureCallback<Void>() {
                        @Override
                        public void onSuccess(@Nullable Void result) {
                            mEncodedDataSet.remove(encodedData);
                        }

                        @Override
                        public void onFailure(@NonNull Throwable t) {
                            mEncodedDataSet.remove(encodedData);
                            if (t instanceof MediaCodec.CodecException) {
                                handleEncodeError(
                                        (MediaCodec.CodecException) t);
                            } else {
                                handleEncodeError(EncodeException.ERROR_UNKNOWN,
                                        t.getMessage(), t);
                            }
                        }
                    }, mEncoderExecutor);
            try {
                executor.execute(() -> callback.onEncodedData(encodedData));
            } catch (RejectedExecutionException e) {
                Logger.e(mTag, "Unable to post to the supplied executor.", e);
                encodedData.close();
            }
        }

        /**
         * Checks the {@link BufferInfo} and updates related states.
         *
         * @return {@code true} if the buffer is valid, otherwise {@code false}.
         */
        @ExecutedBy("mEncoderExecutor")
        private boolean checkBufferInfo(@NonNull BufferInfo bufferInfo) {
            if (mHasEndData) {
                Logger.d(mTag, "Drop buffer by already reach end of stream.");
                return false;
            }

            if (bufferInfo.size <= 0) {
                Logger.d(mTag, "Drop buffer by invalid buffer size.");
                return false;
            }

            // Sometimes the codec config data was notified by output callback, they should have
            // been sent out by onOutputFormatChanged(), so ignore it.
            if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
                Logger.d(mTag, "Drop buffer by codec config.");
                return false;
            }

            if (mVideoTimestampConverter != null) {
                bufferInfo.presentationTimeUs =
                        mVideoTimestampConverter.convertToUptimeUs(bufferInfo.presentationTimeUs);
            }

            // MediaCodec may send out of order buffer
            if (bufferInfo.presentationTimeUs <= mLastPresentationTimeUs) {
                Logger.d(mTag, "Drop buffer by out of order buffer from MediaCodec.");
                return false;
            }
            mLastPresentationTimeUs = bufferInfo.presentationTimeUs;

            // Ignore buffers are not in start/stop range. One situation is to ignore outdated
            // frames when using the Surface of MediaCodec#createPersistentInputSurface. After
            // the persistent Surface stops, it will keep a small number of old frames in its
            // buffer, and send those old frames in the next startup.
            if (!mStartStopTimeRangeUs.contains(bufferInfo.presentationTimeUs)) {
                Logger.d(mTag, "Drop buffer by not in start-stop range.");
                // If data hasn't reached the expected stop timestamp, set the stop timestamp.
                if (mPendingCodecStop
                        && bufferInfo.presentationTimeUs >= mStartStopTimeRangeUs.getUpper()) {
                    if (mStopTimeoutFuture != null) {
                        mStopTimeoutFuture.cancel(true);
                    }
                    mLastDataStopTimestamp = bufferInfo.presentationTimeUs;
                    signalCodecStop();
                    mPendingCodecStop = false;
                }
                return false;
            }

            if (updatePauseRangeStateAndCheckIfBufferPaused(bufferInfo)) {
                Logger.d(mTag, "Drop buffer by pause.");
                return false;
            }

            // We should check if the adjusted time is valid. see b/189114207.
            if (getAdjustedTimeUs(bufferInfo) <= mLastSentAdjustedTimeUs) {
                Logger.d(mTag, "Drop buffer by adjusted time is less than the last sent time.");
                if (mIsVideoEncoder && isKeyFrame(bufferInfo)) {
                    mIsKeyFrameRequired = true;
                }
                return false;
            }

            if (!mHasFirstData && !mIsKeyFrameRequired && mIsVideoEncoder) {
                mIsKeyFrameRequired = true;
            }

            if (mIsKeyFrameRequired) {
                if (!isKeyFrame(bufferInfo)) {
                    Logger.d(mTag, "Drop buffer by not a key frame.");
                    requestKeyFrameToMediaCodec();
                    return false;
                }
                mIsKeyFrameRequired = false;
            }

            return true;
        }

        @ExecutedBy("mEncoderExecutor")
        private boolean isEndOfStream(@NonNull BufferInfo bufferInfo) {
            return hasEndOfStreamFlag(bufferInfo) || isEosSignalledAndStopTimeReached(bufferInfo);
        }

        @ExecutedBy("mEncoderExecutor")
        private boolean isEosSignalledAndStopTimeReached(@NonNull BufferInfo bufferInfo) {
            return mMediaCodecEosSignalled
                    && bufferInfo.presentationTimeUs > mStartStopTimeRangeUs.getUpper();
        }

        @SuppressWarnings("StatementWithEmptyBody") // to better organize the logic and comments
        @ExecutedBy("mEncoderExecutor")
        private boolean updatePauseRangeStateAndCheckIfBufferPaused(
                @NonNull BufferInfo bufferInfo) {
            updateTotalPausedDuration(bufferInfo.presentationTimeUs);
            boolean isInPauseRange = isInPauseRange(bufferInfo.presentationTimeUs);
            if (!mIsOutputBufferInPauseState && isInPauseRange) {
                Logger.d(mTag, "Switch to pause state");
                // From resume to pause
                mIsOutputBufferInPauseState = true;

                // Invoke paused callback
                Executor executor;
                EncoderCallback encoderCallback;
                synchronized (mLock) {
                    executor = mEncoderCallbackExecutor;
                    encoderCallback = mEncoderCallback;
                }
                executor.execute(encoderCallback::onEncodePaused);

                // We must ensure that the current state is PAUSED before we stop the input
                // source and pause the codec. This is because start() may be called before the
                // output buffer reaches the pause range.
                if (mState == PAUSED) {
                    if (!mIsVideoEncoder && DeviceQuirks.get(
                            AudioEncoderIgnoresInputTimestampQuirk.class) != null) {
                        // Do nothing, which means keep handling audio data in the codec.
                    } else if (mIsVideoEncoder && DeviceQuirks.get(
                            VideoEncoderSuspendDoesNotIncludeSuspendTimeQuirk.class) != null) {
                        // Do nothing, which means don't pause the codec.
                    } else {
                        if (mEncoderInput instanceof ByteBufferInput) {
                            ((ByteBufferInput) mEncoderInput).setActive(false);
                        }
                        setMediaCodecPaused(true);
                    }
                }

                // An encoding session could be pause/resume for multiple times. So a later pause
                // should overwrite the previous data stop time.
                mLastDataStopTimestamp = bufferInfo.presentationTimeUs;
                // If the encoder has been stopped before the data enters pause period, stop the
                // codec directly.
                if (mPendingCodecStop) {
                    if (mStopTimeoutFuture != null) {
                        mStopTimeoutFuture.cancel(true);
                    }
                    signalCodecStop();
                    mPendingCodecStop = false;
                }
            } else if (mIsOutputBufferInPauseState && !isInPauseRange) {
                // From pause to resume
                Logger.d(mTag, "Switch to resume state");
                mIsOutputBufferInPauseState = false;
                if (mIsVideoEncoder && !isKeyFrame(bufferInfo)) {
                    mIsKeyFrameRequired = true;
                }
            }

            return mIsOutputBufferInPauseState;
        }

        @Override
        public void onError(@NonNull MediaCodec mediaCodec, @NonNull MediaCodec.CodecException e) {
            mEncoderExecutor.execute(() -> {
                switch (mState) {
                    case STARTED:
                    case PAUSED:
                    case STOPPING:
                    case PENDING_START:
                    case PENDING_START_PAUSED:
                    case PENDING_RELEASE:
                        handleEncodeError(e);
                        break;
                    case CONFIGURED:
                    case ERROR:
                    case RELEASED:
                        // Do nothing
                        break;
                    default:
                        throw new IllegalStateException("Unknown state: " + mState);
                }
            });
        }

        @Override
        public void onOutputFormatChanged(@NonNull MediaCodec mediaCodec,
                @NonNull MediaFormat mediaFormat) {
            mEncoderExecutor.execute(() -> {
                if (mStopped) {
                    Logger.w(mTag, "Receives onOutputFormatChanged after codec is reset.");
                    return;
                }
                switch (mState) {
                    case STARTED:
                    case PAUSED:
                    case STOPPING:
                    case PENDING_START:
                    case PENDING_START_PAUSED:
                    case PENDING_RELEASE:
                        EncoderCallback encoderCallback;
                        Executor executor;
                        synchronized (mLock) {
                            encoderCallback = mEncoderCallback;
                            executor = mEncoderCallbackExecutor;
                        }
                        try {
                            executor.execute(
                                    () -> encoderCallback.onOutputConfigUpdate(() -> mediaFormat));
                        } catch (RejectedExecutionException e) {
                            Logger.e(mTag, "Unable to post to the supplied executor.", e);
                        }
                        break;
                    case CONFIGURED:
                    case ERROR:
                    case RELEASED:
                        // Do nothing
                        break;
                    default:
                        throw new IllegalStateException("Unknown state: " + mState);
                }
            });
        }

        /** Stop process further frame output. */
        @ExecutedBy("mEncoderExecutor")
        void stop() {
            mStopped = true;
        }
    }

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
    class SurfaceInput implements Encoder.SurfaceInput {

        private final Object mLock = new Object();

        @GuardedBy("mLock")
        private Surface mSurface;

        @GuardedBy("mLock")
        private final Set<Surface> mObsoleteSurfaces = new HashSet<>();

        @GuardedBy("mLock")
        private OnSurfaceUpdateListener mSurfaceUpdateListener;

        @GuardedBy("mLock")
        private Executor mSurfaceUpdateExecutor;

        /**
         * Sets the surface update listener.
         *
         * @param executor the executor to invoke the listener
         * @param listener the surface update listener
         */
        @Override
        public void setOnSurfaceUpdateListener(@NonNull Executor executor,
                @NonNull OnSurfaceUpdateListener listener) {
            Surface surface;
            synchronized (mLock) {
                mSurfaceUpdateListener = Preconditions.checkNotNull(listener);
                mSurfaceUpdateExecutor = Preconditions.checkNotNull(executor);
                surface = mSurface;
            }
            if (surface != null) {
                notifySurfaceUpdate(executor, listener, surface);
            }
        }

        @SuppressLint("NewApi")
        void resetSurface() {
            Surface surface;
            Executor executor;
            OnSurfaceUpdateListener listener;
            EncoderNotUsePersistentInputSurfaceQuirk quirk = DeviceQuirks.get(
                    EncoderNotUsePersistentInputSurfaceQuirk.class);
            synchronized (mLock) {
                if (quirk == null) {
                    if (mSurface == null) {
                        mSurface = Api23Impl.createPersistentInputSurface();
                        surface = mSurface;
                    } else {
                        surface = null;
                    }
                    Api23Impl.setInputSurface(mMediaCodec, mSurface);
                } else {
                    if (mSurface != null) {
                        mObsoleteSurfaces.add(mSurface);
                    }
                    mSurface = mMediaCodec.createInputSurface();
                    surface = mSurface;
                }
                listener = mSurfaceUpdateListener;
                executor = mSurfaceUpdateExecutor;
            }
            if (surface != null && listener != null && executor != null) {
                notifySurfaceUpdate(executor, listener, surface);
            }
        }

        void releaseSurface() {
            Surface surface;
            Set<Surface> obsoleteSurfaces;
            synchronized (mLock) {
                surface = mSurface;
                mSurface = null;
                obsoleteSurfaces = new HashSet<>(mObsoleteSurfaces);
                mObsoleteSurfaces.clear();
            }
            if (surface != null) {
                surface.release();
            }
            for (Surface obsoleteSurface : obsoleteSurfaces) {
                obsoleteSurface.release();
            }
        }

        private void notifySurfaceUpdate(@NonNull Executor executor,
                @NonNull OnSurfaceUpdateListener listener, @NonNull Surface surface) {
            try {
                executor.execute(() -> listener.onSurfaceUpdate(surface));
            } catch (RejectedExecutionException e) {
                Logger.e(mTag, "Unable to post to the supplied executor.", e);
            }
        }
    }

    @SuppressWarnings("WeakerAccess") // synthetic accessor
    class ByteBufferInput implements Encoder.ByteBufferInput {

        private final Map<Observer<? super State>, Executor> mStateObservers =
                new LinkedHashMap<>();

        private State mBufferProviderState = State.INACTIVE;

        private final List<ListenableFuture<InputBuffer>> mAcquisitionList = new ArrayList<>();

        /** {@inheritDoc} */
        @NonNull
        @Override
        public ListenableFuture<State> fetchData() {
            return CallbackToFutureAdapter.getFuture(completer -> {
                mEncoderExecutor.execute(() -> completer.set(mBufferProviderState));
                return "fetchData";
            });
        }

        /** {@inheritDoc} */
        @NonNull
        @Override
        public ListenableFuture<InputBuffer> acquireBuffer() {
            return CallbackToFutureAdapter.getFuture(completer -> {
                mEncoderExecutor.execute(() -> {
                    if (mBufferProviderState == State.ACTIVE) {
                        ListenableFuture<InputBuffer> future = acquireInputBuffer();
                        Futures.propagate(future, completer);
                        // Cancel by outer, also cancel internal future.
                        completer.addCancellationListener(() -> cancelInputBuffer(future),
                                CameraXExecutors.directExecutor());

                        // Keep tracking the acquisition by internal future. Once the provider state
                        // transition to inactive, cancel the internal future can also send signal
                        // to outer future since we propagate the internal result to the completer.
                        mAcquisitionList.add(future);
                        future.addListener(() -> mAcquisitionList.remove(future), mEncoderExecutor);
                    } else if (mBufferProviderState == State.INACTIVE) {
                        completer.setException(
                                new IllegalStateException("BufferProvider is not active."));
                    } else {
                        completer.setException(
                                new IllegalStateException(
                                        "Unknown state: " + mBufferProviderState));
                    }
                });
                return "acquireBuffer";
            });
        }

        private void cancelInputBuffer(@NonNull ListenableFuture<InputBuffer> inputBufferFuture) {
            if (!inputBufferFuture.cancel(true)) {
                // Not able to cancel the future, need to cancel the input buffer as possible.
                Preconditions.checkState(inputBufferFuture.isDone());
                try {
                    inputBufferFuture.get().cancel();
                } catch (ExecutionException | InterruptedException | CancellationException e) {
                    Logger.w(mTag, "Unable to cancel the input buffer: " + e);
                }
            }
        }

        /** {@inheritDoc} */
        @Override
        public void addObserver(@NonNull Executor executor,
                @NonNull Observer<? super State> observer) {
            mEncoderExecutor.execute(() -> {
                mStateObservers.put(Preconditions.checkNotNull(observer),
                        Preconditions.checkNotNull(executor));
                final State state = mBufferProviderState;
                executor.execute(() -> observer.onNewData(state));
            });
        }

        /** {@inheritDoc} */
        @Override
        public void removeObserver(@NonNull Observer<? super State> observer) {
            mEncoderExecutor.execute(
                    () -> mStateObservers.remove(Preconditions.checkNotNull(observer)));
        }

        @ExecutedBy("mEncoderExecutor")
        void setActive(boolean isActive) {
            final State newState = isActive ? State.ACTIVE : State.INACTIVE;
            if (mBufferProviderState == newState) {
                return;
            }
            mBufferProviderState = newState;

            if (newState == State.INACTIVE) {
                for (ListenableFuture<InputBuffer> future : mAcquisitionList) {
                    future.cancel(true);
                }
                mAcquisitionList.clear();
            }

            for (Map.Entry<Observer<? super State>, Executor> entry : mStateObservers.entrySet()) {
                try {
                    entry.getValue().execute(() -> entry.getKey().onNewData(newState));
                } catch (RejectedExecutionException e) {
                    Logger.e(mTag, "Unable to post to the supplied executor.", e);
                }
            }
        }
    }

    /**
     * Nested class to avoid verification errors for methods introduced in Android 6.0 (API 23).
     */
    @RequiresApi(23)
    private static class Api23Impl {

        private Api23Impl() {
        }

        @DoNotInline
        @NonNull
        static Surface createPersistentInputSurface() {
            return MediaCodec.createPersistentInputSurface();
        }

        @DoNotInline
        static void setInputSurface(@NonNull MediaCodec mediaCodec, @NonNull Surface surface) {
            mediaCodec.setInputSurface(surface);
        }
    }
}


text:
<#
.SYNOPSIS
Pulls the version of PS 'Core' available on the web and compares it to the running version

.DESCRIPTION
Just a quick function to poll the MS Github site for the current version of PowerShell 'Core'.
Then it compares that version against what's running and let's you know if this is an
older version. Handy, no?

BTW ... PowerShell 'Core' will _always_ be newer than Windows PowerShell, so bear that in mind.

Also, with PowerShell 7, Microsoft has dropped the 'Core' postfix. I, however, am leaving it
in this script to maintain the "separation" between Windows PowerShell and "Core". Just a
little differentiation between friends.

.PARAMETER Quiet
Don't show the Progress Bar as it queries the website

.PARAMETER ReleaseInfo
Show the release info / change log provided from the url

.PARAMETER NoObject
Don't output the version object

.LINK
http://www.virtu-al.net/2017/03/27/powershell-core-date/
#>

param (
	[switch] $Quiet = $false,
	[switch] $ReleaseInfo = $false,
	[switch] $NoObject = $false
)

$PSCoreURI = 'https://github.com/powershell/powershell'

if ($PSVersionTable.PSVersion.Major -lt 6) {
	if (-not $Quiet) {
		Write-Host "This is Windows Powershell $($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor) - PS 'Core' will always be newer than this." -ForegroundColor White
		Write-Host "  PS 'Core' is available at $PSCoreURI" -ForegroundColor Green
	}
} else {
	#Using this to get rid of the nasty output Invoke-WebRequest gives you in PowerShell on the Mac
	if ($Quiet) {
		$progress = $ProgressPreference
		$ProgressPreference = "SilentlyContinue"
	}

	Write-Host "Current Version of PowerShell 'Core' is $($PSVersionTable.PSVersion.ToString())"  -ForegroundColor White
	if (($PSVersionTable.PSVersion -match 'rc') -or ($PSVersionTable.PSVersion -match 'preview')) {
		Write-Host "  This is not a release version"  -ForegroundColor Yellow
	}
	$JSON = Invoke-WebRequest 'https://api.github.com/repos/powershell/powershell/releases/latest' | ConvertFrom-Json
	if ($PSVersionTable.GitCommitId) {
		if (($JSON.tag_name -replace '\D', '') -notmatch ($PSVersionTable.GitCommitId -replace '\D', '')) {
			Write-Host "Latest official PowerShell release version is $($JSON.tag_name)"  -ForegroundColor White
			Write-Host "  $PSCoreURI" -ForegroundColor Green
			Write-Host 'One Line Install: iex "& { $(irm https://aka.ms/install-powershell.ps1) } -UseMSI"' -ForegroundColor White
			if ($ReleaseInfo) {
				Write-Host ''
				Write-Host $JSON.body
			}
		} else {
			if (-not $Quiet) { Write-Host "  PowerShell 'Core' is currently up to date." -ForegroundColor Green }
		}
	}
	if ($Quiet) {
		$ProgressPreference = $progress
	}
}
if (-not $NoObject) { $PSVersionTable.PSVersion } else { write-host '' }

if ($ReleaseInfo) {
	Write-Host ''
	Write-Host $JSON.body
}


text:
package com.beanu.l2_shareutil.login.result;

import android.text.TextUtils;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * Created by shaohui on 2016/12/1.
 */

public class QQUser extends BaseUser {

    private String qZoneHeadImage;

    private String qZoneHeadImageLarge;

    public static QQUser parse(String openId, JSONObject jsonObject) throws JSONException {
        QQUser user = new QQUser();
        user.setNickname(jsonObject.getString("nickname"));
        user.setOpenId(openId);
        user.setSex(TextUtils.equals("男", jsonObject.getString("gender")) ? 1 : 2);
        user.setHeadImageUrl(jsonObject.getString("figureurl_qq_1"));
        user.setHeadImageUrlLarge(jsonObject.getString("figureurl_qq_2"));
        user.setqZoneHeadImage(jsonObject.getString("figureurl_1"));
        user.setqZoneHeadImageLarge(jsonObject.getString("figureurl_2"));

        return user;
    }

    public String getqZoneHeadImage() {
        return qZoneHeadImage;
    }

    public void setqZoneHeadImage(String qZoneHeadImage) {
        this.qZoneHeadImage = qZoneHeadImage;
    }

    public String getqZoneHeadImageLarge() {
        return qZoneHeadImageLarge;
    }

    public void setqZoneHeadImageLarge(String qZoneHeadImageLarge) {
        this.qZoneHeadImageLarge = qZoneHeadImageLarge;
    }
}


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>org.ogcs.netty.impl</title>
<meta name="date" content="2017-07-08">
<link rel="stylesheet" type="text/css" href="../../../../stylesheet.css" title="Style">

org.ogcs.netty.impl

类

TcpProtocolClient

TcpProtocolServer

UdpProtocol


text:
module Types
  class MergeRequestStateEnum < IssuableStateEnum
    graphql_name 'MergeRequestState'
    description 'State of a GitLab merge request'

    value 'merged'
  end
end


text:
<?php

namespace Google\Service\Datastore;

class GoogleDatastoreAdminV1MigrationStateEvent extends \Google\Model
{
  /**
   * @var string
   */
  public $state;

  /**
   * @param string
   */
  public function setState($state)
  {
    $this->state = $state;
  }
  /**
   * @return string
   */
  public function getState()
  {
    return $this->state;
  }
}

// Adding a class alias for backwards compatibility with the previous class name.
class_alias(GoogleDatastoreAdminV1MigrationStateEvent::class, 'Google_Service_Datastore_GoogleDatastoreAdminV1MigrationStateEvent');


text:
ifeq ($(shell uname -s), Darwin)
  seder := sed -i ".bak"
else
  seder := sed -i
endif

VER=$(shell grep version package.json | sed "s/[a-z \":,]*//g")

PATH := node_modules/.bin:$(PATH)
SHELL := /bin/bash

build: directories
	@find src -name '*.coffee' | xargs coffee -c -o dist
	@find test -name '*.coffee' | xargs coffee -c -o test

	@uglifyjs -o dist/period.min.js dist/period.js

	@$(seder) "s/  \"version\": [0-9.:\",]*/  \"version\": \"${VER}\",/g" bower.json

configure:
	@npm install

directories:
	@mkdir -p dist

bench: build
	@node test/period.bench.js

test: build
	@npm test

lint: build
	@coffeelint src test

coverage: build
	@mocha --require blanket -R html-cov > test/coverage.html

coveralls: build
	@mocha --require blanket -R mocha-lcov-reporter | coveralls