Search in sources :

Example 36 with MediaFormat

use of android.media.MediaFormat in project grafika by google.

the class VideoEncoderCore method drainEncoder.

/**
 * Extracts all pending data from the encoder and forwards it to the muxer.
 * <p>
 * If endOfStream is not set, this returns when there is no more data to drain.  If it
 * is set, we send EOS to the encoder, and then iterate until we see EOS on the output.
 * Calling this with endOfStream set should be done once, right before stopping the muxer.
 * <p>
 * We're just using the muxer to get a .mp4 file (instead of a raw H.264 stream).  We're
 * not recording audio.
 */
public void drainEncoder(boolean endOfStream) {
    final int TIMEOUT_USEC = 10000;
    if (VERBOSE)
        Log.d(TAG, "drainEncoder(" + endOfStream + ")");
    if (endOfStream) {
        if (VERBOSE)
            Log.d(TAG, "sending EOS to encoder");
        mEncoder.signalEndOfInputStream();
    }
    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) {
                // out of while
                break;
            } else {
                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
            if (mMuxerStarted) {
                throw new RuntimeException("format changed twice");
            }
            MediaFormat newFormat = mEncoder.getOutputFormat();
            Log.d(TAG, "encoder output format changed: " + newFormat);
            // now that we have the Magic Goodies, start the muxer
            mTrackIndex = mMuxer.addTrack(newFormat);
            mMuxer.start();
            mMuxerStarted = true;
        } 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.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
                // the INFO_OUTPUT_FORMAT_CHANGED status.  Ignore it.
                if (VERBOSE)
                    Log.d(TAG, "ignoring BUFFER_FLAG_CODEC_CONFIG");
                mBufferInfo.size = 0;
            }
            if (mBufferInfo.size != 0) {
                if (!mMuxerStarted) {
                    throw new RuntimeException("muxer hasn't started");
                }
                // adjust the ByteBuffer values to match BufferInfo (not needed?)
                encodedData.position(mBufferInfo.offset);
                encodedData.limit(mBufferInfo.offset + mBufferInfo.size);
                mMuxer.writeSampleData(mTrackIndex, encodedData, mBufferInfo);
                if (VERBOSE) {
                    Log.d(TAG, "sent " + mBufferInfo.size + " bytes to muxer, ts=" + mBufferInfo.presentationTimeUs);
                }
            }
            mEncoder.releaseOutputBuffer(encoderStatus, false);
            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");
                }
                // out of while
                break;
            }
        }
    }
}
Also used : MediaFormat(android.media.MediaFormat) ByteBuffer(java.nio.ByteBuffer)

Example 37 with MediaFormat

use of android.media.MediaFormat in project grafika by google.

the class MoviePlayer method selectTrack.

/**
 * Selects the video track, if any.
 *
 * @return the track index, or -1 if no video track is found.
 */
private static int selectTrack(MediaExtractor extractor) {
    // Select the first video track we find, ignore the rest.
    int numTracks = extractor.getTrackCount();
    for (int i = 0; i < numTracks; i++) {
        MediaFormat format = extractor.getTrackFormat(i);
        String mime = format.getString(MediaFormat.KEY_MIME);
        if (mime.startsWith("video/")) {
            if (VERBOSE) {
                Log.d(TAG, "Extractor selected track " + i + " (" + mime + "): " + format);
            }
            return i;
        }
    }
    return -1;
}
Also used : MediaFormat(android.media.MediaFormat)

Example 38 with MediaFormat

use of android.media.MediaFormat in project libstreaming by fyhertz.

the class AACStream method encodeWithMediaCodec.

