Advertisement
Guest User

Untitled

a guest
Aug 19th, 2019
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.59 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement