android.media.MediaCodec# start ( ) 源码实例Demo

下面列出了android.media.MediaCodec# start ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

源代码1 项目: libcommon   文件: MediaMoviePlayer.java

/**
 * @param media_extractor
 * @param trackIndex
 * @return
 */
protected MediaCodec internal_start_video(final MediaExtractor media_extractor, final int trackIndex) {
	if (DEBUG) Log.v(TAG, "internal_start_video:");
	MediaCodec codec = null;
	if (trackIndex >= 0) {
        final MediaFormat format = media_extractor.getTrackFormat(trackIndex);
        final String mime = format.getString(MediaFormat.KEY_MIME);
		try {
			codec = MediaCodec.createDecoderByType(mime);
			codec.configure(format, mOutputSurface, null, 0);
	        codec.start();
			if (DEBUG) Log.v(TAG, "internal_start_video:codec started");
		} catch (final IOException e) {
			Log.w(TAG, e);
		}
	}
	return codec;
}
 
源代码2 项目: In77Camera   文件: MediaCodecUtils.java

@TargetApi(MIN_API_LEVEL_AUDIO)
public static int checkMediaCodecAudioEncoderSupport(){
    if(getApiLevel()<MIN_API_LEVEL_AUDIO){
        Log.d(TAG, "checkMediaCodecAudioEncoderSupport: Min API is 16");
        return CODEC_REQ_API_NOT_SATISFIED;
    }
    final MediaFormat audioFormat = MediaFormat.createAudioFormat(MIME_TYPE_AUDIO, TEST_SAMPLE_RATE, 1);
    audioFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
    audioFormat.setInteger(MediaFormat.KEY_CHANNEL_MASK, AudioFormat.CHANNEL_IN_MONO);
    audioFormat.setInteger(MediaFormat.KEY_BIT_RATE, TEST_AUDIO_BIT_RATE);
    audioFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
    MediaCodec mediaCodec;
    try {
        mediaCodec = MediaCodec.createEncoderByType(MIME_TYPE_AUDIO);
        mediaCodec.configure(audioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        mediaCodec.start();
        mediaCodec.stop();
        mediaCodec.release();
        mediaCodec = null;
    } catch (Exception ex) {
        Log.e(TAG, "Failed on creation of codec #", ex);
        return CODEC_ERROR;
    }
    return CODEC_SUPPORTED;
}
 

/**
 * Creates an encoder for the given format using the specified codec, taking input from a
 * surface.
 *
 * <p>The surface to use as input is stored in the given reference.
 *
 * @param codecName of the codec to use
 * @param format of the stream to be produced
 * @param surfaceReference to store the surface to use as input
 */
private MediaCodec createVideoEncoder(
        String codecName,
        MediaFormat format,
        AtomicReference<Surface> surfaceReference) {
    try {
        MediaCodec encoder = MediaCodec.createByCodecName(codecName);
        encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        // Must be called before start() is.
        surfaceReference.set(encoder.createInputSurface());
        encoder.start();
        return encoder;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}
 

@Override
protected MediaCodec createMediaCodec() throws IOException {
    MediaFormat format = MediaFormat.createVideoFormat(mMimeType, 0, 0);
    if (mCsd0 != null) {
        format.setByteBuffer("csd-0", mCsd0);
    }

    if (mCsd1 != null) {
        format.setByteBuffer("csd-1", mCsd1);
    }

    MediaCodec mediaCodec = MediaCodec.createDecoderByType(mMimeType);
    mediaCodec.configure(format, getSurface(), null, 0);
    mediaCodec.setVideoScalingMode(MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
    mediaCodec.start();
    return mediaCodec;
}
 

@TargetApi(MIN_API_LEVEL_VIDEO)
public static int checkMediaCodecVideoEncoderSupport(){
    if(getApiLevel()<MIN_API_LEVEL_VIDEO){
        Log.d(TAG, "checkMediaCodecVideoEncoderSupport: Min API is 18");
        return CODEC_REQ_API_NOT_SATISFIED;
    }
    MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE_VIDEO, TEST_WIDTH, TEST_HEIGHT);
    format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
            MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
    format.setInteger(MediaFormat.KEY_BIT_RATE, TEST_VIDEO_BIT_RATE);
    format.setInteger(MediaFormat.KEY_FRAME_RATE, TEST_FRAME_RATE);
    format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, TEST_IFRAME_INTERVAL);
    MediaCodec mediaCodec;
    try {
        mediaCodec = MediaCodec.createEncoderByType(MIME_TYPE_VIDEO);
        mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        mediaCodec.createInputSurface();
        mediaCodec.start();
        mediaCodec.stop();
        mediaCodec.release();
        mediaCodec = null;
    } catch (Exception ex) {
        Log.e(TAG, "Failed on creation of codec #", ex);
        return CODEC_ERROR;
    }
    return CODEC_SUPPORTED;
}
 

private @NonNull
MediaCodec createVideoDecoder(
        final @NonNull MediaFormat inputFormat,
        final @NonNull Surface surface) throws IOException {
    final MediaCodec decoder = MediaCodec.createDecoderByType(MediaConverter.getMimeTypeFor(inputFormat));
    decoder.configure(inputFormat, surface, null, 0);
    decoder.start();
    return decoder;
}
 

private @NonNull
MediaCodec createVideoEncoder(
        final @NonNull MediaCodecInfo codecInfo,
        final @NonNull MediaFormat format,
        final @NonNull AtomicReference<Surface> surfaceReference) throws IOException {
    final MediaCodec encoder = MediaCodec.createByCodecName(codecInfo.getName());
    encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    // Must be called before start()
    surfaceReference.set(encoder.createInputSurface());
    encoder.start();
    return encoder;
}
 

private static @NonNull
MediaCodec createAudioDecoder(final @NonNull MediaFormat inputFormat) throws IOException {
    final MediaCodec decoder = MediaCodec.createDecoderByType(MediaConverter.getMimeTypeFor(inputFormat));
    decoder.configure(inputFormat, null, null, 0);
    decoder.start();
    return decoder;
}
 
源代码9 项目: ScreenRecoder   文件: ScreenRecoder.java

@Override
public void run() {
	MediaFormat format = MediaFormat.createVideoFormat("video/avc",
			mWidth, mHeight);
	format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
			MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
	format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
	format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
	format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL,
			I_FRAME_INTERVAL);

	MediaCodec codec = MediaCodec.createEncoderByType("video/avc");
	codec.configure(format, null, null,
			MediaCodec.CONFIGURE_FLAG_ENCODE);
	Surface surface = codec.createInputSurface();
	codec.start();

	VirtualDisplay virtualDisplay = mDisplayManager
			.createVirtualDisplay(DISPLAY_NAME, mWidth, mHeight,
					mDensityDpi, surface,
					DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC);
	
	if (virtualDisplay != null) {
		stream(codec);
		virtualDisplay.release();
	}

	codec.signalEndOfInputStream();
	codec.stop();
}
 
