daily pastebin goal
68%
SHARE
TWEET

Untitled

a guest Nov 9th, 2018 78 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. @JNINamespace("webrtc::jni")
  2. public class VideoFileRenderer implements Callbacks, VideoSink {
  3. private static final String TAG = "VideoFileRenderer";
  4. private final HandlerThread renderThread;
  5. private final Handler renderThreadHandler;
  6. private final FileOutputStream videoOutFile;
  7. private final String outputFileName;
  8. private final int outputFileWidth;
  9. private final int outputFileHeight;
  10. private final int outputFrameSize;
  11. private final ByteBuffer outputFrameBuffer;
  12. private EglBase eglBase;
  13. private YuvConverter yuvConverter;
  14. private ArrayList<ByteBuffer> rawFrames = new ArrayList();
  15.  
  16. public VideoFileRenderer(String outputFile, int outputFileWidth, int outputFileHeight, final Context sharedContext) throws IOException {
  17.     if (outputFileWidth % 2 != 1 && outputFileHeight % 2 != 1) {
  18.         this.outputFileName = outputFile;
  19.         this.outputFileWidth = outputFileWidth;
  20.         this.outputFileHeight = outputFileHeight;
  21.         this.outputFrameSize = outputFileWidth * outputFileHeight * 3 / 2;
  22.         this.outputFrameBuffer = ByteBuffer.allocateDirect(this.outputFrameSize);
  23.         this.videoOutFile = new FileOutputStream(outputFile);
  24.         this.videoOutFile.write(("YUV4MPEG2 C420 W" + outputFileWidth + " H" + outputFileHeight + " Ip F30:1 A1:1n").getBytes(Charset.forName("US-ASCII")));
  25.         this.renderThread = new HandlerThread("VideoFileRenderer");
  26.         this.renderThread.start();
  27.         this.renderThreadHandler = new Handler(this.renderThread.getLooper());
  28.         ThreadUtils.invokeAtFrontUninterruptibly(this.renderThreadHandler, new Runnable() {
  29.             public void run() {
  30.                 VideoFileRenderer.this.eglBase = EglBase.create(sharedContext, EglBase.CONFIG_PIXEL_BUFFER);
  31.                 VideoFileRenderer.this.eglBase.createDummyPbufferSurface();
  32.                 VideoFileRenderer.this.eglBase.makeCurrent();
  33.                 VideoFileRenderer.this.yuvConverter = new YuvConverter();
  34.             }
  35.         });
  36.     } else {
  37.         throw new IllegalArgumentException("Does not support uneven width or height");
  38.     }
  39. }
  40.  
  41. public void renderFrame(I420Frame i420Frame) {
  42.     VideoFrame frame = i420Frame.toVideoFrame();
  43.     this.onFrame(frame);
  44.     frame.release();
  45. }
  46.  
  47. public void onFrame(VideoFrame frame) {
  48.     frame.retain();
  49.     this.renderThreadHandler.post(() -> {
  50.         this.renderFrameOnRenderThread(frame);
  51.     });
  52. }
  53.  
  54. private void renderFrameOnRenderThread(VideoFrame frame) {
  55.     Buffer buffer = frame.getBuffer();
  56.     int targetWidth = frame.getRotation() % 180 == 0 ? this.outputFileWidth : this.outputFileHeight;
  57.     int targetHeight = frame.getRotation() % 180 == 0 ? this.outputFileHeight : this.outputFileWidth;
  58.     float frameAspectRatio = (float)buffer.getWidth() / (float)buffer.getHeight();
  59.     float fileAspectRatio = (float)targetWidth / (float)targetHeight;
  60.     int cropWidth = buffer.getWidth();
  61.     int cropHeight = buffer.getHeight();
  62.     if (fileAspectRatio > frameAspectRatio) {
  63.         cropHeight = (int)((float)cropHeight * (frameAspectRatio / fileAspectRatio));
  64.     } else {
  65.         cropWidth = (int)((float)cropWidth * (fileAspectRatio / frameAspectRatio));
  66.     }
  67.  
  68.     int cropX = (buffer.getWidth() - cropWidth) / 2;
  69.     int cropY = (buffer.getHeight() - cropHeight) / 2;
  70.     Buffer scaledBuffer = buffer.cropAndScale(cropX, cropY, cropWidth, cropHeight, targetWidth, targetHeight);
  71.     frame.release();
  72.     I420Buffer i420 = scaledBuffer.toI420();
  73.     scaledBuffer.release();
  74.     ByteBuffer byteBuffer = JniCommon.nativeAllocateByteBuffer(this.outputFrameSize);
  75.     YuvHelper.I420Rotate(i420.getDataY(), i420.getStrideY(), i420.getDataU(), i420.getStrideU(), i420.getDataV(), i420.getStrideV(), byteBuffer, i420.getWidth(), i420.getHeight(), frame.getRotation());
  76.     i420.release();
  77.     byteBuffer.rewind();
  78.     this.rawFrames.add(byteBuffer);
  79. }
  80.  
  81. public void release() {
  82.     CountDownLatch cleanupBarrier = new CountDownLatch(1);
  83.     this.renderThreadHandler.post(() -> {
  84.         this.yuvConverter.release();
  85.         this.eglBase.release();
  86.         this.renderThread.quit();
  87.         cleanupBarrier.countDown();
  88.     });
  89.     ThreadUtils.awaitUninterruptibly(cleanupBarrier);
  90.  
  91.     try {
  92.         Iterator var2 = this.rawFrames.iterator();
  93.  
  94.         while(var2.hasNext()) {
  95.             ByteBuffer buffer = (ByteBuffer)var2.next();
  96.             this.videoOutFile.write("FRAMEn".getBytes(Charset.forName("US-ASCII")));
  97.             byte[] data = new byte[this.outputFrameSize];
  98.             buffer.get(data);
  99.             this.videoOutFile.write(data);
  100.             JniCommon.nativeFreeByteBuffer(buffer);
  101.         }
  102.  
  103.         this.videoOutFile.close();
  104.         Logging.d("VideoFileRenderer", "Video written to disk as " + this.outputFileName + ". Number frames are " + this.rawFrames.size() + " and the dimension of the frames are " + this.outputFileWidth + "x" + this.outputFileHeight + ".");
  105.     } catch (IOException var5) {
  106.         Logging.e("VideoFileRenderer", "Error writing video to disk", var5);
  107.     }
  108.  
  109. }
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
 
Top