@Override
@SuppressLint({ "InlinedApi", "NewApi" })
protected void encodeWithMediaCodec() throws IOException {
    final int bufferSize = AudioRecord.getMinBufferSize(mQuality.samplingRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT) * 2;
    ((AACLATMPacketizer) mPacketizer).setSamplingRate(mQuality.samplingRate);
    mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, mQuality.samplingRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
    mMediaCodec = MediaCodec.createEncoderByType("audio/mp4a-latm");
    MediaFormat format = new MediaFormat();
    format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
    format.setInteger(MediaFormat.KEY_BIT_RATE, mQuality.bitRate);
    format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
    format.setInteger(MediaFormat.KEY_SAMPLE_RATE, mQuality.samplingRate);
    format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
    format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, bufferSize);
    mMediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    mAudioRecord.startRecording();
    mMediaCodec.start();
    final MediaCodecInputStream inputStream = new MediaCodecInputStream(mMediaCodec);
    final ByteBuffer[] inputBuffers = mMediaCodec.getInputBuffers();
    mThread = new Thread(new Runnable() {

        @Override
        public void run() {
            int len = 0, bufferIndex = 0;
            try {
                while (!Thread.interrupted()) {
                    bufferIndex = mMediaCodec.dequeueInputBuffer(10000);
                    if (bufferIndex >= 0) {
                        inputBuffers[bufferIndex].clear();
                        len = mAudioRecord.read(inputBuffers[bufferIndex], bufferSize);
                        if (len == AudioRecord.ERROR_INVALID_OPERATION || len == AudioRecord.ERROR_BAD_VALUE) {
                            Log.e(TAG, "An error occured with the AudioRecord API !");
                        } else {
                            // Log.v(TAG,"Pushing raw audio to the decoder: len="+len+" bs: "+inputBuffers[bufferIndex].capacity());
                            mMediaCodec.queueInputBuffer(bufferIndex, 0, len, System.nanoTime() / 1000, 0);
                        }
                    }
                }
            } catch (RuntimeException e) {
                e.printStackTrace();
            }
        }
    });
    mThread.start();
    // The packetizer encapsulates this stream in an RTP stream and send it over the network
    mPacketizer.setInputStream(inputStream);
    mPacketizer.start();
    mStreaming = true;
}
Also used : AudioRecord(android.media.AudioRecord) MediaFormat(android.media.MediaFormat) AACLATMPacketizer(net.majorkernelpanic.streaming.rtp.AACLATMPacketizer) MediaCodecInputStream(net.majorkernelpanic.streaming.rtp.MediaCodecInputStream) ByteBuffer(java.nio.ByteBuffer) SuppressLint(android.annotation.SuppressLint) SuppressLint(android.annotation.SuppressLint)

Example 39 with MediaFormat

use of android.media.MediaFormat in project libstreaming by fyhertz.

the class VideoStream method encodeWithMediaCodecMethod1.

/**
 * Video encoding is done by a MediaCodec.
 */
@SuppressLint("NewApi")
protected void encodeWithMediaCodecMethod1() throws RuntimeException, IOException {
    Log.d(TAG, "Video encoded using the MediaCodec API with a buffer");
    // Updates the parameters of the camera if needed
    createCamera();
    updateCamera();
    // Estimates the frame rate of the camera
    measureFramerate();
    // Starts the preview if needed
    if (!mPreviewStarted) {
        try {
            mCamera.startPreview();
            mPreviewStarted = true;
        } catch (RuntimeException e) {
            destroyCamera();
            throw e;
        }
    }
    EncoderDebugger debugger = EncoderDebugger.debug(mSettings, mQuality.resX, mQuality.resY);
    final NV21Convertor convertor = debugger.getNV21Convertor();
    mMediaCodec = MediaCodec.createByCodecName(debugger.getEncoderName());
    MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", mQuality.resX, mQuality.resY);
    mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, mQuality.bitrate);
    mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, mQuality.framerate);
    mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, debugger.getEncoderColorFormat());
    mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
    mMediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    mMediaCodec.start();
    Camera.PreviewCallback callback = new Camera.PreviewCallback() {

        long now = System.nanoTime() / 1000, oldnow = now, i = 0;

        ByteBuffer[] inputBuffers = mMediaCodec.getInputBuffers();

        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            oldnow = now;
            now = System.nanoTime() / 1000;
            if (i++ > 3) {
                i = 0;
            // Log.d(TAG,"Measured: "+1000000L/(now-oldnow)+" fps.");
            }
            try {
                int bufferIndex = mMediaCodec.dequeueInputBuffer(500000);
                if (bufferIndex >= 0) {
                    inputBuffers[bufferIndex].clear();
                    if (data == null)
                        Log.e(TAG, "Symptom of the \"Callback buffer was to small\" problem...");
                    else
                        convertor.convert(data, inputBuffers[bufferIndex]);
                    mMediaCodec.queueInputBuffer(bufferIndex, 0, inputBuffers[bufferIndex].position(), now, 0);
                } else {
                    Log.e(TAG, "No buffer available !");
                }
            } finally {
                mCamera.addCallbackBuffer(data);
            }
        }
    };
    for (int i = 0; i < 10; i++) mCamera.addCallbackBuffer(new byte[convertor.getBufferSize()]);
    mCamera.setPreviewCallbackWithBuffer(callback);
    // The packetizer encapsulates the bit stream in an RTP stream and send it over the network
    mPacketizer.setInputStream(new MediaCodecInputStream(mMediaCodec));
    mPacketizer.start();
    mStreaming = true;
}
Also used : MediaFormat(android.media.MediaFormat) EncoderDebugger(net.majorkernelpanic.streaming.hw.EncoderDebugger) NV21Convertor(net.majorkernelpanic.streaming.hw.NV21Convertor) MediaCodecInputStream(net.majorkernelpanic.streaming.rtp.MediaCodecInputStream) Camera(android.hardware.Camera) SuppressLint(android.annotation.SuppressLint) SuppressLint(android.annotation.SuppressLint)