源代码10 项目: DeviceConnect-Android   文件: H265Decoder.java

@Override
protected MediaCodec createMediaCodec() throws IOException {
    parseSps();

    MediaFormat format = MediaFormat.createVideoFormat(mMimeType, mWidth, mHeight);
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
        format.setInteger(MediaFormat.KEY_COLOR_RANGE, MediaFormat.COLOR_RANGE_FULL);
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        format.setInteger(MediaFormat.KEY_OPERATING_RATE, Short.MAX_VALUE);
    }

    ByteBuffer csd0 = ByteBuffer.allocateDirect(mVPS.length + mSPS.length + mPPS.length);
    csd0.put(mVPS);
    csd0.position(mVPS.length);
    csd0.put(mSPS);
    csd0.position(mVPS.length + mSPS.length);
    csd0.put(mPPS);

    format.setByteBuffer("csd-0", csd0);

    if (DEBUG) {
        Log.d(TAG, "H265Decoder::createMediaCodec: " + format);
    }

    MediaCodec mediaCodec = MediaCodec.createDecoderByType(mMimeType);
    mediaCodec.configure(format, getSurface(), null, 0);
    mediaCodec.setVideoScalingMode(MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT);
    mediaCodec.start();
    return mediaCodec;
}
 

/**
 * Creates a decoder for the given format, which outputs to the given surface.
 *
 * @param inputFormat the format of the stream to decode
 * @param surface into which to decode the frames
 */
