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