1 /* 2 * Copyright 2017 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 package org.webrtc; 12 13 import androidx.annotation.Nullable; 14 import java.nio.ByteBuffer; 15 import java.util.concurrent.TimeUnit; 16 17 /** 18 * An encoded frame from a video stream. Used as an input for decoders and as an output for 19 * encoders. 20 */ 21 public class EncodedImage implements RefCounted { 22 // Must be kept in sync with common_types.h FrameType. 23 public enum FrameType { 24 EmptyFrame(0), 25 VideoFrameKey(3), 26 VideoFrameDelta(4); 27 28 private final int nativeIndex; 29 FrameType(int nativeIndex)30 private FrameType(int nativeIndex) { 31 this.nativeIndex = nativeIndex; 32 } 33 getNative()34 public int getNative() { 35 return nativeIndex; 36 } 37 38 @CalledByNative("FrameType") fromNativeIndex(int nativeIndex)39 static FrameType fromNativeIndex(int nativeIndex) { 40 for (FrameType type : FrameType.values()) { 41 if (type.getNative() == nativeIndex) { 42 return type; 43 } 44 } 45 throw new IllegalArgumentException("Unknown native frame type: " + nativeIndex); 46 } 47 } 48 49 private final RefCountDelegate refCountDelegate; 50 public final ByteBuffer buffer; 51 public final int encodedWidth; 52 public final int encodedHeight; 53 public final long captureTimeMs; // Deprecated 54 public final long captureTimeNs; 55 public final FrameType frameType; 56 public final int rotation; 57 public final @Nullable Integer qp; 58 59 // TODO(bugs.webrtc.org/9378): Use retain and release from jni code. 60 @Override retain()61 public void retain() { 62 refCountDelegate.retain(); 63 } 64 65 @Override release()66 public void release() { 67 refCountDelegate.release(); 68 } 69 70 @CalledByNative EncodedImage(ByteBuffer buffer, @Nullable Runnable releaseCallback, int encodedWidth, int encodedHeight, long captureTimeNs, FrameType frameType, int rotation, @Nullable Integer qp)71 private EncodedImage(ByteBuffer buffer, @Nullable Runnable releaseCallback, int encodedWidth, 72 int encodedHeight, long captureTimeNs, FrameType frameType, int rotation, 73 @Nullable Integer qp) { 74 this.buffer = buffer; 75 this.encodedWidth = encodedWidth; 76 this.encodedHeight = encodedHeight; 77 this.captureTimeMs = TimeUnit.NANOSECONDS.toMillis(captureTimeNs); 78 this.captureTimeNs = captureTimeNs; 79 this.frameType = frameType; 80 this.rotation = rotation; 81 this.qp = qp; 82 this.refCountDelegate = new RefCountDelegate(releaseCallback); 83 } 84 85 @CalledByNative getBuffer()86 private ByteBuffer getBuffer() { 87 return buffer; 88 } 89 90 @CalledByNative getEncodedWidth()91 private int getEncodedWidth() { 92 return encodedWidth; 93 } 94 95 @CalledByNative getEncodedHeight()96 private int getEncodedHeight() { 97 return encodedHeight; 98 } 99 100 @CalledByNative getCaptureTimeNs()101 private long getCaptureTimeNs() { 102 return captureTimeNs; 103 } 104 105 @CalledByNative getFrameType()106 private int getFrameType() { 107 return frameType.getNative(); 108 } 109 110 @CalledByNative getRotation()111 private int getRotation() { 112 return rotation; 113 } 114 115 @CalledByNative getQp()116 private @Nullable Integer getQp() { 117 return qp; 118 } 119 builder()120 public static Builder builder() { 121 return new Builder(); 122 } 123 124 public static class Builder { 125 private ByteBuffer buffer; 126 private @Nullable Runnable releaseCallback; 127 private int encodedWidth; 128 private int encodedHeight; 129 private long captureTimeNs; 130 private EncodedImage.FrameType frameType; 131 private int rotation; 132 private @Nullable Integer qp; 133 Builder()134 private Builder() {} 135 setBuffer(ByteBuffer buffer, @Nullable Runnable releaseCallback)136 public Builder setBuffer(ByteBuffer buffer, @Nullable Runnable releaseCallback) { 137 this.buffer = buffer; 138 this.releaseCallback = releaseCallback; 139 return this; 140 } 141 setEncodedWidth(int encodedWidth)142 public Builder setEncodedWidth(int encodedWidth) { 143 this.encodedWidth = encodedWidth; 144 return this; 145 } 146 setEncodedHeight(int encodedHeight)147 public Builder setEncodedHeight(int encodedHeight) { 148 this.encodedHeight = encodedHeight; 149 return this; 150 } 151 152 @Deprecated setCaptureTimeMs(long captureTimeMs)153 public Builder setCaptureTimeMs(long captureTimeMs) { 154 this.captureTimeNs = TimeUnit.MILLISECONDS.toNanos(captureTimeMs); 155 return this; 156 } 157 setCaptureTimeNs(long captureTimeNs)158 public Builder setCaptureTimeNs(long captureTimeNs) { 159 this.captureTimeNs = captureTimeNs; 160 return this; 161 } 162 setFrameType(EncodedImage.FrameType frameType)163 public Builder setFrameType(EncodedImage.FrameType frameType) { 164 this.frameType = frameType; 165 return this; 166 } 167 setRotation(int rotation)168 public Builder setRotation(int rotation) { 169 this.rotation = rotation; 170 return this; 171 } 172 setQp(@ullable Integer qp)173 public Builder setQp(@Nullable Integer qp) { 174 this.qp = qp; 175 return this; 176 } 177 createEncodedImage()178 public EncodedImage createEncodedImage() { 179 return new EncodedImage(buffer, releaseCallback, encodedWidth, encodedHeight, captureTimeNs, 180 frameType, rotation, qp); 181 } 182 } 183 } 184