private MediaCodec createVideoDecoder(
        MediaCodecList mcl, MediaFormat inputFormat, Surface surface){
    try {
        MediaCodec decoder = MediaCodec.createByCodecName(mcl.findDecoderForFormat(inputFormat));
        decoder.configure(inputFormat, surface, null, 0);
        decoder.start();
        return decoder;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}
 

/**
 * Creates a decoder for the given format.
 *
 * @param inputFormat the format of the stream to decode
 */
private MediaCodec createAudioDecoder(
        MediaCodecList mcl, MediaFormat inputFormat) {
    try {
        MediaCodec decoder = MediaCodec.createByCodecName("OMX.google.aac.decoder");//mcl.findDecoderForFormat(inputFormat));
        decoder.configure(inputFormat, null, null, 0);
        decoder.start();
        return decoder;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}
 
源代码13 项目: DeviceConnect-Android   文件: AACDecoder.java

/**
 * MediaCodec を作成します.
 *
 * @return MediaCodec
 * @throws IOException MediaCodec の作成に失敗した場合に発生
 */
private MediaCodec createMediaCodec() throws IOException {
    MediaFormat format = MediaFormat.createAudioFormat("audio/mp4a-latm",
            getSamplingRate(), getChannelCount());

    format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);

    int audioProfile = MediaCodecInfo.CodecProfileLevel.AACObjectLC;
    int sampleIndex = getFreqIdx(getSamplingRate());
    int channelConfig = getChannelCount();

    ByteBuffer csd = ByteBuffer.allocateDirect(2);
    csd.put((byte) ((audioProfile << 3) | (sampleIndex >> 1)));
    csd.position(1);
    csd.put((byte) ((byte) ((sampleIndex << 7) & 0x80) | (channelConfig << 3)));
    csd.flip();

    format.setByteBuffer("csd-0", csd);

    if (DEBUG) {
        Log.d(TAG, "AACDecoder::createMediaCodec: " + format);
    }

    MediaCodec mediaCodec = MediaCodec.createDecoderByType("audio/mp4a-latm");
    mediaCodec.configure(format, null, null, 0);
    mediaCodec.start();
    return mediaCodec;
}
 
源代码14 项目: patrol-android   文件: MediaCodecWrapper.java

private MediaCodecWrapper(MediaCodec codec) {
    mDecoder = codec;
    codec.start();
    mInputBuffers = codec.getInputBuffers();
    mOutputBuffers = codec.getOutputBuffers();
    mOutputBufferInfo = new MediaCodec.BufferInfo[mOutputBuffers.length];
    mAvailableInputBuffers = new ArrayDeque<Integer>(mOutputBuffers.length);
    mAvailableOutputBuffers = new ArrayDeque<Integer>(mInputBuffers.length);
}
 
源代码15 项目: ScreenCapture   文件: MediaCodecWrapper.java

private MediaCodecWrapper(MediaCodec codec) {
    mDecoder = codec;
    codec.start();
    mInputBuffers = codec.getInputBuffers();
    mOutputBuffers = codec.getOutputBuffers();
    mOutputBufferInfo = new MediaCodec.BufferInfo[mOutputBuffers.length];
    mAvailableInputBuffers = new ArrayDeque<>(mOutputBuffers.length);
    mAvailableOutputBuffers = new ArrayDeque<>(mInputBuffers.length);
}
 
源代码16 项目: In77Camera   文件: MediaCodecUtils.java

@TargetApi(MIN_API_LEVEL_VIDEO)
public static int checkMediaCodecVideoEncoderSupport(){
    if(getApiLevel()<MIN_API_LEVEL_VIDEO){
        Log.d(TAG, "checkMediaCodecVideoEncoderSupport: Min API is 18");
        return CODEC_REQ_API_NOT_SATISFIED;
    }
    MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE_VIDEO, TEST_WIDTH, TEST_HEIGHT);
    format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
            MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
    format.setInteger(MediaFormat.KEY_BIT_RATE, TEST_VIDEO_BIT_RATE);
    format.setInteger(MediaFormat.KEY_FRAME_RATE, TEST_FRAME_RATE);
    format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, TEST_IFRAME_INTERVAL);
    MediaCodec mediaCodec;
    try {
        mediaCodec = MediaCodec.createEncoderByType(MIME_TYPE_VIDEO);
        mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        mediaCodec.createInputSurface();
        mediaCodec.start();
        mediaCodec.stop();
        mediaCodec.release();
        mediaCodec = null;
    } catch (Exception ex) {
        Log.e(TAG, "Failed on creation of codec #", ex);
        return CODEC_ERROR;
    }
    return CODEC_SUPPORTED;
}
 

private void feedClipToEncoder( SamplerClip clip ) {

      mLastSampleTime = 0;

      MediaCodec decoder = null;

      MediaExtractor extractor = setupExtractorForClip(clip);
      
      if(extractor == null ) {
         return;
      }
      
      int trackIndex = getVideoTrackIndex(extractor);
      extractor.selectTrack( trackIndex );

      MediaFormat clipFormat = extractor.getTrackFormat( trackIndex );

      if ( clip.getStartTime() != -1 ) {
         extractor.seekTo( clip.getStartTime() * 1000, MediaExtractor.SEEK_TO_PREVIOUS_SYNC );
         clip.setStartTime( extractor.getSampleTime() / 1000 );
      }
      
      try {
         decoder = MediaCodec.createDecoderByType( MediaHelper.MIME_TYPE_AVC );
         mOutputSurface = new OutputSurface();

         decoder.configure( clipFormat, mOutputSurface.getSurface(), null, 0 );
         decoder.start();

         resampleVideo( extractor, decoder, clip );

      } finally {

         if ( mOutputSurface != null ) {
            mOutputSurface.release();
         }
         if ( decoder != null ) {
            decoder.stop();
            decoder.release();
         }

         if ( extractor != null ) {
            extractor.release();
            extractor = null;
         }
      }
   }
 
