Android Open Source - kickflip-android-sdk Android Encoder






From Project

Back to project page kickflip-android-sdk.

License

The source code is released under:

Apache License

If you think the Android project kickflip-android-sdk listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package io.kickflip.sdk.av;
/*w ww . j av a 2 s.c  om*/
import android.annotation.TargetApi;
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;

import java.nio.ByteBuffer;

import static io.kickflip.sdk.Kickflip.isKitKat;

/**
 * @hide
 */
public abstract class AndroidEncoder {
    private final static String TAG = "AndroidEncoder";
    private final static boolean VERBOSE = false;

    protected Muxer mMuxer;
    protected MediaCodec mEncoder;
    protected MediaCodec.BufferInfo mBufferInfo;
    protected int mTrackIndex;
    protected volatile boolean mForceEos = false;
    int mEosSpinCount = 0;
    final int MAX_EOS_SPINS = 10;

    /**
     * This method should be called before the last input packet is queued
     * Some devices don't honor MediaCodec#signalEndOfInputStream
     * e.g: Google Glass
     */
    public void signalEndOfStream() {
        mForceEos = true;
    }

    public void release(){
        if(mMuxer != null)
            mMuxer.onEncoderReleased(mTrackIndex);
        if (mEncoder != null) {
            mEncoder.stop();
            mEncoder.release();
            mEncoder = null;
            if (VERBOSE) Log.i(TAG, "Released encoder");
        }
    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    public void adjustBitrate(int targetBitrate){
        if(isKitKat() && mEncoder != null){
            Bundle bitrate = new Bundle();
            bitrate.putInt(MediaCodec.PARAMETER_KEY_VIDEO_BITRATE, targetBitrate);
            mEncoder.setParameters(bitrate);
        }else if (!isKitKat()) {
            Log.w(TAG, "Ignoring adjustVideoBitrate call. This functionality is only available on Android API 19+");
        }
    }

    public void drainEncoder(boolean endOfStream) {
        if (endOfStream && VERBOSE) {
            if (isSurfaceInputEncoder()) {
                Log.i(TAG, "final video drain");
            } else {
                Log.i(TAG, "final audio drain");
            }
        }
        synchronized (mMuxer){
            final int TIMEOUT_USEC = 1000;
            if (VERBOSE) Log.d(TAG, "drainEncoder(" + endOfStream + ") track: " + mTrackIndex);

            if (endOfStream) {
                if (VERBOSE) Log.d(TAG, "sending EOS to encoder for track " + mTrackIndex);
//                When all target devices honor MediaCodec#signalEndOfInputStream, return to this method
//                if(isSurfaceInputEncoder()){
//                    if (VERBOSE) Log.i(TAG, "signalEndOfInputStream for track " + mTrackIndex);
//                    mEncoder.signalEndOfInputStream();
//                    // Note: This method isn't honored on certain devices including Google Glass
//                }
            }

            ByteBuffer[] encoderOutputBuffers = mEncoder.getOutputBuffers();
            while (true) {
                int encoderStatus = mEncoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);
                if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
                    // no output available yet
                    if (!endOfStream) {
                        break;      // out of while
                    } else {
                        mEosSpinCount++;
                        if (mEosSpinCount > MAX_EOS_SPINS) {
                            if (VERBOSE) Log.i(TAG, "Force shutting down Muxer");
                            mMuxer.forceStop();
                            break;
                        }
                        if (VERBOSE) Log.d(TAG, "no output available, spinning to await EOS");
                    }
                } else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
                    // not expected for an encoder
                    encoderOutputBuffers = mEncoder.getOutputBuffers();
                 } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                    // should happen before receiving buffers, and should only happen once
                    MediaFormat newFormat = mEncoder.getOutputFormat();
                    if (VERBOSE) Log.d(TAG, "encoder output format changed: " + newFormat);

                    // now that we have the Magic Goodies, start the muxer
                    mTrackIndex = mMuxer.addTrack(newFormat);
                    // Muxer is responsible for starting/stopping itself
                    // based on knowledge of expected # tracks
                } else if (encoderStatus < 0) {
                    Log.w(TAG, "unexpected result from encoder.dequeueOutputBuffer: " +
                            encoderStatus);
                    // let's ignore it
                } else {
                    ByteBuffer encodedData = encoderOutputBuffers[encoderStatus];
                    if (encodedData == null) {
                        throw new RuntimeException("encoderOutputBuffer " + encoderStatus +
                                " was null");
                    }

                    if (mBufferInfo.size >= 0) {    // Allow zero length buffer for purpose of sending 0 size video EOS Flag
                        // adjust the ByteBuffer values to match BufferInfo (not needed?)
                        encodedData.position(mBufferInfo.offset);
                        encodedData.limit(mBufferInfo.offset + mBufferInfo.size);
                        if (mForceEos) {
                            mBufferInfo.flags = mBufferInfo.flags | MediaCodec.BUFFER_FLAG_END_OF_STREAM;
                            Log.i(TAG, "Forcing EOS");
                        }
                        // It is the muxer's responsibility to release encodedData
                        mMuxer.writeSampleData(mEncoder, mTrackIndex, encoderStatus, encodedData, mBufferInfo);
                        if (VERBOSE) {
                            Log.d(TAG, "sent " + mBufferInfo.size + " bytes to muxer, \t ts=" +
                                    mBufferInfo.presentationTimeUs + "track " + mTrackIndex);
                        }
                    }

                    if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                        if (!endOfStream) {
                            Log.w(TAG, "reached end of stream unexpectedly");
                        } else {
                            if (VERBOSE) Log.d(TAG, "end of stream reached for track " + mTrackIndex);
                        }
                        break;      // out of while
                    }
                }
            }
            if (endOfStream && VERBOSE ) {
                if (isSurfaceInputEncoder()) {
                    Log.i(TAG, "final video drain complete");
                } else {
                    Log.i(TAG, "final audio drain complete");
                }
            }
        }
    }

    protected abstract boolean isSurfaceInputEncoder();
}




