| /* |
| * Copyright 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.media.cts; |
| |
| import com.android.cts.media.R; |
| |
| import android.media.cts.CodecUtils; |
| |
| import android.cts.util.MediaUtils; |
| import android.graphics.ImageFormat; |
| import android.graphics.SurfaceTexture; |
| import android.media.Image; |
| import android.media.MediaCodec; |
| import android.media.MediaCodec.BufferInfo; |
| import android.media.MediaCodecInfo; |
| import android.media.MediaCodecInfo.CodecCapabilities; |
| import android.media.MediaCodecInfo.VideoCapabilities; |
| import android.media.MediaCodecList; |
| import android.media.MediaExtractor; |
| import android.media.MediaFormat; |
| import android.net.Uri; |
| import android.util.Log; |
| import android.util.Pair; |
| import android.util.Range; |
| import android.util.Size; |
| import android.view.Surface; |
| |
| import java.io.IOException; |
| import java.nio.ByteBuffer; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.LinkedList; |
| import java.util.Map; |
| import java.util.Set; |
| |
| public class VideoEncoderTest extends MediaPlayerTestBase { |
| private static final int MAX_SAMPLE_SIZE = 256 * 1024; |
| private static final String TAG = "VideoEncoderTest"; |
| private static final long FRAME_TIMEOUT_MS = 1000; |
| |
| private static final String SOURCE_URL = |
| "android.resource://com.android.cts.media/raw/video_480x360_mp4_h264_871kbps_30fps"; |
| |
| private final boolean DEBUG = false; |
| |
| class VideoStorage { |
| private LinkedList<Pair<ByteBuffer, BufferInfo>> mStream; |
| private MediaFormat mFormat; |
| private int mInputBufferSize; |
| |
| public VideoStorage() { |
| mStream = new LinkedList<Pair<ByteBuffer, BufferInfo>>(); |
| } |
| |
| public void setFormat(MediaFormat format) { |
| mFormat = format; |
| } |
| |
| public void addBuffer(ByteBuffer buffer, BufferInfo info) { |
| ByteBuffer savedBuffer = ByteBuffer.allocate(info.size); |
| savedBuffer.put(buffer); |
| if (info.size > mInputBufferSize) { |
| mInputBufferSize = info.size; |
| } |
| BufferInfo savedInfo = new BufferInfo(); |
| savedInfo.set(0, savedBuffer.position(), info.presentationTimeUs, info.flags); |
| mStream.addLast(Pair.create(savedBuffer, savedInfo)); |
| } |
| |
| private void play(MediaCodec decoder, Surface surface) { |
| decoder.reset(); |
| final Object condition = new Object(); |
| final Iterator<Pair<ByteBuffer, BufferInfo>> it = mStream.iterator(); |
| decoder.setCallback(new MediaCodec.Callback() { |
| public void onOutputBufferAvailable(MediaCodec codec, int ix, BufferInfo info) { |
| codec.releaseOutputBuffer(ix, info.size > 0); |
| if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { |
| synchronized (condition) { |
| condition.notifyAll(); |
| } |
| } |
| } |
| public void onInputBufferAvailable(MediaCodec codec, int ix) { |
| if (it.hasNext()) { |
| Pair<ByteBuffer, BufferInfo> el = it.next(); |
| el.first.clear(); |
| try { |
| codec.getInputBuffer(ix).put(el.first); |
| } catch (java.nio.BufferOverflowException e) { |
| Log.e(TAG, "cannot fit " + el.first.limit() |
| + "-byte encoded buffer into " |
| + codec.getInputBuffer(ix).remaining() |
| + "-byte input buffer of " + codec.getName() |
| + " configured for " + codec.getInputFormat()); |
| throw e; |
| } |
| BufferInfo info = el.second; |
| codec.queueInputBuffer( |
| ix, 0, info.size, info.presentationTimeUs, info.flags); |
| } |
| } |
| public void onError(MediaCodec codec, MediaCodec.CodecException e) { |
| Log.i(TAG, "got codec exception", e); |
| fail("received codec error during decode" + e); |
| } |
| public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) { |
| Log.i(TAG, "got output format " + format); |
| } |
| }); |
| mFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, mInputBufferSize); |
| decoder.configure(mFormat, surface, null /* crypto */, 0 /* flags */); |
| decoder.start(); |
| synchronized (condition) { |
| try { |
| condition.wait(); |
| } catch (InterruptedException e) { |
| fail("playback interrupted"); |
| } |
| } |
| decoder.stop(); |
| } |
| |
| public void playAll(Surface surface) { |
| if (mFormat == null) { |
| Log.i(TAG, "no stream to play"); |
| return; |
| } |
| String mime = mFormat.getString(MediaFormat.KEY_MIME); |
| MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS); |
| for (MediaCodecInfo info : mcl.getCodecInfos()) { |
| if (info.isEncoder()) { |
| continue; |
| } |
| MediaCodec codec = null; |
| try { |
| CodecCapabilities caps = info.getCapabilitiesForType(mime); |
| if (!caps.isFormatSupported(mFormat)) { |
| continue; |
| } |
| codec = MediaCodec.createByCodecName(info.getName()); |
| } catch (IllegalArgumentException | IOException e) { |
| continue; |
| } |
| play(codec, surface); |
| codec.release(); |
| } |
| } |
| } |
| |
| abstract class VideoProcessorBase extends MediaCodec.Callback { |
| private static final String TAG = "VideoProcessorBase"; |
| |
| private MediaExtractor mExtractor; |
| private ByteBuffer mBuffer = ByteBuffer.allocate(MAX_SAMPLE_SIZE); |
| private int mTrackIndex = -1; |
| private boolean mSignaledDecoderEOS; |
| |
| protected boolean mCompleted; |
| protected final Object mCondition = new Object(); |
| |
| protected MediaFormat mDecFormat; |
| protected MediaCodec mDecoder, mEncoder; |
| |
| private VideoStorage mEncodedStream; |
| protected int mFrameRate = 0; |
| protected int mBitRate = 0; |
| |
| protected void open(String path) throws IOException { |
| mExtractor = new MediaExtractor(); |
| if (path.startsWith("android.resource://")) { |
| mExtractor.setDataSource(mContext, Uri.parse(path), null); |
| } else { |
| mExtractor.setDataSource(path); |
| } |
| |
| for (int i = 0; i < mExtractor.getTrackCount(); i++) { |
| MediaFormat fmt = mExtractor.getTrackFormat(i); |
| String mime = fmt.getString(MediaFormat.KEY_MIME).toLowerCase(); |
| if (mime.startsWith("video/")) { |
| mTrackIndex = i; |
| mDecFormat = fmt; |
| mExtractor.selectTrack(i); |
| break; |
| } |
| } |
| mEncodedStream = new VideoStorage(); |
| assertTrue("file " + path + " has no video", mTrackIndex >= 0); |
| } |
| |
| // returns true if encoder supports the size |
| protected boolean initCodecsAndConfigureEncoder( |
| String videoEncName, String outMime, int width, int height, int colorFormat) |
| throws IOException { |
| mDecFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat); |
| |
| MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS); |
| String videoDecName = mcl.findDecoderForFormat(mDecFormat); |
| Log.i(TAG, "decoder for " + mDecFormat + " is " + videoDecName); |
| mDecoder = MediaCodec.createByCodecName(videoDecName); |
| mEncoder = MediaCodec.createByCodecName(videoEncName); |
| |
| mDecoder.setCallback(this); |
| mEncoder.setCallback(this); |
| |
| VideoCapabilities encCaps = |
| mEncoder.getCodecInfo().getCapabilitiesForType(outMime).getVideoCapabilities(); |
| if (!encCaps.isSizeSupported(width, height)) { |
| Log.i(TAG, videoEncName + " does not support size: " + width + "x" + height); |
| return false; |
| } |
| |
| MediaFormat outFmt = MediaFormat.createVideoFormat(outMime, width, height); |
| |
| { |
| int maxWidth = encCaps.getSupportedWidths().getUpper(); |
| int maxHeight = encCaps.getSupportedHeightsFor(maxWidth).getUpper(); |
| int frameRate = mFrameRate; |
| if (frameRate <= 0) { |
| int maxRate = |
| encCaps.getSupportedFrameRatesFor(maxWidth, maxHeight) |
| .getUpper().intValue(); |
| frameRate = Math.min(30, maxRate); |
| } |
| outFmt.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate); |
| |
| int bitRate = mBitRate; |
| if (bitRate <= 0) { |
| bitRate = encCaps.getBitrateRange().clamp( |
| (int)(encCaps.getBitrateRange().getUpper() / |
| Math.sqrt((double)maxWidth * maxHeight / width / height))); |
| } |
| outFmt.setInteger(MediaFormat.KEY_BIT_RATE, bitRate); |
| |
| Log.d(TAG, "frame rate = " + frameRate + ", bit rate = " + bitRate); |
| } |
| outFmt.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1); |
| outFmt.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat); |
| mEncoder.configure(outFmt, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); |
| Log.i(TAG, "encoder input format " + mEncoder.getInputFormat() + " from " + outFmt); |
| return true; |
| } |
| |
| protected void close() { |
| if (mDecoder != null) { |
| mDecoder.release(); |
| mDecoder = null; |
| } |
| if (mEncoder != null) { |
| mEncoder.release(); |
| mEncoder = null; |
| } |
| if (mExtractor != null) { |
| mExtractor.release(); |
| mExtractor = null; |
| } |
| } |
| |
| // returns true if filled buffer |
| protected boolean fillDecoderInputBuffer(int ix) { |
| if (DEBUG) Log.v(TAG, "decoder received input #" + ix); |
| while (!mSignaledDecoderEOS) { |
| int track = mExtractor.getSampleTrackIndex(); |
| if (track >= 0 && track != mTrackIndex) { |
| mExtractor.advance(); |
| continue; |
| } |
| int size = mExtractor.readSampleData(mBuffer, 0); |
| if (size < 0) { |
| // queue decoder input EOS |
| if (DEBUG) Log.v(TAG, "queuing decoder EOS"); |
| mDecoder.queueInputBuffer( |
| ix, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); |
| mSignaledDecoderEOS = true; |
| } else { |
| mBuffer.limit(size); |
| mBuffer.position(0); |
| BufferInfo info = new BufferInfo(); |
| info.set( |
| 0, mBuffer.limit(), mExtractor.getSampleTime(), |
| mExtractor.getSampleFlags()); |
| mDecoder.getInputBuffer(ix).put(mBuffer); |
| if (DEBUG) Log.v(TAG, "queing input #" + ix + " for decoder with timestamp " |
| + info.presentationTimeUs); |
| mDecoder.queueInputBuffer( |
| ix, 0, mBuffer.limit(), info.presentationTimeUs, 0); |
| } |
| mExtractor.advance(); |
| return true; |
| } |
| return false; |
| } |
| |
| protected void emptyEncoderOutputBuffer(int ix, BufferInfo info) { |
| if (DEBUG) Log.v(TAG, "encoder received output #" + ix |
| + " (sz=" + info.size + ", f=" + info.flags |
| + ", ts=" + info.presentationTimeUs + ")"); |
| mEncodedStream.addBuffer(mEncoder.getOutputBuffer(ix), info); |
| if (!mCompleted) { |
| mEncoder.releaseOutputBuffer(ix, false); |
| if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { |
| Log.d(TAG, "encoder received output EOS"); |
| synchronized(mCondition) { |
| mCompleted = true; |
| mCondition.notifyAll(); // condition is always satisfied |
| } |
| } |
| } |
| } |
| |
| protected void saveEncoderFormat(MediaFormat format) { |
| mEncodedStream.setFormat(format); |
| } |
| |
| public void playBack(Surface surface) { |
| mEncodedStream.playAll(surface); |
| } |
| |
| public void setFrameAndBitRates(int frameRate, int bitRate) { |
| mFrameRate = frameRate; |
| mBitRate = bitRate; |
| } |
| |
| public abstract boolean processLoop( |
| String path, String outMime, String videoEncName, |
| int width, int height, boolean optional); |
| }; |
| |
| class VideoProcessor extends VideoProcessorBase { |
| private static final String TAG = "VideoProcessor"; |
| private boolean mWorkInProgress; |
| private boolean mGotDecoderEOS; |
| private boolean mSignaledEncoderEOS; |
| |
| private LinkedList<Pair<Integer, BufferInfo>> mBuffersToRender = |
| new LinkedList<Pair<Integer, BufferInfo>>(); |
| private LinkedList<Integer> mEncInputBuffers = new LinkedList<Integer>(); |
| |
| private int mEncInputBufferSize = -1; |
| |
| @Override |
| public boolean processLoop( |
| String path, String outMime, String videoEncName, |
| int width, int height, boolean optional) { |
| boolean skipped = true; |
| try { |
| open(path); |
| if (!initCodecsAndConfigureEncoder( |
| videoEncName, outMime, width, height, |
| CodecCapabilities.COLOR_FormatYUV420Flexible)) { |
| assertTrue("could not configure encoder for supported size", optional); |
| return !skipped; |
| } |
| skipped = false; |
| |
| mDecoder.configure(mDecFormat, null /* surface */, null /* crypto */, 0); |
| |
| mDecoder.start(); |
| mEncoder.start(); |
| |
| // main loop - process GL ops as only main thread has GL context |
| while (!mCompleted) { |
| Pair<Integer, BufferInfo> decBuffer = null; |
| int encBuffer = -1; |
| synchronized (mCondition) { |
| try { |
| // wait for an encoder input buffer and a decoder output buffer |
| // Use a timeout to avoid stalling the test if it doesn't arrive. |
| if (!haveBuffers() && !mCompleted) { |
| mCondition.wait(FRAME_TIMEOUT_MS); |
| } |
| } catch (InterruptedException ie) { |
| fail("wait interrupted"); // shouldn't happen |
| } |
| if (mCompleted) { |
| break; |
| } |
| if (!haveBuffers()) { |
| fail("timed out after " + mBuffersToRender.size() |
| + " decoder output and " + mEncInputBuffers.size() |
| + " encoder input buffers"); |
| } |
| |
| if (DEBUG) Log.v(TAG, "got image"); |
| decBuffer = mBuffersToRender.removeFirst(); |
| encBuffer = mEncInputBuffers.removeFirst(); |
| if (isEOSOnlyBuffer(decBuffer)) { |
| queueEncoderEOS(decBuffer, encBuffer); |
| continue; |
| } |
| mWorkInProgress = true; |
| } |
| |
| if (mWorkInProgress) { |
| renderDecodedBuffer(decBuffer, encBuffer); |
| synchronized(mCondition) { |
| mWorkInProgress = false; |
| } |
| } |
| } |
| } catch (IOException e) { |
| e.printStackTrace(); |
| fail("received exception " + e); |
| } finally { |
| close(); |
| } |
| return !skipped; |
| } |
| |
| @Override |
| public void onInputBufferAvailable(MediaCodec mediaCodec, int ix) { |
| if (mediaCodec == mDecoder) { |
| // fill input buffer from extractor |
| fillDecoderInputBuffer(ix); |
| } else if (mediaCodec == mEncoder) { |
| synchronized(mCondition) { |
| mEncInputBuffers.addLast(ix); |
| tryToPropagateEOS(); |
| if (haveBuffers()) { |
| mCondition.notifyAll(); |
| } |
| } |
| } else { |
| fail("received input buffer on " + mediaCodec.getName()); |
| } |
| } |
| |
| @Override |
| public void onOutputBufferAvailable( |
| MediaCodec mediaCodec, int ix, BufferInfo info) { |
| if (mediaCodec == mDecoder) { |
| if (DEBUG) Log.v(TAG, "decoder received output #" + ix |
| + " (sz=" + info.size + ", f=" + info.flags |
| + ", ts=" + info.presentationTimeUs + ")"); |
| // render output buffer from decoder |
| if (!mGotDecoderEOS) { |
| boolean eos = (info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0; |
| // can release empty buffers now |
| if (info.size == 0) { |
| mDecoder.releaseOutputBuffer(ix, false /* render */); |
| ix = -1; // dummy index used by render to not render |
| } |
| synchronized(mCondition) { |
| if (ix < 0 && eos && mBuffersToRender.size() > 0) { |
| // move lone EOS flag to last buffer to be rendered |
| mBuffersToRender.peekLast().second.flags |= |
| MediaCodec.BUFFER_FLAG_END_OF_STREAM; |
| } else if (ix >= 0 || eos) { |
| mBuffersToRender.addLast(Pair.create(ix, info)); |
| } |
| if (eos) { |
| tryToPropagateEOS(); |
| mGotDecoderEOS = true; |
| } |
| if (haveBuffers()) { |
| mCondition.notifyAll(); |
| } |
| } |
| } |
| } else if (mediaCodec == mEncoder) { |
| emptyEncoderOutputBuffer(ix, info); |
| } else { |
| fail("received output buffer on " + mediaCodec.getName()); |
| } |
| } |
| |
| private void renderDecodedBuffer(Pair<Integer, BufferInfo> decBuffer, int encBuffer) { |
| // process heavyweight actions under instance lock |
| Image encImage = mEncoder.getInputImage(encBuffer); |
| Image decImage = mDecoder.getOutputImage(decBuffer.first); |
| assertNotNull("could not get encoder image for " + mEncoder.getInputFormat(), encImage); |
| assertNotNull("could not get decoder image for " + mDecoder.getInputFormat(), decImage); |
| assertEquals("incorrect decoder format",decImage.getFormat(), ImageFormat.YUV_420_888); |
| assertEquals("incorrect encoder format", encImage.getFormat(), ImageFormat.YUV_420_888); |
| |
| CodecUtils.copyFlexYUVImage(encImage, decImage); |
| |
| // TRICKY: need this for queueBuffer |
| if (mEncInputBufferSize < 0) { |
| mEncInputBufferSize = mEncoder.getInputBuffer(encBuffer).capacity(); |
| } |
| Log.d(TAG, "queuing output #" + encBuffer + " for encoder (sz=" |
| + mEncInputBufferSize + ", f=" + decBuffer.second.flags |
| + ", ts=" + decBuffer.second.presentationTimeUs + ")"); |
| mEncoder.queueInputBuffer( |
| encBuffer, 0, mEncInputBufferSize, decBuffer.second.presentationTimeUs, |
| decBuffer.second.flags); |
| if ((decBuffer.second.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { |
| mSignaledEncoderEOS = true; |
| } |
| mDecoder.releaseOutputBuffer(decBuffer.first, false /* render */); |
| } |
| |
| @Override |
| public void onError(MediaCodec mediaCodec, MediaCodec.CodecException e) { |
| fail("received error on " + mediaCodec.getName() + ": " + e); |
| } |
| |
| @Override |
| public void onOutputFormatChanged(MediaCodec mediaCodec, MediaFormat mediaFormat) { |
| Log.i(TAG, mediaCodec.getName() + " got new output format " + mediaFormat); |
| if (mediaCodec == mEncoder) { |
| saveEncoderFormat(mediaFormat); |
| } |
| } |
| |
| // next methods are synchronized on mCondition |
| private boolean haveBuffers() { |
| return mEncInputBuffers.size() > 0 && mBuffersToRender.size() > 0 |
| && !mSignaledEncoderEOS; |
| } |
| |
| private boolean isEOSOnlyBuffer(Pair<Integer, BufferInfo> decBuffer) { |
| return decBuffer.first < 0 || decBuffer.second.size == 0; |
| } |
| |
| protected void tryToPropagateEOS() { |
| if (!mWorkInProgress && haveBuffers() && isEOSOnlyBuffer(mBuffersToRender.getFirst())) { |
| Pair<Integer, BufferInfo> decBuffer = mBuffersToRender.removeFirst(); |
| int encBuffer = mEncInputBuffers.removeFirst(); |
| queueEncoderEOS(decBuffer, encBuffer); |
| } |
| } |
| |
| void queueEncoderEOS(Pair<Integer, BufferInfo> decBuffer, int encBuffer) { |
| Log.d(TAG, "signaling encoder EOS"); |
| mEncoder.queueInputBuffer(encBuffer, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); |
| mSignaledEncoderEOS = true; |
| if (decBuffer.first >= 0) { |
| mDecoder.releaseOutputBuffer(decBuffer.first, false /* render */); |
| } |
| } |
| } |
| |
| |
| class SurfaceVideoProcessor extends VideoProcessorBase |
| implements SurfaceTexture.OnFrameAvailableListener { |
| private static final String TAG = "SurfaceVideoProcessor"; |
| private boolean mFrameAvailable; |
| private boolean mGotDecoderEOS; |
| private boolean mSignaledEncoderEOS; |
| |
| private InputSurface mEncSurface; |
| private OutputSurface mDecSurface; |
| private BufferInfo mInfoOnSurface; |
| |
| private LinkedList<Pair<Integer, BufferInfo>> mBuffersToRender = |
| new LinkedList<Pair<Integer, BufferInfo>>(); |
| |
| @Override |
| public boolean processLoop( |
| String path, String outMime, String videoEncName, |
| int width, int height, boolean optional) { |
| boolean skipped = true; |
| try { |
| open(path); |
| if (!initCodecsAndConfigureEncoder( |
| videoEncName, outMime, width, height, |
| CodecCapabilities.COLOR_FormatSurface)) { |
| assertTrue("could not configure encoder for supported size", optional); |
| return !skipped; |
| } |
| skipped = false; |
| |
| mEncSurface = new InputSurface(mEncoder.createInputSurface()); |
| mEncSurface.makeCurrent(); |
| |
| mDecSurface = new OutputSurface(this); |
| //mDecSurface.changeFragmentShader(FRAGMENT_SHADER); |
| mDecoder.configure(mDecFormat, mDecSurface.getSurface(), null /* crypto */, 0); |
| |
| mDecoder.start(); |
| mEncoder.start(); |
| |
| // main loop - process GL ops as only main thread has GL context |
| while (!mCompleted) { |
| BufferInfo info = null; |
| synchronized (mCondition) { |
| try { |
| // wait for mFrameAvailable, which is set by onFrameAvailable(). |
| // Use a timeout to avoid stalling the test if it doesn't arrive. |
| if (!mFrameAvailable && !mCompleted) { |
| mCondition.wait(FRAME_TIMEOUT_MS); |
| } |
| } catch (InterruptedException ie) { |
| fail("wait interrupted"); // shouldn't happen |
| } |
| if (mCompleted) { |
| break; |
| } |
| assertTrue("still waiting for image", mFrameAvailable); |
| if (DEBUG) Log.v(TAG, "got image"); |
| info = mInfoOnSurface; |
| } |
| if (info == null) { |
| continue; |
| } |
| if (info.size > 0) { |
| mDecSurface.latchImage(); |
| if (DEBUG) Log.v(TAG, "latched image"); |
| mFrameAvailable = false; |
| |
| mDecSurface.drawImage(); |
| Log.d(TAG, "encoding frame at " + info.presentationTimeUs * 1000); |
| |
| mEncSurface.setPresentationTime(info.presentationTimeUs * 1000); |
| mEncSurface.swapBuffers(); |
| } |
| if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { |
| mSignaledEncoderEOS = true; |
| Log.d(TAG, "signaling encoder EOS"); |
| mEncoder.signalEndOfInputStream(); |
| } |
| |
| synchronized (mCondition) { |
| mInfoOnSurface = null; |
| if (mBuffersToRender.size() > 0 && mInfoOnSurface == null) { |
| if (DEBUG) Log.v(TAG, "handling postponed frame"); |
| Pair<Integer, BufferInfo> nextBuffer = mBuffersToRender.removeFirst(); |
| renderDecodedBuffer(nextBuffer.first, nextBuffer.second); |
| } |
| } |
| } |
| } catch (IOException e) { |
| e.printStackTrace(); |
| fail("received exception " + e); |
| } finally { |
| close(); |
| if (mEncSurface != null) { |
| mEncSurface.release(); |
| mEncSurface = null; |
| } |
| if (mDecSurface != null) { |
| mDecSurface.release(); |
| mDecSurface = null; |
| } |
| } |
| return !skipped; |
| } |
| |
| @Override |
| public void onFrameAvailable(SurfaceTexture st) { |
| if (DEBUG) Log.v(TAG, "new frame available"); |
| synchronized (mCondition) { |
| assertFalse("mFrameAvailable already set, frame could be dropped", mFrameAvailable); |
| mFrameAvailable = true; |
| mCondition.notifyAll(); |
| } |
| } |
| |
| @Override |
| public void onInputBufferAvailable(MediaCodec mediaCodec, int ix) { |
| if (mediaCodec == mDecoder) { |
| // fill input buffer from extractor |
| fillDecoderInputBuffer(ix); |
| } else { |
| fail("received input buffer on " + mediaCodec.getName()); |
| } |
| } |
| |
| @Override |
| public void onOutputBufferAvailable( |
| MediaCodec mediaCodec, int ix, BufferInfo info) { |
| if (mediaCodec == mDecoder) { |
| if (DEBUG) Log.v(TAG, "decoder received output #" + ix |
| + " (sz=" + info.size + ", f=" + info.flags |
| + ", ts=" + info.presentationTimeUs + ")"); |
| // render output buffer from decoder |
| if (!mGotDecoderEOS) { |
| boolean eos = (info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0; |
| if (eos) { |
| mGotDecoderEOS = true; |
| } |
| // can release empty buffers now |
| if (info.size == 0) { |
| mDecoder.releaseOutputBuffer(ix, false /* render */); |
| ix = -1; // dummy index used by render to not render |
| } |
| if (eos || info.size > 0) { |
| synchronized(mCondition) { |
| if (mInfoOnSurface != null || mBuffersToRender.size() > 0) { |
| if (DEBUG) Log.v(TAG, "postponing render, surface busy"); |
| mBuffersToRender.addLast(Pair.create(ix, info)); |
| } else { |
| renderDecodedBuffer(ix, info); |
| } |
| } |
| } |
| } |
| } else if (mediaCodec == mEncoder) { |
| emptyEncoderOutputBuffer(ix, info); |
| } else { |
| fail("received output buffer on " + mediaCodec.getName()); |
| } |
| } |
| |
| private void renderDecodedBuffer(int ix, BufferInfo info) { |
| boolean eos = (info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0; |
| mInfoOnSurface = info; |
| if (info.size > 0) { |
| Log.d(TAG, "rendering frame #" + ix + " at " + info.presentationTimeUs * 1000 |
| + (eos ? " with EOS" : "")); |
| mDecoder.releaseOutputBuffer(ix, info.presentationTimeUs * 1000); |
| } |
| |
| if (eos && info.size == 0) { |
| if (DEBUG) Log.v(TAG, "decoder output EOS available"); |
| mFrameAvailable = true; |
| mCondition.notifyAll(); |
| } |
| } |
| |
| @Override |
| public void onError(MediaCodec mediaCodec, MediaCodec.CodecException e) { |
| fail("received error on " + mediaCodec.getName() + ": " + e); |
| } |
| |
| @Override |
| public void onOutputFormatChanged(MediaCodec mediaCodec, MediaFormat mediaFormat) { |
| Log.i(TAG, mediaCodec.getName() + " got new output format " + mediaFormat); |
| if (mediaCodec == mEncoder) { |
| saveEncoderFormat(mediaFormat); |
| } |
| } |
| } |
| |
| class Encoder { |
| final private String mName; |
| final private String mMime; |
| final private VideoCapabilities mCaps; |
| |
| final private Map<Size, Set<Size>> mMinMax; // extreme sizes |
| final private Map<Size, Set<Size>> mNearMinMax; // sizes near extreme |
| final private Set<Size> mArbitrary; // arbitrary sizes in the middle |
| final private Set<Size> mSizes; // all non-specifically tested sizes |
| |
| final private int xAlign; |
| final private int yAlign; |
| |
| Encoder(String name, String mime, CodecCapabilities caps) { |
| mName = name; |
| mMime = mime; |
| mCaps = caps.getVideoCapabilities(); |
| |
| /* calculate min/max sizes */ |
| mMinMax = new HashMap<Size, Set<Size>>(); |
| mNearMinMax = new HashMap<Size, Set<Size>>(); |
| mArbitrary = new HashSet<Size>(); |
| mSizes = new HashSet<Size>(); |
| |
| xAlign = mCaps.getWidthAlignment(); |
| yAlign = mCaps.getHeightAlignment(); |
| |
| initializeSizes(); |
| } |
| |
| private void initializeSizes() { |
| for (int x = 0; x < 2; ++x) { |
| for (int y = 0; y < 2; ++y) { |
| addExtremeSizesFor(x, y); |
| } |
| } |
| |
| // initialize arbitrary sizes |
| for (int i = 1; i <= 7; ++i) { |
| int j = ((7 * i) % 11) + 1; |
| int width = alignedPointInRange(i * 0.125, xAlign, mCaps.getSupportedWidths()); |
| int height = alignedPointInRange( |
| j * 0.077, yAlign, mCaps.getSupportedHeightsFor(width)); |
| mArbitrary.add(new Size(width, height)); |
| |
| height = alignedPointInRange(i * 0.125, yAlign, mCaps.getSupportedHeights()); |
| width = alignedPointInRange(j * 0.077, xAlign, mCaps.getSupportedWidthsFor(height)); |
| mArbitrary.add(new Size(width, height)); |
| } |
| mArbitrary.removeAll(mSizes); |
| mSizes.addAll(mArbitrary); |
| if (DEBUG) Log.i(TAG, "arbitrary=" + mArbitrary); |
| } |
| |
| private void addExtremeSizesFor(int x, int y) { |
| Set<Size> minMax = new HashSet<Size>(); |
| Set<Size> nearMinMax = new HashSet<Size>(); |
| |
| for (int dx = 0; dx <= xAlign; dx += xAlign) { |
| for (int dy = 0; dy <= yAlign; dy += yAlign) { |
| Set<Size> bucket = (dx + dy == 0) ? minMax : nearMinMax; |
| try { |
| int width = getExtreme(mCaps.getSupportedWidths(), x, dx); |
| int height = getExtreme(mCaps.getSupportedHeightsFor(width), y, dy); |
| bucket.add(new Size(width, height)); |
| |
| // try max max with more reasonable ratio if too skewed |
| if (x + y == 2 && width >= 4 * height) { |
| Size wideScreen = getLargestSizeForRatio(16, 9); |
| width = getExtreme( |
| mCaps.getSupportedWidths() |
| .intersect(0, wideScreen.getWidth()), x, dx); |
| height = getExtreme(mCaps.getSupportedHeightsFor(width), y, 0); |
| bucket.add(new Size(width, height)); |
| } |
| } catch (IllegalArgumentException e) { |
| } |
| |
| try { |
| int height = getExtreme(mCaps.getSupportedHeights(), y, dy); |
| int width = getExtreme(mCaps.getSupportedWidthsFor(height), x, dx); |
| bucket.add(new Size(width, height)); |
| |
| // try max max with more reasonable ratio if too skewed |
| if (x + y == 2 && height >= 4 * width) { |
| Size wideScreen = getLargestSizeForRatio(9, 16); |
| height = getExtreme( |
| mCaps.getSupportedHeights() |
| .intersect(0, wideScreen.getHeight()), y, dy); |
| width = getExtreme(mCaps.getSupportedWidthsFor(height), x, dx); |
| bucket.add(new Size(width, height)); |
| } |
| } catch (IllegalArgumentException e) { |
| } |
| } |
| } |
| |
| // keep unique sizes |
| minMax.removeAll(mSizes); |
| mSizes.addAll(minMax); |
| nearMinMax.removeAll(mSizes); |
| mSizes.addAll(nearMinMax); |
| |
| mMinMax.put(new Size(x, y), minMax); |
| mNearMinMax.put(new Size(x, y), nearMinMax); |
| if (DEBUG) Log.i(TAG, x + "x" + y + ": minMax=" + mMinMax + ", near=" + mNearMinMax); |
| } |
| |
| private int alignInRange(double value, int align, Range<Integer> range) { |
| return range.clamp(align * (int)Math.round(value / align)); |
| } |
| |
| /* point should be between 0. and 1. */ |
| private int alignedPointInRange(double point, int align, Range<Integer> range) { |
| return alignInRange( |
| range.getLower() + point * (range.getUpper() - range.getLower()), align, range); |
| } |
| |
| private int getExtreme(Range<Integer> range, int i, int delta) { |
| int dim = i == 1 ? range.getUpper() - delta : range.getLower() + delta; |
| if (delta == 0 |
| || (dim > range.getLower() && dim < range.getUpper())) { |
| return dim; |
| } |
| throw new IllegalArgumentException(); |
| } |
| |
| private Size getLargestSizeForRatio(int x, int y) { |
| Range<Integer> widthRange = mCaps.getSupportedWidths(); |
| Range<Integer> heightRange = mCaps.getSupportedHeightsFor(widthRange.getUpper()); |
| final int xAlign = mCaps.getWidthAlignment(); |
| final int yAlign = mCaps.getHeightAlignment(); |
| |
| // scale by alignment |
| int width = alignInRange( |
| Math.sqrt(widthRange.getUpper() * heightRange.getUpper() * (double)x / y), |
| xAlign, widthRange); |
| int height = alignInRange( |
| width * (double)y / x, yAlign, mCaps.getSupportedHeightsFor(width)); |
| return new Size(width, height); |
| } |
| |
| |
| public boolean testExtreme(int x, int y, boolean flexYUV, boolean near) { |
| boolean skipped = true; |
| for (Size s : (near ? mNearMinMax : mMinMax).get(new Size(x, y))) { |
| if (test(s.getWidth(), s.getHeight(), false /* optional */, flexYUV)) { |
| skipped = false; |
| } |
| } |
| return !skipped; |
| } |
| |
| public boolean testArbitrary(boolean flexYUV) { |
| boolean skipped = true; |
| for (Size s : mArbitrary) { |
| if (test(s.getWidth(), s.getHeight(), false /* optional */, flexYUV)) { |
| skipped = false; |
| } |
| } |
| return !skipped; |
| } |
| |
| public boolean testSpecific(int width, int height, boolean flexYUV) { |
| // already tested by one of the min/max tests |
| if (mSizes.contains(new Size(width, height))) { |
| return false; |
| } |
| return test(width, height, true /* optional */, flexYUV); |
| } |
| |
| public boolean testDetailed( |
| int width, int height, int frameRate, int bitRate, boolean flexYUV) { |
| return test(width, height, frameRate, bitRate, true /* optional */, flexYUV); |
| } |
| |
| public boolean testSupport(int width, int height, int frameRate, int bitRate) { |
| return mCaps.areSizeAndRateSupported(width, height, frameRate) && |
| mCaps.getBitrateRange().contains(bitRate); |
| } |
| |
| private boolean test(int width, int height, boolean optional, boolean flexYUV) { |
| return test(width, height, 0 /* frameRate */, 0 /* bitRate */, optional, flexYUV); |
| } |
| |
| private boolean test(int width, int height, int frameRate, int bitRate, |
| boolean optional, boolean flexYUV) { |
| Log.i(TAG, "testing " + mMime + " on " + mName + " for " + width + "x" + height |
| + (flexYUV ? " flexYUV" : " surface")); |
| |
| VideoProcessorBase processor = |
| flexYUV ? new VideoProcessor() : new SurfaceVideoProcessor(); |
| |
| processor.setFrameAndBitRates(frameRate, bitRate); |
| |
| // We are using a resource URL as an example |
| boolean success = processor.processLoop( |
| SOURCE_URL, mMime, mName, width, height, optional); |
| if (success) { |
| processor.playBack(getActivity().getSurfaceHolder().getSurface()); |
| } |
| return success; |
| } |
| } |
| |
| private Encoder[] googH265() { return goog(MediaFormat.MIMETYPE_VIDEO_HEVC); } |
| private Encoder[] googH264() { return goog(MediaFormat.MIMETYPE_VIDEO_AVC); } |
| private Encoder[] googH263() { return goog(MediaFormat.MIMETYPE_VIDEO_H263); } |
| private Encoder[] googMpeg4() { return goog(MediaFormat.MIMETYPE_VIDEO_MPEG4); } |
| private Encoder[] googVP8() { return goog(MediaFormat.MIMETYPE_VIDEO_VP8); } |
| private Encoder[] googVP9() { return goog(MediaFormat.MIMETYPE_VIDEO_VP9); } |
| |
| private Encoder[] otherH265() { return other(MediaFormat.MIMETYPE_VIDEO_HEVC); } |
| private Encoder[] otherH264() { return other(MediaFormat.MIMETYPE_VIDEO_AVC); } |
| private Encoder[] otherH263() { return other(MediaFormat.MIMETYPE_VIDEO_H263); } |
| private Encoder[] otherMpeg4() { return other(MediaFormat.MIMETYPE_VIDEO_MPEG4); } |
| private Encoder[] otherVP8() { return other(MediaFormat.MIMETYPE_VIDEO_VP8); } |
| private Encoder[] otherVP9() { return other(MediaFormat.MIMETYPE_VIDEO_VP9); } |
| |
| private Encoder[] goog(String mime) { |
| return encoders(mime, true /* goog */); |
| } |
| |
| private Encoder[] other(String mime) { |
| return encoders(mime, false /* goog */); |
| } |
| |
| private Encoder[] combineArray(Encoder[] a, Encoder[] b) { |
| Encoder[] all = new Encoder[a.length + b.length]; |
| System.arraycopy(a, 0, all, 0, a.length); |
| System.arraycopy(b, 0, all, a.length, b.length); |
| return all; |
| } |
| |
| private Encoder[] h264() { |
| return combineArray(googH264(), otherH264()); |
| } |
| |
| private Encoder[] vp8() { |
| return combineArray(googVP8(), otherVP8()); |
| } |
| |
| private Encoder[] encoders(String mime, boolean goog) { |
| MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS); |
| ArrayList<Encoder> result = new ArrayList<Encoder>(); |
| |
| for (MediaCodecInfo info : mcl.getCodecInfos()) { |
| if (!info.isEncoder() |
| || info.getName().toLowerCase().startsWith("omx.google.") != goog) { |
| continue; |
| } |
| try { |
| CodecCapabilities caps = info.getCapabilitiesForType(mime); |
| result.add(new Encoder(info.getName(), mime, caps)); |
| } catch (IllegalArgumentException e) { // mime is not supported |
| } |
| } |
| return result.toArray(new Encoder[result.size()]); |
| } |
| |
| public void testGoogH265FlexMinMin() { minmin(googH265(), true /* flex */); } |
| public void testGoogH265SurfMinMin() { minmin(googH265(), false /* flex */); } |
| public void testGoogH264FlexMinMin() { minmin(googH264(), true /* flex */); } |
| public void testGoogH264SurfMinMin() { minmin(googH264(), false /* flex */); } |
| public void testGoogH263FlexMinMin() { minmin(googH263(), true /* flex */); } |
| public void testGoogH263SurfMinMin() { minmin(googH263(), false /* flex */); } |
| public void testGoogMpeg4FlexMinMin() { minmin(googMpeg4(), true /* flex */); } |
| public void testGoogMpeg4SurfMinMin() { minmin(googMpeg4(), false /* flex */); } |
| public void testGoogVP8FlexMinMin() { minmin(googVP8(), true /* flex */); } |
| public void testGoogVP8SurfMinMin() { minmin(googVP8(), false /* flex */); } |
| public void testGoogVP9FlexMinMin() { minmin(googVP9(), true /* flex */); } |
| public void testGoogVP9SurfMinMin() { minmin(googVP9(), false /* flex */); } |
| |
| public void testOtherH265FlexMinMin() { minmin(otherH265(), true /* flex */); } |
| public void testOtherH265SurfMinMin() { minmin(otherH265(), false /* flex */); } |
| public void testOtherH264FlexMinMin() { minmin(otherH264(), true /* flex */); } |
| public void testOtherH264SurfMinMin() { minmin(otherH264(), false /* flex */); } |
| public void testOtherH263FlexMinMin() { minmin(otherH263(), true /* flex */); } |
| public void testOtherH263SurfMinMin() { minmin(otherH263(), false /* flex */); } |
| public void testOtherMpeg4FlexMinMin() { minmin(otherMpeg4(), true /* flex */); } |
| public void testOtherMpeg4SurfMinMin() { minmin(otherMpeg4(), false /* flex */); } |
| public void testOtherVP8FlexMinMin() { minmin(otherVP8(), true /* flex */); } |
| public void testOtherVP8SurfMinMin() { minmin(otherVP8(), false /* flex */); } |
| public void testOtherVP9FlexMinMin() { minmin(otherVP9(), true /* flex */); } |
| public void testOtherVP9SurfMinMin() { minmin(otherVP9(), false /* flex */); } |
| |
| public void testGoogH265FlexMinMax() { minmax(googH265(), true /* flex */); } |
| public void testGoogH265SurfMinMax() { minmax(googH265(), false /* flex */); } |
| public void testGoogH264FlexMinMax() { minmax(googH264(), true /* flex */); } |
| public void testGoogH264SurfMinMax() { minmax(googH264(), false /* flex */); } |
| public void testGoogH263FlexMinMax() { minmax(googH263(), true /* flex */); } |
| public void testGoogH263SurfMinMax() { minmax(googH263(), false /* flex */); } |
| public void testGoogMpeg4FlexMinMax() { minmax(googMpeg4(), true /* flex */); } |
| public void testGoogMpeg4SurfMinMax() { minmax(googMpeg4(), false /* flex */); } |
| public void testGoogVP8FlexMinMax() { minmax(googVP8(), true /* flex */); } |
| public void testGoogVP8SurfMinMax() { minmax(googVP8(), false /* flex */); } |
| public void testGoogVP9FlexMinMax() { minmax(googVP9(), true /* flex */); } |
| public void testGoogVP9SurfMinMax() { minmax(googVP9(), false /* flex */); } |
| |
| public void testOtherH265FlexMinMax() { minmax(otherH265(), true /* flex */); } |
| public void testOtherH265SurfMinMax() { minmax(otherH265(), false /* flex */); } |
| public void testOtherH264FlexMinMax() { minmax(otherH264(), true /* flex */); } |
| public void testOtherH264SurfMinMax() { minmax(otherH264(), false /* flex */); } |
| public void testOtherH263FlexMinMax() { minmax(otherH263(), true /* flex */); } |
| public void testOtherH263SurfMinMax() { minmax(otherH263(), false /* flex */); } |
| public void testOtherMpeg4FlexMinMax() { minmax(otherMpeg4(), true /* flex */); } |
| public void testOtherMpeg4SurfMinMax() { minmax(otherMpeg4(), false /* flex */); } |
| public void testOtherVP8FlexMinMax() { minmax(otherVP8(), true /* flex */); } |
| public void testOtherVP8SurfMinMax() { minmax(otherVP8(), false /* flex */); } |
| public void testOtherVP9FlexMinMax() { minmax(otherVP9(), true /* flex */); } |
| public void testOtherVP9SurfMinMax() { minmax(otherVP9(), false /* flex */); } |
| |
| public void testGoogH265FlexMaxMin() { maxmin(googH265(), true /* flex */); } |
| public void testGoogH265SurfMaxMin() { maxmin(googH265(), false /* flex */); } |
| public void testGoogH264FlexMaxMin() { maxmin(googH264(), true /* flex */); } |
| public void testGoogH264SurfMaxMin() { maxmin(googH264(), false /* flex */); } |
| public void testGoogH263FlexMaxMin() { maxmin(googH263(), true /* flex */); } |
| public void testGoogH263SurfMaxMin() { maxmin(googH263(), false /* flex */); } |
| public void testGoogMpeg4FlexMaxMin() { maxmin(googMpeg4(), true /* flex */); } |
| public void testGoogMpeg4SurfMaxMin() { maxmin(googMpeg4(), false /* flex */); } |
| public void testGoogVP8FlexMaxMin() { maxmin(googVP8(), true /* flex */); } |
| public void testGoogVP8SurfMaxMin() { maxmin(googVP8(), false /* flex */); } |
| public void testGoogVP9FlexMaxMin() { maxmin(googVP9(), true /* flex */); } |
| public void testGoogVP9SurfMaxMin() { maxmin(googVP9(), false /* flex */); } |
| |
| public void testOtherH265FlexMaxMin() { maxmin(otherH265(), true /* flex */); } |
| public void testOtherH265SurfMaxMin() { maxmin(otherH265(), false /* flex */); } |
| public void testOtherH264FlexMaxMin() { maxmin(otherH264(), true /* flex */); } |
| public void testOtherH264SurfMaxMin() { maxmin(otherH264(), false /* flex */); } |
| public void testOtherH263FlexMaxMin() { maxmin(otherH263(), true /* flex */); } |
| public void testOtherH263SurfMaxMin() { maxmin(otherH263(), false /* flex */); } |
| public void testOtherMpeg4FlexMaxMin() { maxmin(otherMpeg4(), true /* flex */); } |
| public void testOtherMpeg4SurfMaxMin() { maxmin(otherMpeg4(), false /* flex */); } |
| public void testOtherVP8FlexMaxMin() { maxmin(otherVP8(), true /* flex */); } |
| public void testOtherVP8SurfMaxMin() { maxmin(otherVP8(), false /* flex */); } |
| public void testOtherVP9FlexMaxMin() { maxmin(otherVP9(), true /* flex */); } |
| public void testOtherVP9SurfMaxMin() { maxmin(otherVP9(), false /* flex */); } |
| |
| public void testGoogH265FlexMaxMax() { maxmax(googH265(), true /* flex */); } |
| public void testGoogH265SurfMaxMax() { maxmax(googH265(), false /* flex */); } |
| public void testGoogH264FlexMaxMax() { maxmax(googH264(), true /* flex */); } |
| public void testGoogH264SurfMaxMax() { maxmax(googH264(), false /* flex */); } |
| public void testGoogH263FlexMaxMax() { maxmax(googH263(), true /* flex */); } |
| public void testGoogH263SurfMaxMax() { maxmax(googH263(), false /* flex */); } |
| public void testGoogMpeg4FlexMaxMax() { maxmax(googMpeg4(), true /* flex */); } |
| public void testGoogMpeg4SurfMaxMax() { maxmax(googMpeg4(), false /* flex */); } |
| public void testGoogVP8FlexMaxMax() { maxmax(googVP8(), true /* flex */); } |
| public void testGoogVP8SurfMaxMax() { maxmax(googVP8(), false /* flex */); } |
| public void testGoogVP9FlexMaxMax() { maxmax(googVP9(), true /* flex */); } |
| public void testGoogVP9SurfMaxMax() { maxmax(googVP9(), false /* flex */); } |
| |
| public void testOtherH265FlexMaxMax() { maxmax(otherH265(), true /* flex */); } |
| public void testOtherH265SurfMaxMax() { maxmax(otherH265(), false /* flex */); } |
| public void testOtherH264FlexMaxMax() { maxmax(otherH264(), true /* flex */); } |
| public void testOtherH264SurfMaxMax() { maxmax(otherH264(), false /* flex */); } |
| public void testOtherH263FlexMaxMax() { maxmax(otherH263(), true /* flex */); } |
| public void testOtherH263SurfMaxMax() { maxmax(otherH263(), false /* flex */); } |
| public void testOtherMpeg4FlexMaxMax() { maxmax(otherMpeg4(), true /* flex */); } |
| public void testOtherMpeg4SurfMaxMax() { maxmax(otherMpeg4(), false /* flex */); } |
| public void testOtherVP8FlexMaxMax() { maxmax(otherVP8(), true /* flex */); } |
| public void testOtherVP8SurfMaxMax() { maxmax(otherVP8(), false /* flex */); } |
| public void testOtherVP9FlexMaxMax() { maxmax(otherVP9(), true /* flex */); } |
| public void testOtherVP9SurfMaxMax() { maxmax(otherVP9(), false /* flex */); } |
| |
| public void testGoogH265FlexNearMinMin() { nearminmin(googH265(), true /* flex */); } |
| public void testGoogH265SurfNearMinMin() { nearminmin(googH265(), false /* flex */); } |
| public void testGoogH264FlexNearMinMin() { nearminmin(googH264(), true /* flex */); } |
| public void testGoogH264SurfNearMinMin() { nearminmin(googH264(), false /* flex */); } |
| public void testGoogH263FlexNearMinMin() { nearminmin(googH263(), true /* flex */); } |
| public void testGoogH263SurfNearMinMin() { nearminmin(googH263(), false /* flex */); } |
| public void testGoogMpeg4FlexNearMinMin() { nearminmin(googMpeg4(), true /* flex */); } |
| public void testGoogMpeg4SurfNearMinMin() { nearminmin(googMpeg4(), false /* flex */); } |
| public void testGoogVP8FlexNearMinMin() { nearminmin(googVP8(), true /* flex */); } |
| public void testGoogVP8SurfNearMinMin() { nearminmin(googVP8(), false /* flex */); } |
| public void testGoogVP9FlexNearMinMin() { nearminmin(googVP9(), true /* flex */); } |
| public void testGoogVP9SurfNearMinMin() { nearminmin(googVP9(), false /* flex */); } |
| |
| public void testOtherH265FlexNearMinMin() { nearminmin(otherH265(), true /* flex */); } |
| public void testOtherH265SurfNearMinMin() { nearminmin(otherH265(), false /* flex */); } |
| public void testOtherH264FlexNearMinMin() { nearminmin(otherH264(), true /* flex */); } |
| public void testOtherH264SurfNearMinMin() { nearminmin(otherH264(), false /* flex */); } |
| public void testOtherH263FlexNearMinMin() { nearminmin(otherH263(), true /* flex */); } |
| public void testOtherH263SurfNearMinMin() { nearminmin(otherH263(), false /* flex */); } |
| public void testOtherMpeg4FlexNearMinMin() { nearminmin(otherMpeg4(), true /* flex */); } |
| public void testOtherMpeg4SurfNearMinMin() { nearminmin(otherMpeg4(), false /* flex */); } |
| public void testOtherVP8FlexNearMinMin() { nearminmin(otherVP8(), true /* flex */); } |
| public void testOtherVP8SurfNearMinMin() { nearminmin(otherVP8(), false /* flex */); } |
| public void testOtherVP9FlexNearMinMin() { nearminmin(otherVP9(), true /* flex */); } |
| public void testOtherVP9SurfNearMinMin() { nearminmin(otherVP9(), false /* flex */); } |
| |
| public void testGoogH265FlexNearMinMax() { nearminmax(googH265(), true /* flex */); } |
| public void testGoogH265SurfNearMinMax() { nearminmax(googH265(), false /* flex */); } |
| public void testGoogH264FlexNearMinMax() { nearminmax(googH264(), true /* flex */); } |
| public void testGoogH264SurfNearMinMax() { nearminmax(googH264(), false /* flex */); } |
| public void testGoogH263FlexNearMinMax() { nearminmax(googH263(), true /* flex */); } |
| public void testGoogH263SurfNearMinMax() { nearminmax(googH263(), false /* flex */); } |
| public void testGoogMpeg4FlexNearMinMax() { nearminmax(googMpeg4(), true /* flex */); } |
| public void testGoogMpeg4SurfNearMinMax() { nearminmax(googMpeg4(), false /* flex */); } |
| public void testGoogVP8FlexNearMinMax() { nearminmax(googVP8(), true /* flex */); } |
| public void testGoogVP8SurfNearMinMax() { nearminmax(googVP8(), false /* flex */); } |
| public void testGoogVP9FlexNearMinMax() { nearminmax(googVP9(), true /* flex */); } |
| public void testGoogVP9SurfNearMinMax() { nearminmax(googVP9(), false /* flex */); } |
| |
| public void testOtherH265FlexNearMinMax() { nearminmax(otherH265(), true /* flex */); } |
| public void testOtherH265SurfNearMinMax() { nearminmax(otherH265(), false /* flex */); } |
| public void testOtherH264FlexNearMinMax() { nearminmax(otherH264(), true /* flex */); } |
| public void testOtherH264SurfNearMinMax() { nearminmax(otherH264(), false /* flex */); } |
| public void testOtherH263FlexNearMinMax() { nearminmax(otherH263(), true /* flex */); } |
| public void testOtherH263SurfNearMinMax() { nearminmax(otherH263(), false /* flex */); } |
| public void testOtherMpeg4FlexNearMinMax() { nearminmax(otherMpeg4(), true /* flex */); } |
| public void testOtherMpeg4SurfNearMinMax() { nearminmax(otherMpeg4(), false /* flex */); } |
| public void testOtherVP8FlexNearMinMax() { nearminmax(otherVP8(), true /* flex */); } |
| public void testOtherVP8SurfNearMinMax() { nearminmax(otherVP8(), false /* flex */); } |
| public void testOtherVP9FlexNearMinMax() { nearminmax(otherVP9(), true /* flex */); } |
| public void testOtherVP9SurfNearMinMax() { nearminmax(otherVP9(), false /* flex */); } |
| |
| public void testGoogH265FlexNearMaxMin() { nearmaxmin(googH265(), true /* flex */); } |
| public void testGoogH265SurfNearMaxMin() { nearmaxmin(googH265(), false /* flex */); } |
| public void testGoogH264FlexNearMaxMin() { nearmaxmin(googH264(), true /* flex */); } |
| public void testGoogH264SurfNearMaxMin() { nearmaxmin(googH264(), false /* flex */); } |
| public void testGoogH263FlexNearMaxMin() { nearmaxmin(googH263(), true /* flex */); } |
| public void testGoogH263SurfNearMaxMin() { nearmaxmin(googH263(), false /* flex */); } |
| public void testGoogMpeg4FlexNearMaxMin() { nearmaxmin(googMpeg4(), true /* flex */); } |
| public void testGoogMpeg4SurfNearMaxMin() { nearmaxmin(googMpeg4(), false /* flex */); } |
| public void testGoogVP8FlexNearMaxMin() { nearmaxmin(googVP8(), true /* flex */); } |
| public void testGoogVP8SurfNearMaxMin() { nearmaxmin(googVP8(), false /* flex */); } |
| public void testGoogVP9FlexNearMaxMin() { nearmaxmin(googVP9(), true /* flex */); } |
| public void testGoogVP9SurfNearMaxMin() { nearmaxmin(googVP9(), false /* flex */); } |
| |
| public void testOtherH265FlexNearMaxMin() { nearmaxmin(otherH265(), true /* flex */); } |
| public void testOtherH265SurfNearMaxMin() { nearmaxmin(otherH265(), false /* flex */); } |
| public void testOtherH264FlexNearMaxMin() { nearmaxmin(otherH264(), true /* flex */); } |
| public void testOtherH264SurfNearMaxMin() { nearmaxmin(otherH264(), false /* flex */); } |
| public void testOtherH263FlexNearMaxMin() { nearmaxmin(otherH263(), true /* flex */); } |
| public void testOtherH263SurfNearMaxMin() { nearmaxmin(otherH263(), false /* flex */); } |
| public void testOtherMpeg4FlexNearMaxMin() { nearmaxmin(otherMpeg4(), true /* flex */); } |
| public void testOtherMpeg4SurfNearMaxMin() { nearmaxmin(otherMpeg4(), false /* flex */); } |
| public void testOtherVP8FlexNearMaxMin() { nearmaxmin(otherVP8(), true /* flex */); } |
| public void testOtherVP8SurfNearMaxMin() { nearmaxmin(otherVP8(), false /* flex */); } |
| public void testOtherVP9FlexNearMaxMin() { nearmaxmin(otherVP9(), true /* flex */); } |
| public void testOtherVP9SurfNearMaxMin() { nearmaxmin(otherVP9(), false /* flex */); } |
| |
| public void testGoogH265FlexNearMaxMax() { nearmaxmax(googH265(), true /* flex */); } |
| public void testGoogH265SurfNearMaxMax() { nearmaxmax(googH265(), false /* flex */); } |
| public void testGoogH264FlexNearMaxMax() { nearmaxmax(googH264(), true /* flex */); } |
| public void testGoogH264SurfNearMaxMax() { nearmaxmax(googH264(), false /* flex */); } |
| public void testGoogH263FlexNearMaxMax() { nearmaxmax(googH263(), true /* flex */); } |
| public void testGoogH263SurfNearMaxMax() { nearmaxmax(googH263(), false /* flex */); } |
| public void testGoogMpeg4FlexNearMaxMax() { nearmaxmax(googMpeg4(), true /* flex */); } |
| public void testGoogMpeg4SurfNearMaxMax() { nearmaxmax(googMpeg4(), false /* flex */); } |
| public void testGoogVP8FlexNearMaxMax() { nearmaxmax(googVP8(), true /* flex */); } |
| public void testGoogVP8SurfNearMaxMax() { nearmaxmax(googVP8(), false /* flex */); } |
| public void testGoogVP9FlexNearMaxMax() { nearmaxmax(googVP9(), true /* flex */); } |
| public void testGoogVP9SurfNearMaxMax() { nearmaxmax(googVP9(), false /* flex */); } |
| |
| public void testOtherH265FlexNearMaxMax() { nearmaxmax(otherH265(), true /* flex */); } |
| public void testOtherH265SurfNearMaxMax() { nearmaxmax(otherH265(), false /* flex */); } |
| public void testOtherH264FlexNearMaxMax() { nearmaxmax(otherH264(), true /* flex */); } |
| public void testOtherH264SurfNearMaxMax() { nearmaxmax(otherH264(), false /* flex */); } |
| public void testOtherH263FlexNearMaxMax() { nearmaxmax(otherH263(), true /* flex */); } |
| public void testOtherH263SurfNearMaxMax() { nearmaxmax(otherH263(), false /* flex */); } |
| public void testOtherMpeg4FlexNearMaxMax() { nearmaxmax(otherMpeg4(), true /* flex */); } |
| public void testOtherMpeg4SurfNearMaxMax() { nearmaxmax(otherMpeg4(), false /* flex */); } |
| public void testOtherVP8FlexNearMaxMax() { nearmaxmax(otherVP8(), true /* flex */); } |
| public void testOtherVP8SurfNearMaxMax() { nearmaxmax(otherVP8(), false /* flex */); } |
| public void testOtherVP9FlexNearMaxMax() { nearmaxmax(otherVP9(), true /* flex */); } |
| public void testOtherVP9SurfNearMaxMax() { nearmaxmax(otherVP9(), false /* flex */); } |
| |
| public void testGoogH265FlexArbitrary() { arbitrary(googH265(), true /* flex */); } |
| public void testGoogH265SurfArbitrary() { arbitrary(googH265(), false /* flex */); } |
| public void testGoogH264FlexArbitrary() { arbitrary(googH264(), true /* flex */); } |
| public void testGoogH264SurfArbitrary() { arbitrary(googH264(), false /* flex */); } |
| public void testGoogH263FlexArbitrary() { arbitrary(googH263(), true /* flex */); } |
| public void testGoogH263SurfArbitrary() { arbitrary(googH263(), false /* flex */); } |
| public void testGoogMpeg4FlexArbitrary() { arbitrary(googMpeg4(), true /* flex */); } |
| public void testGoogMpeg4SurfArbitrary() { arbitrary(googMpeg4(), false /* flex */); } |
| public void testGoogVP8FlexArbitrary() { arbitrary(googVP8(), true /* flex */); } |
| public void testGoogVP8SurfArbitrary() { arbitrary(googVP8(), false /* flex */); } |
| public void testGoogVP9FlexArbitrary() { arbitrary(googVP9(), true /* flex */); } |
| public void testGoogVP9SurfArbitrary() { arbitrary(googVP9(), false /* flex */); } |
| |
| public void testOtherH265FlexArbitrary() { arbitrary(otherH265(), true /* flex */); } |
| public void testOtherH265SurfArbitrary() { arbitrary(otherH265(), false /* flex */); } |
| public void testOtherH264FlexArbitrary() { arbitrary(otherH264(), true /* flex */); } |
| public void testOtherH264SurfArbitrary() { arbitrary(otherH264(), false /* flex */); } |
| public void testOtherH263FlexArbitrary() { arbitrary(otherH263(), true /* flex */); } |
| public void testOtherH263SurfArbitrary() { arbitrary(otherH263(), false /* flex */); } |
| public void testOtherMpeg4FlexArbitrary() { arbitrary(otherMpeg4(), true /* flex */); } |
| public void testOtherMpeg4SurfArbitrary() { arbitrary(otherMpeg4(), false /* flex */); } |
| public void testOtherVP8FlexArbitrary() { arbitrary(otherVP8(), true /* flex */); } |
| public void testOtherVP8SurfArbitrary() { arbitrary(otherVP8(), false /* flex */); } |
| public void testOtherVP9FlexArbitrary() { arbitrary(otherVP9(), true /* flex */); } |
| public void testOtherVP9SurfArbitrary() { arbitrary(otherVP9(), false /* flex */); } |
| |
| public void testGoogH265FlexQCIF() { specific(googH265(), 176, 144, true /* flex */); } |
| public void testGoogH265SurfQCIF() { specific(googH265(), 176, 144, false /* flex */); } |
| public void testGoogH264FlexQCIF() { specific(googH264(), 176, 144, true /* flex */); } |
| public void testGoogH264SurfQCIF() { specific(googH264(), 176, 144, false /* flex */); } |
| public void testGoogH263FlexQCIF() { specific(googH263(), 176, 144, true /* flex */); } |
| public void testGoogH263SurfQCIF() { specific(googH263(), 176, 144, false /* flex */); } |
| public void testGoogMpeg4FlexQCIF() { specific(googMpeg4(), 176, 144, true /* flex */); } |
| public void testGoogMpeg4SurfQCIF() { specific(googMpeg4(), 176, 144, false /* flex */); } |
| public void testGoogVP8FlexQCIF() { specific(googVP8(), 176, 144, true /* flex */); } |
| public void testGoogVP8SurfQCIF() { specific(googVP8(), 176, 144, false /* flex */); } |
| public void testGoogVP9FlexQCIF() { specific(googVP9(), 176, 144, true /* flex */); } |
| public void testGoogVP9SurfQCIF() { specific(googVP9(), 176, 144, false /* flex */); } |
| |
| public void testOtherH265FlexQCIF() { specific(otherH265(), 176, 144, true /* flex */); } |
| public void testOtherH265SurfQCIF() { specific(otherH265(), 176, 144, false /* flex */); } |
| public void testOtherH264FlexQCIF() { specific(otherH264(), 176, 144, true /* flex */); } |
| public void testOtherH264SurfQCIF() { specific(otherH264(), 176, 144, false /* flex */); } |
| public void testOtherH263FlexQCIF() { specific(otherH263(), 176, 144, true /* flex */); } |
| public void testOtherH263SurfQCIF() { specific(otherH263(), 176, 144, false /* flex */); } |
| public void testOtherMpeg4FlexQCIF() { specific(otherMpeg4(), 176, 144, true /* flex */); } |
| public void testOtherMpeg4SurfQCIF() { specific(otherMpeg4(), 176, 144, false /* flex */); } |
| public void testOtherVP8FlexQCIF() { specific(otherVP8(), 176, 144, true /* flex */); } |
| public void testOtherVP8SurfQCIF() { specific(otherVP8(), 176, 144, false /* flex */); } |
| public void testOtherVP9FlexQCIF() { specific(otherVP9(), 176, 144, true /* flex */); } |
| public void testOtherVP9SurfQCIF() { specific(otherVP9(), 176, 144, false /* flex */); } |
| |
| public void testGoogH265Flex480p() { specific(googH265(), 720, 480, true /* flex */); } |
| public void testGoogH265Surf480p() { specific(googH265(), 720, 480, false /* flex */); } |
| public void testGoogH264Flex480p() { specific(googH264(), 720, 480, true /* flex */); } |
| public void testGoogH264Surf480p() { specific(googH264(), 720, 480, false /* flex */); } |
| public void testGoogH263Flex480p() { specific(googH263(), 720, 480, true /* flex */); } |
| public void testGoogH263Surf480p() { specific(googH263(), 720, 480, false /* flex */); } |
| public void testGoogMpeg4Flex480p() { specific(googMpeg4(), 720, 480, true /* flex */); } |
| public void testGoogMpeg4Surf480p() { specific(googMpeg4(), 720, 480, false /* flex */); } |
| public void testGoogVP8Flex480p() { specific(googVP8(), 720, 480, true /* flex */); } |
| public void testGoogVP8Surf480p() { specific(googVP8(), 720, 480, false /* flex */); } |
| public void testGoogVP9Flex480p() { specific(googVP9(), 720, 480, true /* flex */); } |
| public void testGoogVP9Surf480p() { specific(googVP9(), 720, 480, false /* flex */); } |
| |
| public void testOtherH265Flex480p() { specific(otherH265(), 720, 480, true /* flex */); } |
| public void testOtherH265Surf480p() { specific(otherH265(), 720, 480, false /* flex */); } |
| public void testOtherH264Flex480p() { specific(otherH264(), 720, 480, true /* flex */); } |
| public void testOtherH264Surf480p() { specific(otherH264(), 720, 480, false /* flex */); } |
| public void testOtherH263Flex480p() { specific(otherH263(), 720, 480, true /* flex */); } |
| public void testOtherH263Surf480p() { specific(otherH263(), 720, 480, false /* flex */); } |
| public void testOtherMpeg4Flex480p() { specific(otherMpeg4(), 720, 480, true /* flex */); } |
| public void testOtherMpeg4Surf480p() { specific(otherMpeg4(), 720, 480, false /* flex */); } |
| public void testOtherVP8Flex480p() { specific(otherVP8(), 720, 480, true /* flex */); } |
| public void testOtherVP8Surf480p() { specific(otherVP8(), 720, 480, false /* flex */); } |
| public void testOtherVP9Flex480p() { specific(otherVP9(), 720, 480, true /* flex */); } |
| public void testOtherVP9Surf480p() { specific(otherVP9(), 720, 480, false /* flex */); } |
| |
| // even though H.263 and MPEG-4 are not defined for 720p or 1080p |
| // test for it, in case device claims support for it. |
| |
| public void testGoogH265Flex720p() { specific(googH265(), 1280, 720, true /* flex */); } |
| public void testGoogH265Surf720p() { specific(googH265(), 1280, 720, false /* flex */); } |
| public void testGoogH264Flex720p() { specific(googH264(), 1280, 720, true /* flex */); } |
| public void testGoogH264Surf720p() { specific(googH264(), 1280, 720, false /* flex */); } |
| public void testGoogH263Flex720p() { specific(googH263(), 1280, 720, true /* flex */); } |
| public void testGoogH263Surf720p() { specific(googH263(), 1280, 720, false /* flex */); } |
| public void testGoogMpeg4Flex720p() { specific(googMpeg4(), 1280, 720, true /* flex */); } |
| public void testGoogMpeg4Surf720p() { specific(googMpeg4(), 1280, 720, false /* flex */); } |
| public void testGoogVP8Flex720p() { specific(googVP8(), 1280, 720, true /* flex */); } |
| public void testGoogVP8Surf720p() { specific(googVP8(), 1280, 720, false /* flex */); } |
| public void testGoogVP9Flex720p() { specific(googVP9(), 1280, 720, true /* flex */); } |
| public void testGoogVP9Surf720p() { specific(googVP9(), 1280, 720, false /* flex */); } |
| |
| public void testOtherH265Flex720p() { specific(otherH265(), 1280, 720, true /* flex */); } |
| public void testOtherH265Surf720p() { specific(otherH265(), 1280, 720, false /* flex */); } |
| public void testOtherH264Flex720p() { specific(otherH264(), 1280, 720, true /* flex */); } |
| public void testOtherH264Surf720p() { specific(otherH264(), 1280, 720, false /* flex */); } |
| public void testOtherH263Flex720p() { specific(otherH263(), 1280, 720, true /* flex */); } |
| public void testOtherH263Surf720p() { specific(otherH263(), 1280, 720, false /* flex */); } |
| public void testOtherMpeg4Flex720p() { specific(otherMpeg4(), 1280, 720, true /* flex */); } |
| public void testOtherMpeg4Surf720p() { specific(otherMpeg4(), 1280, 720, false /* flex */); } |
| public void testOtherVP8Flex720p() { specific(otherVP8(), 1280, 720, true /* flex */); } |
| public void testOtherVP8Surf720p() { specific(otherVP8(), 1280, 720, false /* flex */); } |
| public void testOtherVP9Flex720p() { specific(otherVP9(), 1280, 720, true /* flex */); } |
| public void testOtherVP9Surf720p() { specific(otherVP9(), 1280, 720, false /* flex */); } |
| |
| public void testGoogH265Flex1080p() { specific(googH265(), 1920, 1080, true /* flex */); } |
| public void testGoogH265Surf1080p() { specific(googH265(), 1920, 1080, false /* flex */); } |
| public void testGoogH264Flex1080p() { specific(googH264(), 1920, 1080, true /* flex */); } |
| public void testGoogH264Surf1080p() { specific(googH264(), 1920, 1080, false /* flex */); } |
| public void testGoogH263Flex1080p() { specific(googH263(), 1920, 1080, true /* flex */); } |
| public void testGoogH263Surf1080p() { specific(googH263(), 1920, 1080, false /* flex */); } |
| public void testGoogMpeg4Flex1080p() { specific(googMpeg4(), 1920, 1080, true /* flex */); } |
| public void testGoogMpeg4Surf1080p() { specific(googMpeg4(), 1920, 1080, false /* flex */); } |
| public void testGoogVP8Flex1080p() { specific(googVP8(), 1920, 1080, true /* flex */); } |
| public void testGoogVP8Surf1080p() { specific(googVP8(), 1920, 1080, false /* flex */); } |
| public void testGoogVP9Flex1080p() { specific(googVP9(), 1920, 1080, true /* flex */); } |
| public void testGoogVP9Surf1080p() { specific(googVP9(), 1920, 1080, false /* flex */); } |
| |
| public void testOtherH265Flex1080p() { specific(otherH265(), 1920, 1080, true /* flex */); } |
| public void testOtherH265Surf1080p() { specific(otherH265(), 1920, 1080, false /* flex */); } |
| public void testOtherH264Flex1080p() { specific(otherH264(), 1920, 1080, true /* flex */); } |
| public void testOtherH264Surf1080p() { specific(otherH264(), 1920, 1080, false /* flex */); } |
| public void testOtherH263Flex1080p() { specific(otherH263(), 1920, 1080, true /* flex */); } |
| public void testOtherH263Surf1080p() { specific(otherH263(), 1920, 1080, false /* flex */); } |
| public void testOtherMpeg4Flex1080p() { specific(otherMpeg4(), 1920, 1080, true /* flex */); } |
| public void testOtherMpeg4Surf1080p() { specific(otherMpeg4(), 1920, 1080, false /* flex */); } |
| public void testOtherVP8Flex1080p() { specific(otherVP8(), 1920, 1080, true /* flex */); } |
| public void testOtherVP8Surf1080p() { specific(otherVP8(), 1920, 1080, false /* flex */); } |
| public void testOtherVP9Flex1080p() { specific(otherVP9(), 1920, 1080, true /* flex */); } |
| public void testOtherVP9Surf1080p() { specific(otherVP9(), 1920, 1080, false /* flex */); } |
| |
| // Tests encoder profiles required by CDD. |
| // H264 |
| public void testH264LowQualitySDSupport() { |
| support(h264(), 320, 240, 20, 384 * 1000); |
| } |
| |
| public void testH264HighQualitySDSupport() { |
| support(h264(), 720, 480, 30, 2 * 1000000); |
| } |
| |
| public void testH264FlexQVGA20fps384kbps() { |
| detailed(h264(), 320, 240, 20, 384 * 1000, true /* flex */); |
| } |
| |
| public void testH264SurfQVGA20fps384kbps() { |
| detailed(h264(), 320, 240, 20, 384 * 1000, false /* flex */); |
| } |
| |
| public void testH264Flex480p30fps2Mbps() { |
| detailed(h264(), 720, 480, 30, 2 * 1000000, true /* flex */); |
| } |
| |
| public void testH264Surf480p30fps2Mbps() { |
| detailed(h264(), 720, 480, 30, 2 * 1000000, false /* flex */); |
| } |
| |
| public void testH264Flex720p30fps4Mbps() { |
| detailed(h264(), 1280, 720, 30, 4 * 1000000, true /* flex */); |
| } |
| |
| public void testH264Surf720p30fps4Mbps() { |
| detailed(h264(), 1280, 720, 30, 4 * 1000000, false /* flex */); |
| } |
| |
| public void testH264Flex1080p30fps10Mbps() { |
| detailed(h264(), 1920, 1080, 30, 10 * 1000000, true /* flex */); |
| } |
| |
| public void testH264Surf1080p30fps10Mbps() { |
| detailed(h264(), 1920, 1080, 30, 10 * 1000000, false /* flex */); |
| } |
| |
| // VP8 |
| public void testVP8LowQualitySDSupport() { |
| support(vp8(), 320, 180, 30, 800 * 1000); |
| } |
| |
| public void testVP8HighQualitySDSupport() { |
| support(vp8(), 640, 360, 30, 2 * 1000000); |
| } |
| |
| public void testVP8Flex180p30fps800kbps() { |
| detailed(vp8(), 320, 180, 30, 800 * 1000, true /* flex */); |
| } |
| |
| public void testVP8Surf180p30fps800kbps() { |
| detailed(vp8(), 320, 180, 30, 800 * 1000, false /* flex */); |
| } |
| |
| public void testVP8Flex360p30fps2Mbps() { |
| detailed(vp8(), 640, 360, 30, 2 * 1000000, true /* flex */); |
| } |
| |
| public void testVP8Surf360p30fps2Mbps() { |
| detailed(vp8(), 640, 360, 30, 2 * 1000000, false /* flex */); |
| } |
| |
| public void testVP8Flex720p30fps4Mbps() { |
| detailed(vp8(), 1280, 720, 30, 4 * 1000000, true /* flex */); |
| } |
| |
| public void testVP8Surf720p30fps4Mbps() { |
| detailed(vp8(), 1280, 720, 30, 4 * 1000000, false /* flex */); |
| } |
| |
| public void testVP8Flex1080p30fps10Mbps() { |
| detailed(vp8(), 1920, 1080, 30, 10 * 1000000, true /* flex */); |
| } |
| |
| public void testVP8Surf1080p30fps10Mbps() { |
| detailed(vp8(), 1920, 1080, 30, 10 * 1000000, false /* flex */); |
| } |
| |
| private void minmin(Encoder[] encoders, boolean flexYUV) { |
| extreme(encoders, 0 /* x */, 0 /* y */, flexYUV, false /* near */); |
| } |
| |
| private void minmax(Encoder[] encoders, boolean flexYUV) { |
| extreme(encoders, 0 /* x */, 1 /* y */, flexYUV, false /* near */); |
| } |
| |
| private void maxmin(Encoder[] encoders, boolean flexYUV) { |
| extreme(encoders, 1 /* x */, 0 /* y */, flexYUV, false /* near */); |
| } |
| |
| private void maxmax(Encoder[] encoders, boolean flexYUV) { |
| extreme(encoders, 1 /* x */, 1 /* y */, flexYUV, false /* near */); |
| } |
| |
| private void nearminmin(Encoder[] encoders, boolean flexYUV) { |
| extreme(encoders, 0 /* x */, 0 /* y */, flexYUV, true /* near */); |
| } |
| |
| private void nearminmax(Encoder[] encoders, boolean flexYUV) { |
| extreme(encoders, 0 /* x */, 1 /* y */, flexYUV, true /* near */); |
| } |
| |
| private void nearmaxmin(Encoder[] encoders, boolean flexYUV) { |
| extreme(encoders, 1 /* x */, 0 /* y */, flexYUV, true /* near */); |
| } |
| |
| private void nearmaxmax(Encoder[] encoders, boolean flexYUV) { |
| extreme(encoders, 1 /* x */, 1 /* y */, flexYUV, true /* near */); |
| } |
| |
| private void extreme(Encoder[] encoders, int x, int y, boolean flexYUV, boolean near) { |
| boolean skipped = true; |
| if (encoders.length == 0) { |
| MediaUtils.skipTest("no such encoder present"); |
| return; |
| } |
| for (Encoder encoder: encoders) { |
| if (encoder.testExtreme(x, y, flexYUV, near)) { |
| skipped = false; |
| } |
| } |
| if (skipped) { |
| MediaUtils.skipTest("duplicate resolution extreme"); |
| } |
| } |
| |
| private void arbitrary(Encoder[] encoders, boolean flexYUV) { |
| boolean skipped = true; |
| if (encoders.length == 0) { |
| MediaUtils.skipTest("no such encoder present"); |
| return; |
| } |
| for (Encoder encoder: encoders) { |
| if (encoder.testArbitrary(flexYUV)) { |
| skipped = false; |
| } |
| } |
| if (skipped) { |
| MediaUtils.skipTest("duplicate resolution"); |
| } |
| } |
| |
| /* test specific size */ |
| private void specific(Encoder[] encoders, int width, int height, boolean flexYUV) { |
| boolean skipped = true; |
| if (encoders.length == 0) { |
| MediaUtils.skipTest("no such encoder present"); |
| return; |
| } |
| for (Encoder encoder : encoders) { |
| if (encoder.testSpecific(width, height, flexYUV)) { |
| skipped = false; |
| } |
| } |
| if (skipped) { |
| MediaUtils.skipTest("duplicate or unsupported resolution"); |
| } |
| } |
| |
| /* test size, frame rate and bit rate */ |
| private void detailed( |
| Encoder[] encoders, int width, int height, int frameRate, int bitRate, |
| boolean flexYUV) { |
| if (encoders.length == 0) { |
| MediaUtils.skipTest("no such encoder present"); |
| return; |
| } |
| boolean skipped = true; |
| for (Encoder encoder : encoders) { |
| if (encoder.testSupport(width, height, frameRate, bitRate)) { |
| skipped = false; |
| encoder.testDetailed(width, height, frameRate, bitRate, flexYUV); |
| } |
| } |
| if (skipped) { |
| MediaUtils.skipTest("unsupported resolution and rate"); |
| } |
| } |
| |
| /* test size and rate are supported */ |
| private void support(Encoder[] encoders, int width, int height, int frameRate, int bitRate) { |
| boolean supported = false; |
| if (encoders.length == 0) { |
| MediaUtils.skipTest("no such encoder present"); |
| return; |
| } |
| for (Encoder encoder : encoders) { |
| if (encoder.testSupport(width, height, frameRate, bitRate)) { |
| supported = true; |
| break; |
| } |
| } |
| if (!supported) { |
| fail("unsupported format " + width + "x" + height + " " + |
| frameRate + "fps " + bitRate + "bps"); |
| } |
| } |
| } |