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