SHARE
TWEET

Untitled

a guest Aug 19th, 2019 63 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package com.takusemba.rtmppublisher;
  2.  
  3. import android.media.MediaCodec;
  4. import android.media.MediaCodecInfo;
  5. import android.media.MediaFormat;
  6. import android.os.Handler;
  7. import android.os.HandlerThread;
  8. import android.view.Surface;
  9.  
  10. import java.io.IOException;
  11. import java.nio.ByteBuffer;
  12.  
  13. class VideoEncoder implements Encoder {
  14.  
  15.     // H.264 Advanced Video Coding
  16.     private static final String MIME_TYPE = "video/avc";
  17.     // 5 seconds between I-frames
  18.     private static final int IFRAME_INTERVAL = 5;
  19.  
  20.     private boolean isEncoding = false;
  21.     private static final int TIMEOUT_USEC = 10000;
  22.  
  23.     private Surface inputSurface;
  24.     private MediaCodec encoder;
  25.     private MediaCodec.BufferInfo bufferInfo;
  26.     private VideoHandler.OnVideoEncoderStateListener listener;
  27.     private long lastFrameEncodedAt = 0;
  28.     private long startStreamingAt = 0;
  29.  
  30.     void setOnVideoEncoderStateListener(VideoHandler.OnVideoEncoderStateListener listener) {
  31.         this.listener = listener;
  32.     }
  33.  
  34.     long getLastFrameEncodedAt() {
  35.         return lastFrameEncodedAt;
  36.     }
  37.  
  38.     Surface getInputSurface() {
  39.         return inputSurface;
  40.     }
  41.  
  42.     /**
  43.      * prepare the Encoder. call this before start the encoder.
  44.      */
  45.     void prepare(int width, int height, int bitRate, int frameRate, long startStreamingAt)
  46.             throws IOException {
  47.         this.startStreamingAt = startStreamingAt;
  48.         this.bufferInfo = new MediaCodec.BufferInfo();
  49.         MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, width, height);
  50.         format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
  51.                 MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
  52.         format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
  53.         format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
  54.         format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
  55.  
  56.         encoder = MediaCodec.createEncoderByType(MIME_TYPE);
  57.         encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
  58.         inputSurface = encoder.createInputSurface();
  59.     }
  60.  
  61.     @Override
  62.     public void start() {
  63.         encoder.start();
  64.         isEncoding = true;
  65.         drain();
  66.     }
  67.  
  68.     @Override
  69.     public void stop() {
  70.         if (isEncoding()) {
  71.             encoder.signalEndOfInputStream();
  72.         }
  73.     }
  74.  
  75.     @Override
  76.     public boolean isEncoding() {
  77.         return encoder != null && isEncoding;
  78.     }
  79.  
  80.     void drain() {
  81.         HandlerThread handlerThread = new HandlerThread("VideoEncoder-drain");
  82.         handlerThread.start();
  83.         Handler handler = new Handler(handlerThread.getLooper());
  84.         handler.post(new Runnable() {
  85.             @Override
  86.             public void run() {
  87.                 // keep running... so use a different thread.
  88.                 while (isEncoding) {
  89.                     if (encoder == null) return;
  90.                     ByteBuffer[] encoderOutputBuffers = encoder.getOutputBuffers();
  91.                     int inputBufferId = encoder.dequeueOutputBuffer(bufferInfo, TIMEOUT_USEC);
  92.                     if (inputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
  93.  
  94.                         MediaFormat newFormat = encoder.getOutputFormat();
  95.                         ByteBuffer sps = newFormat.getByteBuffer("csd-0");
  96.                         ByteBuffer pps = newFormat.getByteBuffer("csd-1");
  97.                         byte[] config = new byte[sps.limit() + pps.limit()];
  98.                         sps.get(config, 0, sps.limit());
  99.                         pps.get(config, sps.limit(), pps.limit());
  100.  
  101.                         listener.onVideoDataEncoded(config, config.length, 0);
  102.                     } else {
  103.                         if (inputBufferId > 0) {
  104.                             ByteBuffer encodedData = encoderOutputBuffers[inputBufferId];
  105.                             if (encodedData == null) {
  106.                                 continue;
  107.                             }
  108.  
  109.                             if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
  110.                                 bufferInfo.size = 0;
  111.                             }
  112.  
  113.                             if (bufferInfo.size != 0) {
  114.  
  115.                                 encodedData.position(bufferInfo.offset);
  116.                                 encodedData.limit(bufferInfo.offset + bufferInfo.size);
  117.  
  118.                                 long currentTime = System.currentTimeMillis();
  119.                                 int timestamp = (int) (currentTime - startStreamingAt);
  120.                                 byte[] data = new byte[bufferInfo.size];
  121.                                 encodedData.get(data, 0, bufferInfo.size);
  122.                                 encodedData.position(bufferInfo.offset);
  123.  
  124.                                 listener.onVideoDataEncoded(data, bufferInfo.size, timestamp);
  125.                                 lastFrameEncodedAt = currentTime;
  126.                             }
  127.                             encoder.releaseOutputBuffer(inputBufferId, false);
  128.                         } else if (inputBufferId == MediaCodec.INFO_TRY_AGAIN_LATER) {
  129.                             continue;
  130.                         }
  131.  
  132.                         if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
  133.                             break;
  134.                         }
  135.                     }
  136.                 }
  137.                 release();
  138.             }
  139.         });
  140.     }
  141.  
  142.     private void release() {
  143.         if (encoder != null) {
  144.             isEncoding = false;
  145.             encoder.stop();
  146.             encoder.release();
  147.             encoder = null;
  148.         }
  149.     }
  150. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top