/** * Edits a video file, saving the contents to a new file. This involves decoding and * re-encoding, not to mention conversions between YUV and RGB, and so may be lossy. * <p> * If we recognize the decoded format we can do this in Java code using the ByteBuffer[] * output, but it's not practical to support all OEM formats. By using a SurfaceTexture * for output and a Surface for input, we can avoid issues with obscure formats and can * use a fragment shader to do transformations. */ private VideoChunks editVideoFile(VideoChunks inputData) { if (AppSettings.Logging.SendToConsole) { Log.Debug(TAG, "editVideoFile " + mWidth + "x" + mHeight); } VideoChunks outputData = new VideoChunks(); MediaCodec decoder = null; MediaCodec encoder = null; InputSurface inputSurface = null; OutputSurface outputSurface = null; try { MediaFormat inputFormat = inputData.getMediaFormat(); // Create an encoder format that matches the input format. (Might be able to just // re-use the format used to generate the video, since we want it to be the same.) MediaFormat outputFormat = MediaFormat.CreateVideoFormat(MIME_TYPE, mWidth, mHeight); outputFormat.SetInteger(MediaFormat.KeyColorFormat, (int)MediaCodecInfo.CodecCapabilities.COLORFormatSurface); outputFormat.SetInteger(MediaFormat.KeyBitRate, inputFormat.GetInteger(MediaFormat.KeyBitRate)); outputFormat.SetInteger(MediaFormat.KeyFrameRate, inputFormat.GetInteger(MediaFormat.KeyFrameRate)); outputFormat.SetInteger(MediaFormat.KeyIFrameInterval, inputFormat.GetInteger(MediaFormat.KeyIFrameInterval)); outputData.setMediaFormat(outputFormat); encoder = MediaCodec.CreateEncoderByType(MIME_TYPE); encoder.Configure(outputFormat, null, null, MediaCodecConfigFlags.Encode); inputSurface = new InputSurface(encoder.CreateInputSurface()); inputSurface.MakeCurrent(); encoder.Start(); // OutputSurface uses the EGL context created by InputSurface. decoder = MediaCodec.CreateDecoderByType(MIME_TYPE); outputSurface = new OutputSurface(); outputSurface.ChangeFragmentShader(FRAGMENT_SHADER); decoder.Configure(inputFormat, outputSurface.Surface, null, 0); decoder.Start(); editVideoData(inputData, decoder, outputSurface, inputSurface, encoder, outputData); } finally { if (AppSettings.Logging.SendToConsole) { Log.Debug(TAG, "shutting down encoder, decoder"); } if (outputSurface != null) { outputSurface.Release(); } if (inputSurface != null) { inputSurface.Release(); } if (encoder != null) { encoder.Stop(); encoder.Release(); } if (decoder != null) { decoder.Stop(); decoder.Release(); } } return(outputData); }
protected override void OnDraw(Canvas canvas) { if (rtspCancel == null) { rtspClientStart(); } if (codec == null && (h264 || h265)) { codec = MediaCodec.CreateDecoderByType(h265 ? MediaFormat.MimetypeVideoHevc : MediaFormat.MimetypeVideoAvc); callbacks = new CallBacks(this); codec.SetCallback(callbacks); var mediafmt = MediaFormat.CreateVideoFormat(h265 ? MediaFormat.MimetypeVideoHevc : MediaFormat.MimetypeVideoAvc, 1920, 1080); codec.Configure(mediafmt, videoView.Holder.Surface, null, MediaCodecConfigFlags.None); codec.Start(); } base.OnDraw(canvas); }
public void SetupVideo(int width, int height, byte[] spsData, byte[] ppsData) { MediaFormat videoFormat = MediaFormat.CreateVideoFormat( mime: MediaFormat.MimetypeVideoAvc, width: width, height: height); /* * TODO: Use SPS / PPS * videoFormat.SetByteBuffer("csd-0", Java.Nio.ByteBuffer.Wrap(spsData)); * videoFormat.SetByteBuffer("csd-1", Java.Nio.ByteBuffer.Wrap(ppsData)); */ videoFormat.SetInteger(MediaFormat.KeyMaxInputSize, 100000); _videoCodec = MediaCodec.CreateDecoderByType( MediaFormat.MimetypeVideoAvc); _videoCodec.SetCallback(this); _videoCodec.Configure(format: videoFormat, surface: new Surface(_surface), crypto: null, flags: MediaCodecConfigFlags.None); _videoCodec.Start(); }
public bool setup(DecoderCallback callback_obj, int width, int height) //format_hint is aviFileContent { callbackThread = new HandlerThread("H264DecoderHandler"); callbackThread.Start(); handler = new Handler(callbackThread.Looper); mDecoder = MediaCodec.CreateDecoderByType(MIME); mCallbackObj = callback_obj; myCallback = new MyCallback(mDecoder, mCallbackObj); mDecoder.SetCallback(myCallback, handler); //mOutputFormat = mDecoder.GetOutputFormat(); // option B inputFormat = MediaFormat.CreateVideoFormat(MIME, width, height); inputFormat.SetInteger(MediaFormat.KeyMaxInputSize, width * height); inputFormat.SetInteger("durationUs", 63446722); //inputFormat.SetInteger(MediaFormat.KeyColorFormat, (int)MediaCodecCapabilities.Formatyuv420semiplanar); //inputFormat.SetInteger(MediaFormat.KeyIFrameInterval, 60); try { mDecoder.Configure(inputFormat, null, null, 0 /* Decoder */); } catch (Exception ex) { throw ex; } Console.WriteLine("before mDecoder.Start()"); mDecoder.Start(); Console.WriteLine("after mDecoder.Start()"); return(true); }
private static MediaFormat GetMediaFormat(string mimeType, int videoWidth, int videoHeight) { var format = MediaFormat.CreateVideoFormat( mime: mimeType, width: videoWidth, height: videoHeight); format.SetInteger(MediaFormat.KeyMaxInputSize, 100000); return(format); }
private void Init() { if (sps.Length == 14) decoderWidth = 1280; else decoderWidth = 960; MediaFormat videoFormat = MediaFormat.CreateVideoFormat("video/avc", decoderWidth, decoderHeight); videoFormat.SetByteBuffer("csd-0", ByteBuffer.Wrap(sps)); videoFormat.SetByteBuffer("csd-1", ByteBuffer.Wrap(pps)); string str = videoFormat.GetString("mime"); try { var cdx = MediaCodec.CreateDecoderByType(str); cdx.Configure(videoFormat, Holder.Surface, (MediaCrypto)null, 0); cdx.SetVideoScalingMode(VideoScalingMode.ScaleToFit); cdx.Start(); codec = cdx; } catch (Exception ex) { //handle } bConfigured = true; //set surface aspect ratio MainActivity.getActivity().RunOnUiThread(() => { float videoProportion = (float)decoderWidth / (float)decoderHeight; var size = new Android.Graphics.Point(); MainActivity.getActivity().WindowManager.DefaultDisplay.GetSize(size); int screenWidth = size.X; int screenHeight = size.Y; float screenProportion = (float)screenWidth / (float)screenHeight; var lp = this.LayoutParameters; if (videoProportion > screenProportion) { lp.Width = screenWidth; lp.Height = (int)((float)screenWidth / videoProportion); } else { lp.Width = (int)(videoProportion * (float)screenHeight); lp.Height = screenHeight; } this.LayoutParameters = lp; }); }
/** * Instantiates and starts the decoder. * @throws IOException The decoder cannot be configured */ private void configureDecoder() { 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.KeyColorFormat, 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.Error(TAG, "No buffer available !"); } } }
/** * Instantiates and starts the encoder. * @throws IOException The encoder cannot be configured */ private void configureEncoder() { mEncoder = MediaCodec.CreateByCodecName(mEncoderName); MediaFormat mediaFormat = MediaFormat.CreateVideoFormat(MIME_TYPE, mWidth, mHeight); mediaFormat.SetInteger(MediaFormat.KeyBitRate, BITRATE); mediaFormat.SetInteger(MediaFormat.KeyFrameRate, FRAMERATE); mediaFormat.SetInteger(MediaFormat.KeyColorFormat, mEncoderColorFormat); mediaFormat.SetInteger(MediaFormat.KeyIFrameInterval, 1); mEncoder.Configure(mediaFormat, null, null, MediaCodecConfigFlags.Encode); mEncoder.Start(); }
public VideoStreamer(int width, int height) { MediaFormat videoFormat = MediaFormat.CreateVideoFormat(MediaFormat.MimetypeVideoAvc, width, height); MediaCodecList availableCodecs = new MediaCodecList(MediaCodecListKind.RegularCodecs); MediaCodec encoder = MediaCodec.CreateEncoderByType(MediaFormat.MimetypeVideoAvc); _backgroundThread = new HandlerThread("EncoderBackgroundWorker"); _backgroundThread.Start(); _backgroundHandler = new Handler(_backgroundThread.Looper); encoder.SetCallback(new EncoderCallback(), _backgroundHandler); encoder.Configure(videoFormat, null, null, MediaCodecConfigFlags.Encode); encoder.Start(); }
/** * Configures encoder and muxer state, and prepares the input Surface. Initializes * mEncoder, mMuxer, mInputSurface, mBufferInfo, mTrackIndex, and mMuxerStarted. */ private void prepareEncoder() { mBufferInfo = new MediaCodec.BufferInfo(); MediaFormat format = MediaFormat.CreateVideoFormat(MIME_TYPE, _width, _height); // Set some properties. Failing to specify some of these can cause the MediaCodec // configure() call to throw an unhelpful exception. format.SetInteger(MediaFormat.KeyColorFormat, (int)MediaCodecCapabilities.Formatsurface); format.SetInteger(MediaFormat.KeyBitRate, _bitRate); format.SetInteger(MediaFormat.KeyFrameRate, FRAME_RATE); format.SetInteger(MediaFormat.KeyIFrameInterval, IFRAME_INTERVAL); if (VERBOSE) { Log.Debug(TAG, "format: " + format); } // Create a MediaCodec encoder, and configure it with our format. Get a Surface // we can use for input and wrap it with a class that handles the EGL work. // // If you want to have two EGL contexts -- one for display, one for recording -- // you will likely want to defer instantiation of CodecInputSurface until after the // "display" EGL context is created, then modify the eglCreateContext call to // take eglGetCurrentContext() as the share_context argument. mEncoder = MediaCodec.CreateEncoderByType(MIME_TYPE); mEncoder.Configure(format, null, null, MediaCodec.ConfigureFlagEncode); _inputSurface = new InputSurface(mEncoder.CreateInputSurface()); mEncoder.Start(); // Output filename. Ideally this would use Context.getFilesDir() rather than a // hard-coded output directory. string outputPath = System.IO.Path.Combine(_workingDirectory, "test." + _width + "x" + _height + ".mp4"); Log.Info(TAG, "Output file is " + outputPath); // Create a MediaMuxer. We can't add the video track and start() the muxer here, // because our MediaFormat doesn't have the Magic Goodies. These can only be // obtained from the encoder after it has started processing data. // // We're not actually interested in multiplexing audio. We just want to convert // the raw H.264 elementary stream we get from MediaCodec into a .mp4 file. try { mMuxer = new MediaMuxer(outputPath, MediaMuxer.OutputFormat.MuxerOutputMpeg4); } catch (System.Exception e) { throw new System.Exception(e.Message); } mTrackIndex = -1; mMuxerStarted = false; }
private void PrepareEncoder() { MediaCodecInfo codecInfo = selectCodec(MIME_TYPE); if (codecInfo == null) { return; } int colorFormat; try { colorFormat = selectColorFormat(codecInfo, MIME_TYPE); } catch { colorFormat = (int)MediaCodecCapabilities.Formatyuv420semiplanar; } var format = MediaFormat.CreateVideoFormat(MIME_TYPE, _Width, _Height); format.SetInteger(MediaFormat.KeyColorFormat, colorFormat); format.SetInteger(MediaFormat.KeyBitRate, _BitRate); format.SetInteger(MediaFormat.KeyFrameRate, _frameRate); format.SetInteger(MediaFormat.KeyIFrameInterval, IFRAME_INTERVAL); _Encoder = MediaCodec.CreateEncoderByType(MIME_TYPE); _Encoder.Configure(format, null, null, MediaCodecConfigFlags.Encode); _Encoder.Start(); // Create a MediaMuxer. We can't add the video track and start() the muxer here, // because our MediaFormat doesn't have the Magic Goodies. These can only be // obtained from the encoder after it has started processing data. try { _Muxer = new MediaMuxer(_Filepath, MuxerOutputType.Mpeg4); } catch (Exception e) { Log.Error(TAG, e.Message, e); throw; } _TrackIndex = -1; _MuxerStarted = false; }
public BufferPlayer(Surface surface) : base(surface) { format = MediaFormat.CreateVideoFormat("video/avc", 720, 480); //these are custom/dependant upon the source of the video //**TODO: search for and find them @ runtime. (it is not hard to do), but that //can cause a slight delay in initial video rendering. var sps = new byte[] { 0, 0, 0, 1, 103, 66, 224, 30, 218, 2, 208, 246, 192, 68, 0, 0, 46, 236, 0, 10, 252, 130, 16 }; var pps = new byte[] { 0, 0, 0, 1, 104, 206, 60, 128 }; format.SetByteBuffer("csd-0", Java.Nio.ByteBuffer.Wrap(sps)); format.SetByteBuffer("csd-1", Java.Nio.ByteBuffer.Wrap(pps)); format.SetInteger(MediaFormat.KeyMaxInputSize, 720 * 480);//don't need this if you look up the pps/sps? Log.Debug(TAG, "format: " + format); }
private void SetupEncoder() { MediaFormat outputFormat = MediaFormat.CreateVideoFormat(MediaHelper.MIME_TYPE_AVC, mWidth, mHeight); outputFormat.SetInteger(MediaFormat.KeyColorFormat, (int)MediaCodecCapabilities.Formatsurface); outputFormat.SetInteger(MediaFormat.KeyBitRate, mBitRate); outputFormat.SetInteger(MediaFormat.KeyFrameRate, mFrameRate); outputFormat.SetInteger(MediaFormat.KeyIFrameInterval, mIFrameInterval); mEncoder = MediaCodec.CreateEncoderByType(MediaHelper.MIME_TYPE_AVC); mEncoder.Configure(outputFormat, null, null, MediaCodecConfigFlags.Encode); mInputSurface = new InputSurface(mEncoder.CreateInputSurface()); mInputSurface.MakeCurrent(); mEncoder.Start(); }
private static void Init() { MediaFormat videoFormat = MediaFormat.CreateVideoFormat("video/avc", width, height); videoFormat.SetByteBuffer("csd-0", ByteBuffer.Wrap(sps)); videoFormat.SetByteBuffer("csd-1", ByteBuffer.Wrap(pps)); string str = videoFormat.GetString("mime"); try { var cdx = MediaCodec.CreateDecoderByType(str); cdx.Configure(videoFormat, picSurface, (MediaCrypto)null, 0); cdx.SetVideoScalingMode(VideoScalingMode.ScaleToFit); cdx.Start(); picCodec = cdx; //codec = picCodec; } catch (Exception ex) { } videoFormat = MediaFormat.CreateVideoFormat("video/avc", 1280, 720); videoFormat.SetByteBuffer("csd-0", ByteBuffer.Wrap(vidSps)); videoFormat.SetByteBuffer("csd-1", ByteBuffer.Wrap(pps)); try { var cdx = MediaCodec.CreateDecoderByType(videoFormat.GetString("mime")); cdx.Configure(videoFormat, vidSurface, (MediaCrypto)null, 0); cdx.SetVideoScalingMode(VideoScalingMode.ScaleToFit); cdx.Start(); vidCodec = cdx; } catch (Exception ex) { } bConfigured = true; }
public MediaFormat CreateVideoOutputFormat(MediaFormat inputFormat) { int width = inputFormat.GetInteger(MediaFormat.KeyWidth); int height = inputFormat.GetInteger(MediaFormat.KeyHeight); int longer, shorter, outWidth, outHeight; if (width >= height) { longer = width; shorter = height; outWidth = LONGER_LENGTH; outHeight = SHORTER_LENGTH; } else { shorter = width; longer = height; outWidth = SHORTER_LENGTH; outHeight = LONGER_LENGTH; } //if (longer * 9 != shorter * 16) //{ // throw new OutputFormatUnavailableException("This video is not 16:9, and is not able to transcode. (" + width + "x" + height + ")"); //} if (shorter <= SHORTER_LENGTH) { #if DEBUG System.Console.WriteLine("This video is less or equal to 720p, pass-through. (" + width + "x" + height + ")"); #endif return(null); } MediaFormat format = MediaFormat.CreateVideoFormat("video/avc", outWidth, outHeight); format.SetInteger(MediaFormat.KeyBitRate, mVideoBitrate); format.SetInteger(MediaFormat.KeyFrameRate, 30); format.SetInteger(MediaFormat.KeyIFrameInterval, 3); // this is obsolete: MediaCodecInfo.CodecCapabilities.COLORFormatSurface, so using MediaCodecCapabilities.Formatsurface instead format.SetInteger(MediaFormat.KeyColorFormat, (int)MediaCodecCapabilities.Formatsurface); return(format); }
static public void config(Surface surface, int width, int height, byte[] sps, byte[] pps) { if (sps == null || pps == null)//not ready. { return; } if (bConfigured) { return; } if (codec != null) { stop(); } Decoder.width = width; Decoder.height = height; Decoder.sps = sps; Decoder.pps = pps; MediaFormat videoFormat = MediaFormat.CreateVideoFormat("video/avc", width, height); videoFormat.SetByteBuffer("csd-0", ByteBuffer.Wrap(sps)); videoFormat.SetByteBuffer("csd-1", ByteBuffer.Wrap(pps)); videoFormat.SetInteger("color-format", 19); string str = videoFormat.GetString("mime"); try { codec = MediaCodec.CreateDecoderByType(str); codec.Configure(videoFormat, surface, (MediaCrypto)null, 0); codec.SetVideoScalingMode(VideoScalingMode.ScaleToFit); codec.Start(); bConfigured = true; } catch (Exception ex) { var errstr = ex.Message.ToString(); } }
/** * Configures encoder and muxer state, and prepares the input Surface. Initializes * mEncoder, mMuxer, mInputSurface, mBufferInfo, mTrackIndex, and mMuxerStarted. */ private void prepareEncoder(string outputPath) { _bfi = new MediaCodec.BufferInfo(); LatestOutputPath = outputPath; MediaFormat format = MediaFormat.CreateVideoFormat(MIME_TYPE, _width, _height); // Set some properties. Failing to specify some of these can cause the MediaCodec // configure() call to throw an unhelpful exception. format.SetInteger(MediaFormat.KeyColorFormat, (int)MediaCodecCapabilities.Formatsurface); format.SetInteger(MediaFormat.KeyBitRate, _bitRate); format.SetInteger(MediaFormat.KeyFrameRate, FRAME_RATE); format.SetInteger(MediaFormat.KeyIFrameInterval, IFRAME_INTERVAL); if (AppSettings.Logging.SendToConsole) { Log.Debug(TAG, "format: " + format); } // Create a MediaCodec encoder, and configure it with our format. Get a Surface // we can use for input and wrap it with a class that handles the EGL work. // // If you want to have two EGL contexts -- one for display, one for recording -- // you will likely want to defer instantiation of CodecInputSurface until after the // "display" EGL context is created, then modify the eglCreateContext call to // take eglGetCurrentContext() as the share_context argument. mEncoder = MediaCodec.CreateEncoderByType(MIME_TYPE); mEncoder.Configure(format, null, null, MediaCodec.ConfigureFlagEncode); _inputSurface = new InputSurface(mEncoder.CreateInputSurface()); mEncoder.Start(); Log.Info(TAG, "Output file is " + outputPath); try { _muxer = new MediaMuxer(outputPath, MediaMuxer.OutputFormat.MuxerOutputMpeg4); } catch (System.Exception e) { throw new System.Exception(e.Message); } mTrackIndex = -1; MuxerStarted = false; }
/** * Video encoding is done by a MediaCodec. */ protected void encodeWithMediaCodecMethod1() { Log.Debug(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); const NV21Convertor convertor = debugger.getNV21Convertor(); mMediaCodec = MediaCodec.CreateByCodecName(debugger.getEncoderName()); MediaFormat mediaFormat = MediaFormat.CreateVideoFormat("video/avc", mQuality.resX, mQuality.resY); mediaFormat.SetInteger(MediaFormat.KeyBitRate, mQuality.bitrate); mediaFormat.SetInteger(MediaFormat.KeyFrameRate, mQuality.framerate); mediaFormat.SetInteger(MediaFormat.KeyColorFormat,debugger.getEncoderColorFormat()); mediaFormat.SetInteger(MediaFormat.KeyIFrameInterval, 1); mMediaCodec.Configure(mediaFormat, null, null, MediaCodecConfigFlags.Encode); mMediaCodec.Start(); Camera.PreviewCallback callback = new Camera.PreviewCallback() Action InnerMethod = () =>{ long now = System.nanoTime()/1000, oldnow = now, i=0; ByteBuffer[] inputBuffers = mMediaCodec.getInputBuffers(); @Override
/** * 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 bool generateVideoFile(VideoChunks output) { if (AppSettings.Logging.SendToConsole) { Log.Debug(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.Error(TAG, "Unable to find an appropriate codec for " + MIME_TYPE); return(false); } if (AppSettings.Logging.SendToConsole) { Log.Debug(TAG, "found codec: " + codecInfo.Name); } // 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.KeyColorFormat, (int)MediaCodecCapabilities.Formatsurface); format.SetInteger(MediaFormat.KeyBitRate, mBitRate); format.SetInteger(MediaFormat.KeyFrameRate, FRAME_RATE); format.SetInteger(MediaFormat.KeyIFrameInterval, IFRAME_INTERVAL); if (AppSettings.Logging.SendToConsole) { Log.Debug(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.Name); encoder.Configure(format, null, null, MediaCodecConfigFlags.Encode); inputSurface = new InputSurface(encoder.CreateInputSurface()); inputSurface.MakeCurrent(); encoder.Start(); generateVideoData(encoder, inputSurface, output); } finally { if (encoder != null) { if (AppSettings.Logging.SendToConsole) { Log.Debug(TAG, "releasing encoder"); } encoder.Stop(); encoder.Release(); if (AppSettings.Logging.SendToConsole) { Log.Debug(TAG, "released encoder"); } } if (inputSurface != null) { inputSurface.Release(); } } return(true); }
// https://github.com/lanhq147/SampleMediaFrame/blob/e2f20ff9eef73318e5a9b4de15458c5c2eb0fd46/app/src/main/java/com/google/android/exoplayer2/video/av/HWRecorder.java public bool BeginEncoding(int resX, int resY, int rateNumer, int rateDenom, int videoBitRate, int audioBitRate, string audioFile, string outputFile) { videoBufferInfo = new MediaCodec.BufferInfo(); audioBufferInfo = new MediaCodec.BufferInfo(); frameRateNumer = rateNumer; frameRateDenom = rateDenom; MediaFormat videoFormat = MediaFormat.CreateVideoFormat(VideoMimeType, resX, resY); videoFormat.SetInteger(MediaFormat.KeyColorFormat, (int)MediaCodecCapabilities.Formatsurface); videoFormat.SetInteger(MediaFormat.KeyBitRate, videoBitRate * 1000); videoFormat.SetFloat(MediaFormat.KeyFrameRate, rateNumer / (float)rateDenom); videoFormat.SetInteger(MediaFormat.KeyIFrameInterval, 4); videoFormat.SetInteger(MediaFormat.KeyProfile, (int)MediaCodecProfileType.Avcprofilehigh); videoFormat.SetInteger(MediaFormat.KeyLevel, (int)MediaCodecProfileLevel.Avclevel31); videoEncoder = MediaCodec.CreateEncoderByType(VideoMimeType); videoEncoder.Configure(videoFormat, null, null, MediaCodecConfigFlags.Encode); surface = videoEncoder.CreateInputSurface(); videoEncoder.Start(); MediaFormat audioFormat = MediaFormat.CreateAudioFormat(AudioMimeType, 44100, 1); audioFormat.SetInteger(MediaFormat.KeyAacProfile, (int)MediaCodecProfileType.Aacobjectlc); audioFormat.SetInteger(MediaFormat.KeyBitRate, audioBitRate * 1000); audioEncoder = MediaCodec.CreateEncoderByType(AudioMimeType); audioEncoder.Configure(audioFormat, null, null, MediaCodecConfigFlags.Encode); audioEncoder.Start(); try { muxer = new MediaMuxer(outputFile, MuxerOutputType.Mpeg4); } catch { return(false); } videoTrackIndex = -1; audioTrackIndex = -1; muxerStarted = false; if (!ElgInitialize()) { return(false); } audioData = File.ReadAllBytes(audioFile); if (audioData == null) { return(false); } DrainEncoder(videoEncoder, videoBufferInfo, videoTrackIndex, false); DrainEncoder(audioEncoder, audioBufferInfo, audioTrackIndex, false); audioEncodingTask = Task.Factory.StartNew(AudioEncodeThread, TaskCreationOptions.LongRunning); return(true); }