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 android.support.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 boolean completeFrame; 58 public final @Nullable Integer qp; 59 60 // TODO(bugs.webrtc.org/9378): Use retain and release from jni code. 61 @Override retain()62 public void retain() { 63 refCountDelegate.retain(); 64 } 65 66 @Override release()67 public void release() { 68 refCountDelegate.release(); 69 } 70 71 @CalledByNative EncodedImage(ByteBuffer buffer, @Nullable Runnable releaseCallback, int encodedWidth, int encodedHeight, long captureTimeNs, FrameType frameType, int rotation, boolean completeFrame, @Nullable Integer qp)72 private EncodedImage(ByteBuffer buffer, @Nullable Runnable releaseCallback, int encodedWidth, 73 int encodedHeight, long captureTimeNs, FrameType frameType, int rotation, 74 boolean completeFrame, @Nullable Integer qp) { 75 this.buffer = buffer; 76 this.encodedWidth = encodedWidth; 77 this.encodedHeight = encodedHeight; 78 this.captureTimeMs = TimeUnit.NANOSECONDS.toMillis(captureTimeNs); 79 this.captureTimeNs = captureTimeNs; 80 this.frameType = frameType; 81 this.rotation = rotation; 82 this.completeFrame = completeFrame; 83 this.qp = qp; 84 this.refCountDelegate = new RefCountDelegate(releaseCallback); 85 } 86 87 @CalledByNative getBuffer()88 private ByteBuffer getBuffer() { 89 return buffer; 90 } 91 92 @CalledByNative getEncodedWidth()93 private int getEncodedWidth() { 94 return encodedWidth; 95 } 96 97 @CalledByNative getEncodedHeight()98 private int getEncodedHeight() { 99 return encodedHeight; 100 } 101 102 @CalledByNative getCaptureTimeNs()103 private long getCaptureTimeNs() { 104 return captureTimeNs; 105 } 106 107 @CalledByNative getFrameType()108 private int getFrameType() { 109 return frameType.getNative(); 110 } 111 112 @CalledByNative getRotation()113 private int getRotation() { 114 return rotation; 115 } 116 117 @CalledByNative getCompleteFrame()118 private boolean getCompleteFrame() { 119 return completeFrame; 120 } 121 122 @CalledByNative getQp()123 private @Nullable Integer getQp() { 124 return qp; 125 } 126 builder()127 public static Builder builder() { 128 return new Builder(); 129 } 130 131 public static class Builder { 132 private ByteBuffer buffer; 133 private @Nullable Runnable releaseCallback; 134 private int encodedWidth; 135 private int encodedHeight; 136 private long captureTimeNs; 137 private EncodedImage.FrameType frameType; 138 private int rotation; 139 private boolean completeFrame; 140 private @Nullable Integer qp; 141 Builder()142 private Builder() {} 143 setBuffer(ByteBuffer buffer, @Nullable Runnable releaseCallback)144 public Builder setBuffer(ByteBuffer buffer, @Nullable Runnable releaseCallback) { 145 this.buffer = buffer; 146 this.releaseCallback = releaseCallback; 147 return this; 148 } 149 setEncodedWidth(int encodedWidth)150 public Builder setEncodedWidth(int encodedWidth) { 151 this.encodedWidth = encodedWidth; 152 return this; 153 } 154 setEncodedHeight(int encodedHeight)155 public Builder setEncodedHeight(int encodedHeight) { 156 this.encodedHeight = encodedHeight; 157 return this; 158 } 159 160 @Deprecated setCaptureTimeMs(long captureTimeMs)161 public Builder setCaptureTimeMs(long captureTimeMs) { 162 this.captureTimeNs = TimeUnit.MILLISECONDS.toNanos(captureTimeMs); 163 return this; 164 } 165 setCaptureTimeNs(long captureTimeNs)166 public Builder setCaptureTimeNs(long captureTimeNs) { 167 this.captureTimeNs = captureTimeNs; 168 return this; 169 } 170 setFrameType(EncodedImage.FrameType frameType)171 public Builder setFrameType(EncodedImage.FrameType frameType) { 172 this.frameType = frameType; 173 return this; 174 } 175 setRotation(int rotation)176 public Builder setRotation(int rotation) { 177 this.rotation = rotation; 178 return this; 179 } 180 setCompleteFrame(boolean completeFrame)181 public Builder setCompleteFrame(boolean completeFrame) { 182 this.completeFrame = completeFrame; 183 return this; 184 } 185 setQp(@ullable Integer qp)186 public Builder setQp(@Nullable Integer qp) { 187 this.qp = qp; 188 return this; 189 } 190 createEncodedImage()191 public EncodedImage createEncodedImage() { 192 return new EncodedImage(buffer, releaseCallback, encodedWidth, encodedHeight, captureTimeNs, 193 frameType, rotation, completeFrame, qp); 194 } 195 } 196 } 197