源代码18 项目: VideoProcessor   文件: AudioUtil.java

/**
 * 需要改变音频速率的情况下,需要先解码->改变速率->编码
 */
public static void decodeToPCM(VideoProcessor.MediaSource audioSource, String outPath, Integer startTimeUs, Integer endTimeUs) throws IOException {
    MediaExtractor extractor = new MediaExtractor();
    audioSource.setDataSource(extractor);
    int audioTrack = VideoUtil.selectTrack(extractor, true);
    extractor.selectTrack(audioTrack);
    if (startTimeUs == null) {
        startTimeUs = 0;
    }
    extractor.seekTo(startTimeUs, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
    MediaFormat oriAudioFormat = extractor.getTrackFormat(audioTrack);
    int maxBufferSize;
    if (oriAudioFormat.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
        maxBufferSize = oriAudioFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
    } else {
        maxBufferSize = 100 * 1000;
    }
    ByteBuffer buffer = ByteBuffer.allocateDirect(maxBufferSize);
    MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();

    //调整音频速率需要重解码音频帧
    MediaCodec decoder = MediaCodec.createDecoderByType(oriAudioFormat.getString(MediaFormat.KEY_MIME));
    decoder.configure(oriAudioFormat, null, null, 0);
    decoder.start();

    boolean decodeDone = false;
    boolean decodeInputDone = false;
    final int TIMEOUT_US = 2500;
    File pcmFile = new File(outPath);
    FileChannel writeChannel = new FileOutputStream(pcmFile).getChannel();
    try {
        while (!decodeDone) {
            if (!decodeInputDone) {
                boolean eof = false;
                int decodeInputIndex = decoder.dequeueInputBuffer(TIMEOUT_US);
                if (decodeInputIndex >= 0) {
                    long sampleTimeUs = extractor.getSampleTime();
                    if (sampleTimeUs == -1) {
                        eof = true;
                    } else if (sampleTimeUs < startTimeUs) {
                        extractor.advance();
                        continue;
                    } else if (endTimeUs != null && sampleTimeUs > endTimeUs) {
                        eof = true;
                    }

                    if (eof) {
                        decodeInputDone = true;
                        decoder.queueInputBuffer(decodeInputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                    } else {
                        info.size = extractor.readSampleData(buffer, 0);
                        info.presentationTimeUs = sampleTimeUs;
                        info.flags = extractor.getSampleFlags();
                        ByteBuffer inputBuffer = decoder.getInputBuffer(decodeInputIndex);
                        inputBuffer.put(buffer);
                        CL.it(TAG, "audio decode queueInputBuffer " + info.presentationTimeUs / 1000);
                        decoder.queueInputBuffer(decodeInputIndex, 0, info.size, info.presentationTimeUs, info.flags);
                        extractor.advance();
                    }

                }
            }

            while (!decodeDone) {
                int outputBufferIndex = decoder.dequeueOutputBuffer(info, TIMEOUT_US);
                if (outputBufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
                    break;
                } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                    MediaFormat newFormat = decoder.getOutputFormat();
                    CL.it(TAG, "audio decode newFormat = " + newFormat);
                } else if (outputBufferIndex < 0) {
                    //ignore
                    CL.et(TAG, "unexpected result from audio decoder.dequeueOutputBuffer: " + outputBufferIndex);
                } else {
                    if (info.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM) {
                        decodeDone = true;
                    } else {
                        ByteBuffer decodeOutputBuffer = decoder.getOutputBuffer(outputBufferIndex);
                        CL.it(TAG, "audio decode saveFrame " + info.presentationTimeUs / 1000);
                        writeChannel.write(decodeOutputBuffer);
                    }
                    decoder.releaseOutputBuffer(outputBufferIndex, false);
                }
            }
        }
    } finally {
        writeChannel.close();
        extractor.release();
        decoder.stop();
        decoder.release();
    }
}
 
源代码19 项目: AlexaAndroid   文件: EncodedAudioRecorder.java

/**
 * Reads bytes from the given recorder and encodes them with the given encoder.
 * Uses the (deprecated) Synchronous Processing using Buffer Arrays.
 * <p/>
 * Encoders (or codecs that generate compressed data) will create and return the codec specific
 * data before any valid output buffer in output buffers marked with the codec-config flag.
 * Buffers containing codec-specific-data have no meaningful timestamps.
 */
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void recorderEncoderLoop(MediaCodec codec, SpeechRecord speechRecord) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        codec.start();
        // Getting some buffers (e.g. 4 of each) to communicate with the codec
        ByteBuffer[] codecInputBuffers = codec.getInputBuffers();
        ByteBuffer[] codecOutputBuffers = codec.getOutputBuffers();
        Log.i("input buffers " + codecInputBuffers.length + "; output buffers: " + codecOutputBuffers.length);
        boolean doneSubmittingInput = false;
        int numRetriesDequeueOutputBuffer = 0;
        int index;
        while (true) {
            if (!doneSubmittingInput) {
                index = codec.dequeueInputBuffer(DEQUEUE_TIMEOUT);
                if (index >= 0) {
                    int size = queueInputBuffer(codec, codecInputBuffers, index, speechRecord);
                    if (size == -1) {
                        codec.queueInputBuffer(index, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                        Log.i("enc: in: EOS");
                        doneSubmittingInput = true;
                    } else {
                        Log.i("enc: in: " + size);
                        mNumBytesSubmitted += size;
                    }
                } else {
                    Log.i("enc: in: timeout, will try again");
                }
            }
            MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
            index = codec.dequeueOutputBuffer(info, DEQUEUE_TIMEOUT);
            Log.i("enc: out: flags/index: " + info.flags + "/" + index);
            if (index == MediaCodec.INFO_TRY_AGAIN_LATER) {
                Log.i("enc: out: INFO_TRY_AGAIN_LATER: " + numRetriesDequeueOutputBuffer);
                if (++numRetriesDequeueOutputBuffer > MAX_NUM_RETRIES_DEQUEUE_OUTPUT_BUFFER) {
                    break;
                }
            } else if (index == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                MediaFormat format = codec.getOutputFormat();
                Log.i("enc: out: INFO_OUTPUT_FORMAT_CHANGED: " + format.toString());
            } else if (index == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
                codecOutputBuffers = codec.getOutputBuffers();
                Log.i("enc: out: INFO_OUTPUT_BUFFERS_CHANGED");
            } else {
                dequeueOutputBuffer(codec, codecOutputBuffers, index, info);
                mNumBytesDequeued += info.size;
                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                    Log.i("enc: out: EOS");
                    break;
                }
            }
        }
        codec.stop();
        codec.release();
    }
}
 

