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 338f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport java.nio.ByteBuffer; 348f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 358f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownpublic class DisplaySinkService extends Service implements SurfaceHolder.Callback { 368f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private final ByteBuffer mBuffer = ByteBuffer.allocate(12); 378f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private final Handler mTransportHandler; 388f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private final int mDensityDpi; 398f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 408f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private SurfaceView mSurfaceView; 418f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 428f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown // These fields are guarded by the following lock. 438f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown // This is to ensure that the surface lifecycle is respected. Although decoding 448f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown // happens on the transport thread, we are not allowed to access the surface after 458f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown // it is destroyed by the UI thread so we need to stop the codec immediately. 468f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private final Object mSurfaceAndCodecLock = new Object(); 478f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private Surface mSurface; 488f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private int mSurfaceWidth; 498f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private int mSurfaceHeight; 508f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private MediaCodec mCodec; 518f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private ByteBuffer[] mCodecInputBuffers; 528f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private BufferInfo mCodecBufferInfo; 538f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 548f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public DisplaySinkService(Context context, Transport transport, int densityDpi) { 558f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown super(context, transport, Protocol.DisplaySinkService.ID); 568f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mTransportHandler = transport.getHandler(); 578f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mDensityDpi = densityDpi; 588f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 598f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 608f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public void setSurfaceView(final SurfaceView surfaceView) { 618f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (mSurfaceView != surfaceView) { 628f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown final SurfaceView oldSurfaceView = mSurfaceView; 638f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mSurfaceView = surfaceView; 648f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 658f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (oldSurfaceView != null) { 668f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown oldSurfaceView.post(new Runnable() { 678f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown @Override 688f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public void run() { 698f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown final SurfaceHolder holder = oldSurfaceView.getHolder(); 708f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown holder.removeCallback(DisplaySinkService.this); 718f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown updateSurfaceFromUi(null); 728f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 738f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown }); 748f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 758f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 768f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (surfaceView != null) { 778f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown surfaceView.post(new Runnable() { 788f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown @Override 798f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public void run() { 808f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown final SurfaceHolder holder = surfaceView.getHolder(); 818f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown holder.addCallback(DisplaySinkService.this); 828f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown updateSurfaceFromUi(holder); 838f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 848f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown }); 858f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 868f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 878f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 888f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 898f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown @Override 908f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public void onMessageReceived(int service, int what, ByteBuffer content) { 918f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown switch (what) { 928f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown case Protocol.DisplaySinkService.MSG_QUERY: { 938f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown getLogger().log("Received MSG_QUERY."); 948f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown sendSinkStatus(); 958f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown break; 968f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 978f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 988f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown case Protocol.DisplaySinkService.MSG_CONTENT: { 998f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown decode(content); 1008f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown break; 1018f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1028f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1038f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1048f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1058f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown @Override 1068f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public void surfaceCreated(SurfaceHolder holder) { 1078f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown // Ignore. Wait for surface changed event that follows. 1088f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1098f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1108f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown @Override 1118f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 1128f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown updateSurfaceFromUi(holder); 1138f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1148f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1158f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown @Override 1168f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public void surfaceDestroyed(SurfaceHolder holder) { 1178f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown updateSurfaceFromUi(null); 1188f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1198f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1208f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private void updateSurfaceFromUi(SurfaceHolder holder) { 1218f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown Surface surface = null; 1228f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown int width = 0, height = 0; 1238f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (holder != null && !holder.isCreating()) { 1248f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown surface = holder.getSurface(); 1258f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (surface.isValid()) { 1268f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown final Rect frame = holder.getSurfaceFrame(); 1278f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown width = frame.width(); 1288f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown height = frame.height(); 1298f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } else { 1308f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown surface = null; 1318f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1328f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1338f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1348f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown synchronized (mSurfaceAndCodecLock) { 1358f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (mSurface == surface && mSurfaceWidth == width && mSurfaceHeight == height) { 1368f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown return; 1378f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1388f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1398f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mSurface = surface; 1408f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mSurfaceWidth = width; 1418f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mSurfaceHeight = height; 1428f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1438f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (mCodec != null) { 1448f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodec.stop(); 1458f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodec = null; 1468f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodecInputBuffers = null; 1478f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodecBufferInfo = null; 1488f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1498f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1508f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (mSurface != null) { 1518f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown MediaFormat format = MediaFormat.createVideoFormat( 1528f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown "video/avc", mSurfaceWidth, mSurfaceHeight); 1538f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodec = MediaCodec.createDecoderByType("video/avc"); 1548f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodec.configure(format, mSurface, null, 0); 1558f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodec.start(); 1568f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodecBufferInfo = new BufferInfo(); 1578f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1588f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1598f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mTransportHandler.post(new Runnable() { 1608f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown @Override 1618f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown public void run() { 1628f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown sendSinkStatus(); 1638f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1648f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown }); 1658f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1668f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1678f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1688f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private void decode(ByteBuffer content) { 1698f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (content == null) { 1708f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown return; 1718f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1728f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown synchronized (mSurfaceAndCodecLock) { 1738f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (mCodec == null) { 1748f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown return; 1758f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1768f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1778f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown while (content.hasRemaining()) { 1788f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (!provideCodecInputLocked(content)) { 1798f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown getLogger().log("Dropping content because there are no available buffers."); 1808f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown return; 1818f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1828f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1838f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown consumeCodecOutputLocked(); 1848f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1858f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1868f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1878f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 1888f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private boolean provideCodecInputLocked(ByteBuffer content) { 1898f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown final int index = mCodec.dequeueInputBuffer(0); 1908f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (index < 0) { 1918f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown return false; 1928f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1938f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (mCodecInputBuffers == null) { 1948f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodecInputBuffers = mCodec.getInputBuffers(); 1958f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 1968f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown final ByteBuffer buffer = mCodecInputBuffers[index]; 1978f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown final int capacity = buffer.capacity(); 1988f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown buffer.clear(); 1998f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (content.remaining() <= capacity) { 2008f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown buffer.put(content); 2018f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } else { 2028f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown final int limit = content.limit(); 2038f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown content.limit(content.position() + capacity); 2048f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown buffer.put(content); 2058f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown content.limit(limit); 2068f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 2078f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown buffer.flip(); 2088f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodec.queueInputBuffer(index, 0, buffer.limit(), 0, 0); 2098f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown return true; 2108f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 2118f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 2128f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private void consumeCodecOutputLocked() { 2138f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown for (;;) { 2148f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown final int index = mCodec.dequeueOutputBuffer(mCodecBufferInfo, 0); 2158f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (index >= 0) { 2168f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mCodec.releaseOutputBuffer(index, true /*render*/); 2178f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } else if (index != MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED 2188f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown && index != MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { 2198f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown break; 2208f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 2218f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 2228f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 2238f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown 2248f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown private void sendSinkStatus() { 2258f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown synchronized (mSurfaceAndCodecLock) { 2268f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown if (mCodec != null) { 2278f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mBuffer.clear(); 2288f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mBuffer.putInt(mSurfaceWidth); 2298f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mBuffer.putInt(mSurfaceHeight); 2308f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mBuffer.putInt(mDensityDpi); 2318f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown mBuffer.flip(); 2328f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown getTransport().sendMessage(Protocol.DisplaySourceService.ID, 2338f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown Protocol.DisplaySourceService.MSG_SINK_AVAILABLE, mBuffer); 2348f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } else { 2358f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown getTransport().sendMessage(Protocol.DisplaySourceService.ID, 2368f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown Protocol.DisplaySourceService.MSG_SINK_NOT_AVAILABLE, null); 2378f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 2388f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 2398f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown } 2408f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown} 241