18f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown/* 28f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * Copyright (C) 2013 The Android Open Source Project 38f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * 48f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 58f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * you may not use this file except in compliance with the License. 68f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * You may obtain a copy of the License at 78f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * 88f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 98f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * 108f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * Unless required by applicable law or agreed to in writing, software 118f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 128f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * See the License for the specific language governing permissions and 148f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * limitations under the License. 158f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown */ 168f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 178f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownpackage com.android.accessorydisplay.sink; 188f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 198f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport com.android.accessorydisplay.common.Protocol; 208f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport com.android.accessorydisplay.common.Service; 218f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport com.android.accessorydisplay.common.Transport; 228f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 238f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.content.Context; 248f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.graphics.Rect; 258f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.media.MediaCodec; 268f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.media.MediaCodec.BufferInfo; 278f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.media.MediaFormat; 288f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.os.Handler; 298f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.view.Surface; 308f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.view.SurfaceHolder; 318f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.view.SurfaceView; 328f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 3383511d2f49c9e272f328730586c3d0a7852247f2Andy Hungimport java.io.IOException; 348f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport java.nio.ByteBuffer; 358f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 368f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownpublic class DisplaySinkService extends Service implements SurfaceHolder.Callback { 378f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private final ByteBuffer mBuffer = ByteBuffer.allocate(12); 388f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private final Handler mTransportHandler; 398f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private final int mDensityDpi; 408f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 418f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private SurfaceView mSurfaceView; 428f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 438f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown // These fields are guarded by the following lock. 448f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown // This is to ensure that the surface lifecycle is respected. Although decoding 458f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown // happens on the transport thread, we are not allowed to access the surface after 468f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown // it is destroyed by the UI thread so we need to stop the codec immediately. 478f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private final Object mSurfaceAndCodecLock = new Object(); 488f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private Surface mSurface; 498f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private int mSurfaceWidth; 508f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private int mSurfaceHeight; 518f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private MediaCodec mCodec; 528f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private ByteBuffer[] mCodecInputBuffers; 538f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private BufferInfo mCodecBufferInfo; 548f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 558f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public DisplaySinkService(Context context, Transport transport, int densityDpi) { 568f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown super(context, transport, Protocol.DisplaySinkService.ID); 578f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mTransportHandler = transport.getHandler(); 588f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mDensityDpi = densityDpi; 598f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 608f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 618f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public void setSurfaceView(final SurfaceView surfaceView) { 628f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (mSurfaceView != surfaceView) { 638f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown final SurfaceView oldSurfaceView = mSurfaceView; 648f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mSurfaceView = surfaceView; 658f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 668f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (oldSurfaceView != null) { 678f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown oldSurfaceView.post(new Runnable() { 688f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown @Override 698f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public void run() { 708f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown final SurfaceHolder holder = oldSurfaceView.getHolder(); 718f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown holder.removeCallback(DisplaySinkService.this); 728f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown updateSurfaceFromUi(null); 738f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 748f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown }); 758f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 768f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 778f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (surfaceView != null) { 788f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown surfaceView.post(new Runnable() { 798f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown @Override 808f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public void run() { 818f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown final SurfaceHolder holder = surfaceView.getHolder(); 828f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown holder.addCallback(DisplaySinkService.this); 838f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown updateSurfaceFromUi(holder); 848f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 858f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown }); 868f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 878f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 888f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 898f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 908f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown @Override 918f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public void onMessageReceived(int service, int what, ByteBuffer content) { 928f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown switch (what) { 938f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown case Protocol.DisplaySinkService.MSG_QUERY: { 948f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown getLogger().log("Received MSG_QUERY."); 958f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown sendSinkStatus(); 968f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown break; 978f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 988f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 998f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown case Protocol.DisplaySinkService.MSG_CONTENT: { 1008f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown decode(content); 1018f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown break; 1028f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1038f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1048f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1058f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1068f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown @Override 1078f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public void surfaceCreated(SurfaceHolder holder) { 1088f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown // Ignore. Wait for surface changed event that follows. 1098f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1108f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1118f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown @Override 1128f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 1138f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown updateSurfaceFromUi(holder); 1148f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1158f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1168f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown @Override 1178f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public void surfaceDestroyed(SurfaceHolder holder) { 1188f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown updateSurfaceFromUi(null); 1198f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1208f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1218f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private void updateSurfaceFromUi(SurfaceHolder holder) { 1228f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown Surface surface = null; 1238f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown int width = 0, height = 0; 1248f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (holder != null && !holder.isCreating()) { 1258f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown surface = holder.getSurface(); 1268f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (surface.isValid()) { 1278f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown final Rect frame = holder.getSurfaceFrame(); 1288f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown width = frame.width(); 1298f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown height = frame.height(); 1308f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } else { 1318f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown surface = null; 1328f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1338f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1348f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1358f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown synchronized (mSurfaceAndCodecLock) { 1368f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (mSurface == surface && mSurfaceWidth == width && mSurfaceHeight == height) { 1378f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown return; 1388f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1398f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1408f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mSurface = surface; 1418f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mSurfaceWidth = width; 1428f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mSurfaceHeight = height; 1438f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1448f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (mCodec != null) { 1458f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodec.stop(); 1468f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodec = null; 1478f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodecInputBuffers = null; 1488f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodecBufferInfo = null; 1498f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1508f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1518f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (mSurface != null) { 1528f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown MediaFormat format = MediaFormat.createVideoFormat( 1538f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown "video/avc", mSurfaceWidth, mSurfaceHeight); 15483511d2f49c9e272f328730586c3d0a7852247f2Andy Hung try { 15583511d2f49c9e272f328730586c3d0a7852247f2Andy Hung mCodec = MediaCodec.createDecoderByType("video/avc"); 15683511d2f49c9e272f328730586c3d0a7852247f2Andy Hung } catch (IOException e) { 15783511d2f49c9e272f328730586c3d0a7852247f2Andy Hung throw new RuntimeException( 15883511d2f49c9e272f328730586c3d0a7852247f2Andy Hung "failed to create video/avc decoder", e); 15983511d2f49c9e272f328730586c3d0a7852247f2Andy Hung } 1608f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodec.configure(format, mSurface, null, 0); 1618f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodec.start(); 1628f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodecBufferInfo = new BufferInfo(); 1638f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1648f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1658f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mTransportHandler.post(new Runnable() { 1668f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown @Override 1678f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public void run() { 1688f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown sendSinkStatus(); 1698f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1708f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown }); 1718f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1728f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1738f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1748f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private void decode(ByteBuffer content) { 1758f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (content == null) { 1768f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown return; 1778f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1788f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown synchronized (mSurfaceAndCodecLock) { 1798f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (mCodec == null) { 1808f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown return; 1818f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1828f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1838f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown while (content.hasRemaining()) { 1848f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (!provideCodecInputLocked(content)) { 1858f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown getLogger().log("Dropping content because there are no available buffers."); 1868f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown return; 1878f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1888f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1898f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown consumeCodecOutputLocked(); 1908f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1918f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1928f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1938f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1948f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private boolean provideCodecInputLocked(ByteBuffer content) { 1958f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown final int index = mCodec.dequeueInputBuffer(0); 1968f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (index < 0) { 1978f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown return false; 1988f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1998f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (mCodecInputBuffers == null) { 2008f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodecInputBuffers = mCodec.getInputBuffers(); 2018f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 2028f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown final ByteBuffer buffer = mCodecInputBuffers[index]; 2038f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown final int capacity = buffer.capacity(); 2048f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown buffer.clear(); 2058f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (content.remaining() <= capacity) { 2068f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown buffer.put(content); 2078f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } else { 2088f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown final int limit = content.limit(); 2098f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown content.limit(content.position() + capacity); 2108f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown buffer.put(content); 2118f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown content.limit(limit); 2128f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 2138f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown buffer.flip(); 2148f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodec.queueInputBuffer(index, 0, buffer.limit(), 0, 0); 2158f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown return true; 2168f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 2178f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 2188f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private void consumeCodecOutputLocked() { 2198f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown for (;;) { 2208f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown final int index = mCodec.dequeueOutputBuffer(mCodecBufferInfo, 0); 2218f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (index >= 0) { 2228f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodec.releaseOutputBuffer(index, true /*render*/); 2238f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } else if (index != MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED 2248f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown && index != MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { 2258f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown break; 2268f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 2278f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 2288f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 2298f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 2308f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private void sendSinkStatus() { 2318f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown synchronized (mSurfaceAndCodecLock) { 2328f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (mCodec != null) { 2338f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mBuffer.clear(); 2348f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mBuffer.putInt(mSurfaceWidth); 2358f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mBuffer.putInt(mSurfaceHeight); 2368f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mBuffer.putInt(mDensityDpi); 2378f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mBuffer.flip(); 2388f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown getTransport().sendMessage(Protocol.DisplaySourceService.ID, 2398f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown Protocol.DisplaySourceService.MSG_SINK_AVAILABLE, mBuffer); 2408f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } else { 2418f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown getTransport().sendMessage(Protocol.DisplaySourceService.ID, 2428f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown Protocol.DisplaySourceService.MSG_SINK_NOT_AVAILABLE, null); 2438f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 2448f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 2458f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 2468f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown} 247