/**
 * Generates a test video file, saving it as VideoChunks.  We generate frames with GL to
 * avoid having to deal with multiple YUV formats.
 *
 * @return true on success, false on "soft" failure
 */
private boolean generateVideoFile(VideoChunks output) {
    if (VERBOSE) Log.d(TAG, "generateVideoFile " + mWidth + "x" + mHeight);
    MediaCodec encoder = null;
    InputSurface inputSurface = null;
    try {
        MediaCodecInfo codecInfo = selectCodec(MIME_TYPE);
        if (codecInfo == null) {
            // Don't fail CTS if they don't have an AVC codec (not here, anyway).
            Log.e(TAG, "Unable to find an appropriate codec for " + MIME_TYPE);
            return false;
        }
        if (VERBOSE) Log.d(TAG, "found codec: " + codecInfo.getName());
        // We avoid the device-specific limitations on width and height by using values that
        // are multiples of 16, which all tested devices seem to be able to handle.
        MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
        // Set some properties.  Failing to specify some of these can cause the MediaCodec
        // configure() call to throw an unhelpful exception.
        format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
                MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
        format.setInteger(MediaFormat.KEY_BIT_RATE, mBitRate);
        format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
        format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
        if (VERBOSE) Log.d(TAG, "format: " + format);
        output.setMediaFormat(format);
        // Create a MediaCodec for the desired codec, then configure it as an encoder with
        // our desired properties.
        encoder = MediaCodec.createByCodecName(codecInfo.getName());
        encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        inputSurface = new InputSurface(encoder.createInputSurface());
        inputSurface.makeCurrent();
        encoder.start();
        generateVideoData(encoder, inputSurface, output);
    } finally {
        if (encoder != null) {
            if (VERBOSE) Log.d(TAG, "releasing encoder");
            encoder.stop();
            encoder.release();
            if (VERBOSE) Log.d(TAG, "released encoder");
        }
        if (inputSurface != null) {
            inputSurface.release();
        }
    }
    return true;
}