Java Source Code List

io.kickflip.sdk.FileUtils.java
io.kickflip.sdk.Kickflip.java
io.kickflip.sdk.Share.java
io.kickflip.sdk.Util.java
io.kickflip.sdk.activity.BroadcastActivity.java
io.kickflip.sdk.activity.GlassBroadcastActivity.java
io.kickflip.sdk.activity.ImmersiveActivity.java
io.kickflip.sdk.activity.MediaPlayerActivity.java
io.kickflip.sdk.api.KickflipApiClient.java
io.kickflip.sdk.api.KickflipCallback.java
io.kickflip.sdk.api.OAuthCallback.java
io.kickflip.sdk.api.OAuthClient.java
io.kickflip.sdk.api.OAuthConfig.java
io.kickflip.sdk.api.json.HlsStream.java
io.kickflip.sdk.api.json.Response.java
io.kickflip.sdk.api.json.StreamList.java
io.kickflip.sdk.api.json.Stream.java
io.kickflip.sdk.api.json.User.java
io.kickflip.sdk.api.s3.S3BroadcastManager.java
io.kickflip.sdk.api.s3.package-info.java
io.kickflip.sdk.av.AVRecorder.java
io.kickflip.sdk.av.AndroidEncoder.java
io.kickflip.sdk.av.AndroidMuxer.java
io.kickflip.sdk.av.AudioEncoderConfig.java
io.kickflip.sdk.av.AudioEncoderCore.java
io.kickflip.sdk.av.BroadcastListener.java
io.kickflip.sdk.av.Broadcaster.java
io.kickflip.sdk.av.CameraEncoder.java
io.kickflip.sdk.av.CameraSurfaceRenderer.java
io.kickflip.sdk.av.Drawable2d.java
io.kickflip.sdk.av.EglCore.java
io.kickflip.sdk.av.EglStateSaver.java
io.kickflip.sdk.av.EglSurfaceBase.java
io.kickflip.sdk.av.FFmpegMuxer.java
io.kickflip.sdk.av.Filters.java
io.kickflip.sdk.av.FullFrameRect.java
io.kickflip.sdk.av.GlUtil.java
io.kickflip.sdk.av.HlsFileObserver.java
io.kickflip.sdk.av.M3u8Parser.java
io.kickflip.sdk.av.MicrophoneEncoder.java
io.kickflip.sdk.av.Muxer.java
io.kickflip.sdk.av.SessionConfig.java
io.kickflip.sdk.av.SizeableFrameRect.java
io.kickflip.sdk.av.Texture2dProgram.java
io.kickflip.sdk.av.VideoEncoderConfig.java
io.kickflip.sdk.av.VideoEncoderCore.java
io.kickflip.sdk.av.WindowSurface.java
io.kickflip.sdk.event.BroadcastEvent.java
io.kickflip.sdk.event.BroadcastIsBufferingEvent.java
io.kickflip.sdk.event.BroadcastIsLiveEvent.java
io.kickflip.sdk.event.CameraOpenedEvent.java
io.kickflip.sdk.event.HlsManifestUploadedEvent.java
io.kickflip.sdk.event.HlsManifestWrittenEvent.java
io.kickflip.sdk.event.HlsSegmentUploadedEvent.java
io.kickflip.sdk.event.HlsSegmentWrittenEvent.java
io.kickflip.sdk.event.MuxerFinishedEvent.java
io.kickflip.sdk.event.S3FailedUploadEvent.java
io.kickflip.sdk.event.S3UploadEvent.java
io.kickflip.sdk.event.StreamLocationAddedEvent.java
io.kickflip.sdk.event.ThumbnailWrittenEvent.java
io.kickflip.sdk.event.UploadEvent.java
io.kickflip.sdk.event.package-info.java
io.kickflip.sdk.exception.KickflipException.java
io.kickflip.sdk.fragment.BroadcastFragment.java
io.kickflip.sdk.fragment.GlassBroadcastFragment.java
io.kickflip.sdk.fragment.MediaPlayerFragment.java
io.kickflip.sdk.fragment.package-info.java
io.kickflip.sdk.location.DeviceLocation.java
io.kickflip.sdk.location.package-info.java
io.kickflip.sdk.view.GLCameraEncoderView.java
io.kickflip.sdk.view.GLCameraView.java
io.kickflip.sdk.view.package-info.java
pro.dbro.ffmpegwrapper.FFmpegWrapper.java
pro.dbro.ffmpegwrapper.package-info.java