PlaybackSession.cpp revision 0b73d4730202fcad53aefc4314a06e7b95f442f0
1d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber/*
2d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber * Copyright 2012, The Android Open Source Project
3d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber *
4d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber * you may not use this file except in compliance with the License.
6d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber * You may obtain a copy of the License at
7d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber *
8d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber *     http://www.apache.org/licenses/LICENSE-2.0
9d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber *
10d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber * Unless required by applicable law or agreed to in writing, software
11d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber * See the License for the specific language governing permissions and
14d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber * limitations under the License.
15d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber */
16d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
17d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber//#define LOG_NDEBUG 0
18d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#define LOG_TAG "PlaybackSession"
19d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <utils/Log.h>
20d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
21d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include "PlaybackSession.h"
22d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
23d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include "Converter.h"
24d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include "RepeaterSource.h"
25d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include "Serializer.h"
26d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include "TSPacketizer.h"
27d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
28d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <binder/IServiceManager.h>
29d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <gui/ISurfaceComposer.h>
30d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <gui/SurfaceComposerClient.h>
31d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/foundation/ABuffer.h>
32d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/foundation/ADebug.h>
33d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/foundation/AMessage.h>
34d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/foundation/hexdump.h>
35082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber#include <media/stagefright/AudioSource.h>
36d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/DataSource.h>
37d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MediaDefs.h>
38d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MediaErrors.h>
39d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MediaExtractor.h>
40d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MediaSource.h>
41d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MetaData.h>
42d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MPEG2TSWriter.h>
43d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/SurfaceMediaSource.h>
44d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/Utils.h>
45d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <ui/DisplayInfo.h>
46d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
47d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <OMX_IVCommon.h>
48d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
49d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#define FAKE_VIDEO      0
50d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
51d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubernamespace android {
52d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
53d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatic size_t kMaxRTPPacketSize = 1500;
54d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatic size_t kMaxNumTSPacketsPerRTPPacket = (kMaxRTPPacketSize - 12) / 188;
55d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
56d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstruct WifiDisplaySource::PlaybackSession::Track : public RefBase {
57d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    Track(const sp<Converter> &converter);
58d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    Track(const sp<AMessage> &format);
59d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
60d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> getFormat();
61d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
62d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    const sp<Converter> &converter() const;
63d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    ssize_t packetizerTrackIndex() const;
64d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
65d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    void setPacketizerTrackIndex(size_t index);
66d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
67d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberprotected:
68d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    virtual ~Track();
69d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
70d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberprivate:
71d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<Converter> mConverter;
72d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> mFormat;
73d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    ssize_t mPacketizerTrackIndex;
74d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
75d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    DISALLOW_EVIL_CONSTRUCTORS(Track);
76d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber};
77d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
78d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas HuberWifiDisplaySource::PlaybackSession::Track::Track(const sp<Converter> &converter)
79d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    : mConverter(converter),
80d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mPacketizerTrackIndex(-1) {
81d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
82d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
83d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas HuberWifiDisplaySource::PlaybackSession::Track::Track(const sp<AMessage> &format)
84d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    : mFormat(format),
85d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mPacketizerTrackIndex(-1) {
86d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
87d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
88d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas HuberWifiDisplaySource::PlaybackSession::Track::~Track() {
89d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
90d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
91d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubersp<AMessage> WifiDisplaySource::PlaybackSession::Track::getFormat() {
92d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mFormat != NULL) {
93d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return mFormat;
94d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
95d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
96d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mConverter->getOutputFormat();
97d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
98d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
99d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberconst sp<Converter> &WifiDisplaySource::PlaybackSession::Track::converter() const {
100d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mConverter;
101d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
102d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
103d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberssize_t WifiDisplaySource::PlaybackSession::Track::packetizerTrackIndex() const {
104d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mPacketizerTrackIndex;
105d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
106d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
107d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::Track::setPacketizerTrackIndex(size_t index) {
108d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK_LT(mPacketizerTrackIndex, 0);
109d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mPacketizerTrackIndex = index;
110d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
111d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
112d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber////////////////////////////////////////////////////////////////////////////////
113d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
114d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas HuberWifiDisplaySource::PlaybackSession::PlaybackSession(
115d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const sp<ANetworkSession> &netSession,
1160b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber        const sp<AMessage> &notify,
1170b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber        bool legacyMode)
118d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    : mNetSession(netSession),
119d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mNotify(notify),
1200b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber      mLegacyMode(legacyMode),
121d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mLastLifesignUs(),
122d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mTSQueue(new ABuffer(12 + kMaxNumTSPacketsPerRTPPacket * 188)),
123d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mPrevTimeUs(-1ll),
124d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mUseInterleavedTCP(false),
125d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTPChannel(0),
126d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTCPChannel(0),
127d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTPPort(0),
128d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTPSessionID(0),
129d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTCPSessionID(0),
130d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTPSeqNo(0),
131d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mLastNTPTime(0),
132d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mLastRTPTime(0),
133d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mNumRTPSent(0),
134d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mNumRTPOctetsSent(0),
135d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mNumSRsSent(0),
136d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mSendSRPending(false),
137d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mFirstPacketTimeUs(-1ll),
138774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber      mHistoryLength(0)
139774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#if LOG_TRANSPORT_STREAM
140774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber      ,mLogFile(NULL)
141774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#endif
142774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber{
143d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mTSQueue->setRange(0, 12);
144774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber
145774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#if LOG_TRANSPORT_STREAM
146774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber    mLogFile = fopen("/system/etc/log.ts", "wb");
147774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#endif
148d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
149d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
150d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::init(
151d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const char *clientIP, int32_t clientRtp, int32_t clientRtcp,
152d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        bool useInterleavedTCP) {
153d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    status_t err = setupPacketizer();
154d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
155d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (err != OK) {
156d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return err;
157d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
158d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
159d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (useInterleavedTCP) {
160d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mUseInterleavedTCP = true;
161d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTPChannel = clientRtp;
162d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTCPChannel = clientRtcp;
163d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTPPort = 0;
164d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTPSessionID = 0;
165d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTCPSessionID = 0;
166d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
167d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        updateLiveness();
168d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return OK;
169d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
170d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
171d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mUseInterleavedTCP = false;
172d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mRTPChannel = 0;
173d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mRTCPChannel = 0;
174d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
175d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    int serverRtp;
176d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
177d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> rtpNotify = new AMessage(kWhatRTPNotify, id());
178d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> rtcpNotify = new AMessage(kWhatRTCPNotify, id());
179d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    for (serverRtp = 15550;; serverRtp += 2) {
180d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        int32_t rtpSession;
181d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        err = mNetSession->createUDPSession(
182d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    serverRtp, clientIP, clientRtp,
183d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    rtpNotify, &rtpSession);
184d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
185d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (err != OK) {
186d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            ALOGI("failed to create RTP socket on port %d", serverRtp);
187d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            continue;
188d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
189d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
190d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (clientRtcp < 0) {
191d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            // No RTCP.
192d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
193d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mRTPPort = serverRtp;
194d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mRTPSessionID = rtpSession;
195d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mRTCPSessionID = 0;
196d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
197d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            ALOGI("rtpSessionId = %d", rtpSession);
198d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
199d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
200d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
201d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        int32_t rtcpSession;
202d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        err = mNetSession->createUDPSession(
203d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                serverRtp + 1, clientIP, clientRtcp,
204d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                rtcpNotify, &rtcpSession);
205d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
206d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (err == OK) {
207d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mRTPPort = serverRtp;
208d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mRTPSessionID = rtpSession;
209d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mRTCPSessionID = rtcpSession;
210d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
211d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            ALOGI("rtpSessionID = %d, rtcpSessionID = %d", rtpSession, rtcpSession);
212d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
213d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
214d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
215d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        ALOGI("failed to create RTCP socket on port %d", serverRtp + 1);
216d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mNetSession->destroySession(rtpSession);
217d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
218d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
219d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mRTPPort == 0) {
220d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return UNKNOWN_ERROR;
221d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
222d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
223d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    updateLiveness();
224d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
225d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
226d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
227d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
228d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas HuberWifiDisplaySource::PlaybackSession::~PlaybackSession() {
229774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#if LOG_TRANSPORT_STREAM
230774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber    if (mLogFile != NULL) {
231774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber        fclose(mLogFile);
232774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber        mLogFile = NULL;
233774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber    }
234774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#endif
235774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber
236d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mTracks.clear();
237d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
238d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mCodecLooper != NULL) {
239d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mCodecLooper->stop();
240d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mCodecLooper.clear();
241d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
242d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
243d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mPacketizer.clear();
244d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
245d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mSerializer != NULL) {
246d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mSerializer->stop();
247d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
248d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        looper()->unregisterHandler(mSerializer->id());
249d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mSerializer.clear();
250d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
251d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
252d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mSerializerLooper != NULL) {
253d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mSerializerLooper->stop();
254d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mSerializerLooper.clear();
255d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
256d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
2570b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber    if (mLegacyMode) {
2580b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber        sp<IServiceManager> sm = defaultServiceManager();
2590b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber        sp<IBinder> binder = sm->getService(String16("SurfaceFlinger"));
2600b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber        sp<ISurfaceComposer> service = interface_cast<ISurfaceComposer>(binder);
2610b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber        CHECK(service != NULL);
2620b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber
2630b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber        service->connectDisplay(NULL);
2640b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber    }
2652dff0f6a7bf06a878ad0890d93dc9c1ef0b5a107Andreas Huber
266d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mRTCPSessionID != 0) {
267d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mNetSession->destroySession(mRTCPSessionID);
268d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
269d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
270d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mRTPSessionID != 0) {
271d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mNetSession->destroySession(mRTPSessionID);
272d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
273d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
274d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
275d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberint32_t WifiDisplaySource::PlaybackSession::getRTPPort() const {
276d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mRTPPort;
277d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
278d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
279d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberint64_t WifiDisplaySource::PlaybackSession::getLastLifesignUs() const {
280d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mLastLifesignUs;
281d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
282d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
283d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::updateLiveness() {
284d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mLastLifesignUs = ALooper::GetNowUs();
285d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
286d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
287d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::play() {
288d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    updateLiveness();
289d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
290d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mRTCPSessionID != 0) {
291d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        scheduleSendSR();
292d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
293d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
294d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mSerializer->start();
295d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
296d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
297d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::pause() {
298d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    updateLiveness();
299d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
300d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
301d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
302d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
303d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::onMessageReceived(
304d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const sp<AMessage> &msg) {
305d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    switch (msg->what()) {
306d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        case kWhatRTPNotify:
307d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        case kWhatRTCPNotify:
308d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        {
309d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            int32_t reason;
310d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            CHECK(msg->findInt32("reason", &reason));
311d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
312d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            switch (reason) {
313d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                case ANetworkSession::kWhatError:
314d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                {
315d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    int32_t sessionID;
316d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findInt32("sessionID", &sessionID));
317d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
318d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    int32_t err;
319d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findInt32("err", &err));
320d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
321d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    int32_t errorOccuredDuringSend;
322d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findInt32("send", &errorOccuredDuringSend));
323d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
324d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    AString detail;
325d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findString("detail", &detail));
326d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
327d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    if (msg->what() == kWhatRTPNotify
328d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                            && !errorOccuredDuringSend) {
329d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        // This is ok, we don't expect to receive anything on
330d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        // the RTP socket.
331d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        break;
332d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
333d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
334d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    ALOGE("An error occurred during %s in session %d "
335d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          "(%d, '%s' (%s)).",
336d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          errorOccuredDuringSend ? "send" : "receive",
337d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          sessionID,
338d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          err,
339d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          detail.c_str(),
340d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          strerror(-err));
341d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
342d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    mNetSession->destroySession(sessionID);
343d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
344d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    if (sessionID == mRTPSessionID) {
345d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        mRTPSessionID = 0;
346d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    } else if (sessionID == mRTCPSessionID) {
347d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        mRTCPSessionID = 0;
348d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
349d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
350d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    // Inform WifiDisplaySource of our premature death (wish).
351d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    sp<AMessage> notify = mNotify->dup();
352d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    notify->setInt32("what", kWhatSessionDead);
353d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    notify->post();
354d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    break;
355d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
356d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
357d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                case ANetworkSession::kWhatDatagram:
358d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                {
359d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    int32_t sessionID;
360d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findInt32("sessionID", &sessionID));
361d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
362d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    sp<ABuffer> data;
363d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findBuffer("data", &data));
364d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
365d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    status_t err;
366d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    if (msg->what() == kWhatRTCPNotify) {
367d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        err = parseRTCP(data);
368d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
369d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    break;
370d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
371d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
372d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                default:
373d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    TRESPASS();
374d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
375d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
376d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
377d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
378d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        case kWhatSendSR:
379d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        {
380d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mSendSRPending = false;
381d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
382d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            if (mRTCPSessionID == 0) {
383d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
384d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
385d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
386d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            onSendSR();
387d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
388d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            scheduleSendSR();
389d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
390d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
391d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
392d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        case kWhatSerializerNotify:
393d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        {
394d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            int32_t what;
395d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            CHECK(msg->findInt32("what", &what));
396d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
397d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            if (what == Serializer::kWhatEOS) {
398d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ALOGI("input eos");
399d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
400d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                for (size_t i = 0; i < mTracks.size(); ++i) {
401d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#if FAKE_VIDEO
402d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    sp<AMessage> msg = new AMessage(kWhatConverterNotify, id());
403d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    msg->setInt32("what", Converter::kWhatEOS);
404d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    msg->setSize("trackIndex", i);
405d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    msg->post();
406d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#else
407d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    mTracks.valueAt(i)->converter()->signalEOS();
408d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#endif
409d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
410d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            } else {
411d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK_EQ(what, Serializer::kWhatAccessUnit);
412d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
413d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                size_t trackIndex;
414d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK(msg->findSize("trackIndex", &trackIndex));
415d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
416d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                sp<ABuffer> accessUnit;
417d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK(msg->findBuffer("accessUnit", &accessUnit));
418d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
419d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#if FAKE_VIDEO
420d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                int64_t timeUs;
421d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
422d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
423d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                void *mbuf;
424d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK(accessUnit->meta()->findPointer("mediaBuffer", &mbuf));
425d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
426d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ((MediaBuffer *)mbuf)->release();
427d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                mbuf = NULL;
428d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
429d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                sp<AMessage> msg = new AMessage(kWhatConverterNotify, id());
430d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                msg->setInt32("what", Converter::kWhatAccessUnit);
431d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                msg->setSize("trackIndex", trackIndex);
432d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                msg->setBuffer("accessUnit", accessUnit);
433d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                msg->post();
434d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#else
435d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                mTracks.valueFor(trackIndex)->converter()
436d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    ->feedAccessUnit(accessUnit);
437d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#endif
438d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
439d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
440d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
441d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
442d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        case kWhatConverterNotify:
443d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        {
444d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            int32_t what;
445d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            CHECK(msg->findInt32("what", &what));
446d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
447d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            size_t trackIndex;
448d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            CHECK(msg->findSize("trackIndex", &trackIndex));
449d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
450d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            if (what == Converter::kWhatAccessUnit) {
451d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                const sp<Track> &track = mTracks.valueFor(trackIndex);
452d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
453d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                uint32_t flags = 0;
454d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
455d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ssize_t packetizerTrackIndex = track->packetizerTrackIndex();
456d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                if (packetizerTrackIndex < 0) {
457d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    flags = TSPacketizer::EMIT_PAT_AND_PMT;
458d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
459d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    packetizerTrackIndex =
460d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        mPacketizer->addTrack(track->getFormat());
461d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
462d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    if (packetizerTrackIndex >= 0) {
463d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        track->setPacketizerTrackIndex(packetizerTrackIndex);
464d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
465d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
466d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
467d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                if (packetizerTrackIndex >= 0) {
468d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    sp<ABuffer> accessUnit;
469d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findBuffer("accessUnit", &accessUnit));
470d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
471d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    int64_t timeUs;
472d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
473d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
474d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    if (mPrevTimeUs < 0ll || mPrevTimeUs + 100000ll >= timeUs) {
475d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        flags |= TSPacketizer::EMIT_PCR;
476d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        mPrevTimeUs = timeUs;
477d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
478d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
479d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    sp<ABuffer> packets;
480d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    mPacketizer->packetize(
481d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                            packetizerTrackIndex, accessUnit, &packets, flags);
482d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
483d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    for (size_t offset = 0;
484d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                            offset < packets->size(); offset += 188) {
485d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        bool lastTSPacket = (offset + 188 >= packets->size());
486d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
487d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        appendTSData(
488d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                                packets->data() + offset,
489d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                                188,
490d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                                true /* timeDiscontinuity */,
491d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                                lastTSPacket /* flush */);
492d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
493774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber
494774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#if LOG_TRANSPORT_STREAM
495774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber                    if (mLogFile != NULL) {
496774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber                        fwrite(packets->data(), 1, packets->size(), mLogFile);
497774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber                    }
498774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#endif
499d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
500d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            } else if (what == Converter::kWhatEOS) {
501d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK_EQ(what, Converter::kWhatEOS);
502d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
503d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ALOGI("output EOS on track %d", trackIndex);
504d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
505d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ssize_t index = mTracks.indexOfKey(trackIndex);
506d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK_GE(index, 0);
507d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
508d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#if !FAKE_VIDEO
509d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                const sp<Converter> &converter =
510d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    mTracks.valueAt(index)->converter();
511d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                looper()->unregisterHandler(converter->id());
512d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#endif
513d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
514d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                mTracks.removeItemsAt(index);
515d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
516d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                if (mTracks.isEmpty()) {
517d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    ALOGI("Reached EOS");
518d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
519d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            } else {
520d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK_EQ(what, Converter::kWhatError);
521d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
522d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                status_t err;
523d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK(msg->findInt32("err", &err));
524d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
525d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ALOGE("converter signaled error %d", err);
526d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
527d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
528d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
529d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
530d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        default:
531d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            TRESPASS();
532d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
533d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
534d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
535d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::setupPacketizer() {
536d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> msg = new AMessage(kWhatSerializerNotify, id());
537d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
538d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mSerializerLooper = new ALooper;
539d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mSerializerLooper->start();
540d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
541d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mSerializer = new Serializer(
542d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#if FAKE_VIDEO
543d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            true /* throttled */
544d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#else
545d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            false /* throttled */
546d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#endif
547d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            , msg);
548d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mSerializerLooper->registerHandler(mSerializer);
549d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
550d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mPacketizer = new TSPacketizer;
551d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
552d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#if FAKE_VIDEO
553d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    DataSource::RegisterDefaultSniffers();
554d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
555d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<DataSource> dataSource =
556d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        DataSource::CreateFromURI(
557d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                "/system/etc/inception_1500.mp4");
558d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
559d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK(dataSource != NULL);
560d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
561d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
562d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK(extractor != NULL);
563d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
564d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    bool haveAudio = false;
565d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    bool haveVideo = false;
566d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    for (size_t i = 0; i < extractor->countTracks(); ++i) {
567d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        sp<MetaData> meta = extractor->getTrackMetaData(i);
568d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
569d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const char *mime;
570d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        CHECK(meta->findCString(kKeyMIMEType, &mime));
571d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
572d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        bool useTrack = false;
573d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (!strncasecmp(mime, "audio/", 6) && !haveAudio) {
574d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            useTrack = true;
575d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            haveAudio = true;
576d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        } else if (!strncasecmp(mime, "video/", 6) && !haveVideo) {
577d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            useTrack = true;
578d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            haveVideo = true;
579d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
580d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
581d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (!useTrack) {
582d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            continue;
583d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
584d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
585d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        sp<MediaSource> source = extractor->getTrack(i);
586d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
587d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        ssize_t index = mSerializer->addSource(source);
588d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        CHECK_GE(index, 0);
589d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
590d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        sp<AMessage> format;
591d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        status_t err = convertMetaDataToMessage(source->getFormat(), &format);
592d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        CHECK_EQ(err, (status_t)OK);
593d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
594d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mTracks.add(index, new Track(format));
595d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
596d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK(haveAudio || haveVideo);
597d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#else
598d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mCodecLooper = new ALooper;
599d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mCodecLooper->start();
600d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
601d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    DisplayInfo info;
602d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    SurfaceComposerClient::getDisplayInfo(0, &info);
603d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
604d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    // sp<SurfaceMediaSource> source = new SurfaceMediaSource(info.w, info.h);
6050b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber    sp<SurfaceMediaSource> source = new SurfaceMediaSource(width(), height());
606d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
607d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#if 0
608d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    ssize_t index = mSerializer->addSource(source);
609d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#else
610d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    ssize_t index = mSerializer->addSource(
611bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber            new RepeaterSource(source, 30.0 /* rateHz */));
612d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#endif
613d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
614d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK_GE(index, 0);
615d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
616d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> format;
617d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    status_t err = convertMetaDataToMessage(source->getFormat(), &format);
618d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK_EQ(err, (status_t)OK);
619d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
620d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    format->setInt32("store-metadata-in-buffers", true);
621d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
622d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    format->setInt32(
623d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            "color-format", OMX_COLOR_FormatAndroidOpaque);
624d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
625d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> notify = new AMessage(kWhatConverterNotify, id());
626d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    notify->setSize("trackIndex", index);
627d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
628d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<Converter> converter =
629d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        new Converter(notify, mCodecLooper, format);
63066e72bc85fb762876baff60ef29de729da93cf26Andreas Huber    CHECK_EQ(converter->initCheck(), (status_t)OK);
63166e72bc85fb762876baff60ef29de729da93cf26Andreas Huber
63266e72bc85fb762876baff60ef29de729da93cf26Andreas Huber    size_t numInputBuffers = converter->getInputBufferCount();
63366e72bc85fb762876baff60ef29de729da93cf26Andreas Huber    ALOGI("numInputBuffers to the encoder is %d", numInputBuffers);
634d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
635d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    looper()->registerHandler(converter);
636d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
637d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mTracks.add(index, new Track(converter));
63866e72bc85fb762876baff60ef29de729da93cf26Andreas Huber
63966e72bc85fb762876baff60ef29de729da93cf26Andreas Huber    sp<IServiceManager> sm = defaultServiceManager();
64066e72bc85fb762876baff60ef29de729da93cf26Andreas Huber    sp<IBinder> binder = sm->getService(String16("SurfaceFlinger"));
64166e72bc85fb762876baff60ef29de729da93cf26Andreas Huber    sp<ISurfaceComposer> service = interface_cast<ISurfaceComposer>(binder);
64266e72bc85fb762876baff60ef29de729da93cf26Andreas Huber    CHECK(service != NULL);
64366e72bc85fb762876baff60ef29de729da93cf26Andreas Huber
64466e72bc85fb762876baff60ef29de729da93cf26Andreas Huber    // Add one reference to account for the serializer.
64566e72bc85fb762876baff60ef29de729da93cf26Andreas Huber    err = source->setMaxAcquiredBufferCount(numInputBuffers + 1);
64666e72bc85fb762876baff60ef29de729da93cf26Andreas Huber    CHECK_EQ(err, (status_t)OK);
64766e72bc85fb762876baff60ef29de729da93cf26Andreas Huber
6480b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber    mBufferQueue = source->getBufferQueue();
6490b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber
6500b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber    if (mLegacyMode) {
6510b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber        service->connectDisplay(mBufferQueue);
6520b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber    }
653d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#endif
654d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
655082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber#if 0
656082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber    sp<AudioSource> audioSource = new AudioSource(
657082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber            AUDIO_SOURCE_MIC,
658082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber            48000 /* sampleRate */,
659082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber            2 /* channelCount */);  // XXX AUDIO_CHANNEL_IN_STEREO?
660082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber
661082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber    CHECK_EQ((status_t)OK, audioSource->initCheck());
662082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber
663082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber    audioSource->setUseLooperTime(true);
664082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber
665082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber    index = mSerializer->addSource(audioSource);
666082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber    CHECK_GE(index, 0);
667082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber
668082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber    sp<AMessage> audioFormat;
669082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber    err = convertMetaDataToMessage(audioSource->getFormat(), &audioFormat);
670082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber    CHECK_EQ(err, (status_t)OK);
671082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber
672082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber    sp<AMessage> audioNotify = new AMessage(kWhatConverterNotify, id());
673082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber    audioNotify->setSize("trackIndex", index);
674082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber
675082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber    converter = new Converter(audioNotify, mCodecLooper, audioFormat);
676082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber    looper()->registerHandler(converter);
677082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber
678082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber    mTracks.add(index, new Track(converter));
679082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber#endif
680082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber
681d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
682d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
683d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
6840b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Hubersp<ISurfaceTexture> WifiDisplaySource::PlaybackSession::getSurfaceTexture() {
6850b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber    return mBufferQueue;
6860b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber}
6870b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber
6880b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huberint32_t WifiDisplaySource::PlaybackSession::width() const {
6890b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber    return 720;
6900b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber}
6910b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber
6920b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huberint32_t WifiDisplaySource::PlaybackSession::height() const {
6930b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber    return 1280;
6940b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber}
6950b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber
696d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::scheduleSendSR() {
697d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mSendSRPending) {
698d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return;
699d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
700d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
701d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mSendSRPending = true;
702d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    (new AMessage(kWhatSendSR, id()))->post(kSendSRIntervalUs);
703d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
704d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
705d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::addSR(const sp<ABuffer> &buffer) {
706d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint8_t *data = buffer->data() + buffer->size();
707d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
708d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    // TODO: Use macros/utility functions to clean up all the bitshifts below.
709d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
710d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[0] = 0x80 | 0;
711d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[1] = 200;  // SR
712d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[2] = 0;
713d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[3] = 6;
714d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[4] = kSourceID >> 24;
715d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[5] = (kSourceID >> 16) & 0xff;
716d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[6] = (kSourceID >> 8) & 0xff;
717d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[7] = kSourceID & 0xff;
718d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
719d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[8] = mLastNTPTime >> (64 - 8);
720d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[9] = (mLastNTPTime >> (64 - 16)) & 0xff;
721d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[10] = (mLastNTPTime >> (64 - 24)) & 0xff;
722d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[11] = (mLastNTPTime >> 32) & 0xff;
723d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[12] = (mLastNTPTime >> 24) & 0xff;
724d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[13] = (mLastNTPTime >> 16) & 0xff;
725d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[14] = (mLastNTPTime >> 8) & 0xff;
726d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[15] = mLastNTPTime & 0xff;
727d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
728d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[16] = (mLastRTPTime >> 24) & 0xff;
729d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[17] = (mLastRTPTime >> 16) & 0xff;
730d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[18] = (mLastRTPTime >> 8) & 0xff;
731d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[19] = mLastRTPTime & 0xff;
732d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
733d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[20] = mNumRTPSent >> 24;
734d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[21] = (mNumRTPSent >> 16) & 0xff;
735d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[22] = (mNumRTPSent >> 8) & 0xff;
736d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[23] = mNumRTPSent & 0xff;
737d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
738d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[24] = mNumRTPOctetsSent >> 24;
739d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[25] = (mNumRTPOctetsSent >> 16) & 0xff;
740d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[26] = (mNumRTPOctetsSent >> 8) & 0xff;
741d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[27] = mNumRTPOctetsSent & 0xff;
742d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
743d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    buffer->setRange(buffer->offset(), buffer->size() + 28);
744d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
745d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
746d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::addSDES(const sp<ABuffer> &buffer) {
747d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint8_t *data = buffer->data() + buffer->size();
748d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[0] = 0x80 | 1;
749d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[1] = 202;  // SDES
750d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[4] = kSourceID >> 24;
751d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[5] = (kSourceID >> 16) & 0xff;
752d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[6] = (kSourceID >> 8) & 0xff;
753d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[7] = kSourceID & 0xff;
754d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
755d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    size_t offset = 8;
756d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
757d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = 1;  // CNAME
758d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
759d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    static const char *kCNAME = "someone@somewhere";
760d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = strlen(kCNAME);
761d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
762d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    memcpy(&data[offset], kCNAME, strlen(kCNAME));
763d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    offset += strlen(kCNAME);
764d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
765d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = 7;  // NOTE
766d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
767d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    static const char *kNOTE = "Hell's frozen over.";
768d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = strlen(kNOTE);
769d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
770d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    memcpy(&data[offset], kNOTE, strlen(kNOTE));
771d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    offset += strlen(kNOTE);
772d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
773d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = 0;
774d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
775d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if ((offset % 4) > 0) {
776d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        size_t count = 4 - (offset % 4);
777d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        switch (count) {
778d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 3:
779d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                data[offset++] = 0;
780d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 2:
781d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                data[offset++] = 0;
782d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 1:
783d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                data[offset++] = 0;
784d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
785d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
786d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
787d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    size_t numWords = (offset / 4) - 1;
788d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[2] = numWords >> 8;
789d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[3] = numWords & 0xff;
790d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
791d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    buffer->setRange(buffer->offset(), buffer->size() + offset);
792d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
793d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
794d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber// static
795d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberuint64_t WifiDisplaySource::PlaybackSession::GetNowNTP() {
796d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint64_t nowUs = ALooper::GetNowUs();
797d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
798d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll;
799d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
800d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint64_t hi = nowUs / 1000000ll;
801d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint64_t lo = ((1ll << 32) * (nowUs % 1000000ll)) / 1000000ll;
802d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
803d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return (hi << 32) | lo;
804d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
805d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
806d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::onSendSR() {
807d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<ABuffer> buffer = new ABuffer(1500);
808d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    buffer->setRange(0, 0);
809d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
810d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    addSR(buffer);
811d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    addSDES(buffer);
812d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
813d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mUseInterleavedTCP) {
814d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        sp<AMessage> notify = mNotify->dup();
815d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        notify->setInt32("what", kWhatBinaryData);
816d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        notify->setInt32("channel", mRTCPChannel);
817d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        notify->setBuffer("data", buffer);
818d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        notify->post();
819d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    } else {
820d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mNetSession->sendRequest(
821d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                mRTCPSessionID, buffer->data(), buffer->size());
822d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
823d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
824d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    ++mNumSRsSent;
825d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
826d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
827d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberssize_t WifiDisplaySource::PlaybackSession::appendTSData(
828d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const void *data, size_t size, bool timeDiscontinuity, bool flush) {
829d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK_EQ(size, 188);
830d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
831d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK_LE(mTSQueue->size() + size, mTSQueue->capacity());
832d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
833d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    memcpy(mTSQueue->data() + mTSQueue->size(), data, size);
834d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mTSQueue->setRange(0, mTSQueue->size() + size);
835d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
836d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (flush || mTSQueue->size() == mTSQueue->capacity()) {
837d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        // flush
838d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
839d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        int64_t nowUs = ALooper::GetNowUs();
840d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (mFirstPacketTimeUs < 0ll) {
841d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mFirstPacketTimeUs = nowUs;
842d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
843d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
844d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        // 90kHz time scale
845d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        uint32_t rtpTime = ((nowUs - mFirstPacketTimeUs) * 9ll) / 100ll;
846d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
847d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        uint8_t *rtp = mTSQueue->data();
848d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[0] = 0x80;
849d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[1] = 33 | (timeDiscontinuity ? (1 << 7) : 0);  // M-bit
850d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[2] = (mRTPSeqNo >> 8) & 0xff;
851d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[3] = mRTPSeqNo & 0xff;
852d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[4] = rtpTime >> 24;
853d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[5] = (rtpTime >> 16) & 0xff;
854d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[6] = (rtpTime >> 8) & 0xff;
855d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[7] = rtpTime & 0xff;
856d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[8] = kSourceID >> 24;
857d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[9] = (kSourceID >> 16) & 0xff;
858d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[10] = (kSourceID >> 8) & 0xff;
859d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[11] = kSourceID & 0xff;
860d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
861d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        ++mRTPSeqNo;
862d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        ++mNumRTPSent;
863d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mNumRTPOctetsSent += mTSQueue->size() - 12;
864d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
865d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mLastRTPTime = rtpTime;
866d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mLastNTPTime = GetNowNTP();
867d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
868d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (mUseInterleavedTCP) {
869d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            sp<AMessage> notify = mNotify->dup();
870d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            notify->setInt32("what", kWhatBinaryData);
871d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
872d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            sp<ABuffer> data = new ABuffer(mTSQueue->size());
873d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            memcpy(data->data(), rtp, mTSQueue->size());
874d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
875d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            notify->setInt32("channel", mRTPChannel);
876d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            notify->setBuffer("data", data);
877d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            notify->post();
878d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        } else {
879d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mNetSession->sendRequest(
880d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    mRTPSessionID, rtp, mTSQueue->size());
881d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
882d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
883d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mTSQueue->setInt32Data(mRTPSeqNo - 1);
884d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mHistory.push_back(mTSQueue);
885d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        ++mHistoryLength;
886d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
887d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (mHistoryLength > kMaxHistoryLength) {
888d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mTSQueue = *mHistory.begin();
889d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mHistory.erase(mHistory.begin());
890d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
891d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            --mHistoryLength;
892d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        } else {
893d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mTSQueue = new ABuffer(12 + kMaxNumTSPacketsPerRTPPacket * 188);
894d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
895d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
896d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mTSQueue->setRange(0, 12);
897d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
898d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
899d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return size;
900d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
901d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
902d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::parseRTCP(
903d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const sp<ABuffer> &buffer) {
904d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    const uint8_t *data = buffer->data();
905d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    size_t size = buffer->size();
906d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
907d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    while (size > 0) {
908d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (size < 8) {
909d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            // Too short to be a valid RTCP header
910d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            return ERROR_MALFORMED;
911d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
912d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
913d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if ((data[0] >> 6) != 2) {
914d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            // Unsupported version.
915d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            return ERROR_UNSUPPORTED;
916d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
917d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
918d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (data[0] & 0x20) {
919d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            // Padding present.
920d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
921d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            size_t paddingLength = data[size - 1];
922d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
923d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            if (paddingLength + 12 > size) {
924d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                // If we removed this much padding we'd end up with something
925d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                // that's too short to be a valid RTP header.
926d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                return ERROR_MALFORMED;
927d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
928d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
929d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            size -= paddingLength;
930d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
931d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
932d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        size_t headerLength = 4 * (data[2] << 8 | data[3]) + 4;
933d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
934d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (size < headerLength) {
935d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            // Only received a partial packet?
936d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            return ERROR_MALFORMED;
937d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
938d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
939d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        switch (data[1]) {
940d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 200:
941d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 201:  // RR
942d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 202:  // SDES
943d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 203:
944d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 204:  // APP
945d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
946d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
947d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 205:  // TSFB (transport layer specific feedback)
948d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                parseTSFB(data, headerLength);
949d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
950d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
951d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 206:  // PSFB (payload specific feedback)
952d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                hexdump(data, headerLength);
953d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
954d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
955d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            default:
956d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            {
957d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ALOGW("Unknown RTCP packet type %u of size %d",
958d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                     (unsigned)data[1], headerLength);
959d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
960d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
961d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
962d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
963d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        data += headerLength;
964d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        size -= headerLength;
965d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
966d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
967d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
968d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
969d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
970d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::parseTSFB(
971d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const uint8_t *data, size_t size) {
972d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if ((data[0] & 0x1f) != 1) {
973d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return ERROR_UNSUPPORTED;  // We only support NACK for now.
974d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
975d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
976d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint32_t srcId = U32_AT(&data[8]);
977d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (srcId != kSourceID) {
978d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return ERROR_MALFORMED;
979d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
980d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
981d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    for (size_t i = 12; i < size; i += 4) {
982d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        uint16_t seqNo = U16_AT(&data[i]);
983d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        uint16_t blp = U16_AT(&data[i + 2]);
984d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
985d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        List<sp<ABuffer> >::iterator it = mHistory.begin();
986d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        bool found = false;
987d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        while (it != mHistory.end()) {
988d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            const sp<ABuffer> &buffer = *it;
989d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
990d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            uint16_t bufferSeqNo = buffer->int32Data() & 0xffff;
991d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
992d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            if (bufferSeqNo == seqNo) {
993d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                mNetSession->sendRequest(
994d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        mRTPSessionID, buffer->data(), buffer->size());
995d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
996d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                found = true;
997d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
998d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
999d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1000d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            ++it;
1001d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1002d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1003d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (found) {
1004d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            ALOGI("retransmitting seqNo %d", seqNo);
1005d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        } else {
1006d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            ALOGI("seqNo %d no longer available", seqNo);
1007d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1008d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1009d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1010d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
1011d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1012d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1013d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}  // namespace android
1014d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1015