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