Example 40 with MediaFormat

use of android.media.MediaFormat in project libstreaming by fyhertz.

the class EncoderDebugger method configureDecoder.

/**
 * Instantiates and starts the decoder.
 * @throws IOException The decoder cannot be configured
 */
private void configureDecoder() throws IOException {
    byte[] prefix = new byte[] { 0x00, 0x00, 0x00, 0x01 };
    ByteBuffer csd0 = ByteBuffer.allocate(4 + mSPS.length + 4 + mPPS.length);
    csd0.put(new byte[] { 0x00, 0x00, 0x00, 0x01 });
    csd0.put(mSPS);
    csd0.put(new byte[] { 0x00, 0x00, 0x00, 0x01 });
    csd0.put(mPPS);
    mDecoder = MediaCodec.createByCodecName(mDecoderName);
    MediaFormat mediaFormat = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
    mediaFormat.setByteBuffer("csd-0", csd0);
    mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, mDecoderColorFormat);
    mDecoder.configure(mediaFormat, null, null, 0);
    mDecoder.start();
    ByteBuffer[] decInputBuffers = mDecoder.getInputBuffers();
    int decInputIndex = mDecoder.dequeueInputBuffer(1000000 / FRAMERATE);
    if (decInputIndex >= 0) {
        decInputBuffers[decInputIndex].clear();
        decInputBuffers[decInputIndex].put(prefix);
        decInputBuffers[decInputIndex].put(mSPS);
        mDecoder.queueInputBuffer(decInputIndex, 0, decInputBuffers[decInputIndex].position(), timestamp(), 0);
    } else {
        if (VERBOSE)
            Log.e(TAG, "No buffer available !");
    }
    decInputIndex = mDecoder.dequeueInputBuffer(1000000 / FRAMERATE);
    if (decInputIndex >= 0) {
        decInputBuffers[decInputIndex].clear();
        decInputBuffers[decInputIndex].put(prefix);
        decInputBuffers[decInputIndex].put(mPPS);
        mDecoder.queueInputBuffer(decInputIndex, 0, decInputBuffers[decInputIndex].position(), timestamp(), 0);
    } else {
        if (VERBOSE)
            Log.e(TAG, "No buffer available !");
    }
}
Also used : MediaFormat(android.media.MediaFormat) ByteBuffer(java.nio.ByteBuffer) SuppressLint(android.annotation.SuppressLint)

Aggregations

MediaFormat (android.media.MediaFormat)130 IOException (java.io.IOException)29 MediaCodec (android.media.MediaCodec)24 ByteBuffer (java.nio.ByteBuffer)22 MediaExtractor (android.media.MediaExtractor)18 SuppressLint (android.annotation.SuppressLint)16 Handler (android.os.Handler)15 Test (org.junit.Test)14 TargetApi (android.annotation.TargetApi)13 InputStream (java.io.InputStream)12 Context (android.content.Context)10 HandlerThread (android.os.HandlerThread)10 Message (android.os.Message)10 Pair (android.util.Pair)10 Format (com.google.android.exoplayer2.Format)10 Runnable (java.lang.Runnable)10 Nullable (androidx.annotation.Nullable)9 File (java.io.File)9 BufferInfo (android.media.MediaCodec.BufferInfo)8 Surface (android.view.Surface)8