PlaybackSession.cpp revision bd08e2f93bafd02abf2c25d740e9fb8bce455a99
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"
24e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber#include "MediaPuller.h"
25d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include "RepeaterSource.h"
26d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include "Serializer.h"
27d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include "TSPacketizer.h"
28d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
29d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <binder/IServiceManager.h>
30d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <gui/ISurfaceComposer.h>
31d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <gui/SurfaceComposerClient.h>
32d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/foundation/ABuffer.h>
33d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/foundation/ADebug.h>
34d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/foundation/AMessage.h>
35d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/foundation/hexdump.h>
36082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber#include <media/stagefright/AudioSource.h>
37d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/DataSource.h>
38d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MediaDefs.h>
39d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MediaErrors.h>
40d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MediaExtractor.h>
41d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MediaSource.h>
42d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MetaData.h>
43d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MPEG2TSWriter.h>
44d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/SurfaceMediaSource.h>
45d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/Utils.h>
46d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
47d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <OMX_IVCommon.h>
48d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
49bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber//#define FAKE_VIDEO            1
50bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber#define USE_SERIALIZER          0
51d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
52d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubernamespace android {
53d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
54d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatic size_t kMaxRTPPacketSize = 1500;
55d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatic size_t kMaxNumTSPacketsPerRTPPacket = (kMaxRTPPacketSize - 12) / 188;
56d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
57d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstruct WifiDisplaySource::PlaybackSession::Track : public RefBase {
58e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    Track(const sp<ALooper> &pullLooper,
59e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber          const sp<ALooper> &codecLooper,
60e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber          const sp<MediaPuller> &mediaPuller,
61e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber          const sp<Converter> &converter);
62e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
63d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    Track(const sp<AMessage> &format);
64d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
65d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> getFormat();
66d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
67d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    const sp<Converter> &converter() const;
68d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    ssize_t packetizerTrackIndex() const;
69d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
70d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    void setPacketizerTrackIndex(size_t index);
71d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
72e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    status_t start();
73e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    status_t stop();
74e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
75d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberprotected:
76d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    virtual ~Track();
77d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
78d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberprivate:
79e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<ALooper> mPullLooper;
80e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<ALooper> mCodecLooper;
81e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<MediaPuller> mMediaPuller;
82d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<Converter> mConverter;
83d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> mFormat;
84e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    bool mStarted;
85d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    ssize_t mPacketizerTrackIndex;
86d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
87d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    DISALLOW_EVIL_CONSTRUCTORS(Track);
88d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber};
89d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
90e1957358f11031a554c57d4fb46988dd6044acc1Andreas HuberWifiDisplaySource::PlaybackSession::Track::Track(
91e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        const sp<ALooper> &pullLooper,
92e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        const sp<ALooper> &codecLooper,
93e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        const sp<MediaPuller> &mediaPuller,
94e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        const sp<Converter> &converter)
95e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    : mPullLooper(pullLooper),
96e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber      mCodecLooper(codecLooper),
97e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber      mMediaPuller(mediaPuller),
98e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber      mConverter(converter),
99e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber      mStarted(false),
100d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mPacketizerTrackIndex(-1) {
101d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
102d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
103d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas HuberWifiDisplaySource::PlaybackSession::Track::Track(const sp<AMessage> &format)
104d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    : mFormat(format),
105d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mPacketizerTrackIndex(-1) {
106d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
107d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
108d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas HuberWifiDisplaySource::PlaybackSession::Track::~Track() {
109e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    stop();
110d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
111d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
112d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubersp<AMessage> WifiDisplaySource::PlaybackSession::Track::getFormat() {
113d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mFormat != NULL) {
114d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return mFormat;
115d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
116d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
117d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mConverter->getOutputFormat();
118d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
119d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
120d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberconst sp<Converter> &WifiDisplaySource::PlaybackSession::Track::converter() const {
121d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mConverter;
122d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
123d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
124d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberssize_t WifiDisplaySource::PlaybackSession::Track::packetizerTrackIndex() const {
125d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mPacketizerTrackIndex;
126d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
127d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
128d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::Track::setPacketizerTrackIndex(size_t index) {
129d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK_LT(mPacketizerTrackIndex, 0);
130d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mPacketizerTrackIndex = index;
131d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
132d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
133e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::Track::start() {
134e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (mStarted) {
135e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        return INVALID_OPERATION;
136e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
137e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
138e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    status_t err = OK;
139e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
140e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (mMediaPuller != NULL) {
141e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        err = mMediaPuller->start();
142e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
143e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
144e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (err == OK) {
145e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        mStarted = true;
146e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
147e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
148e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return err;
149e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber}
150e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
151e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::Track::stop() {
152e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (!mStarted) {
153e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        return INVALID_OPERATION;
154e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
155e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
156e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    status_t err = OK;
157e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
158e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (mMediaPuller != NULL) {
159e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        err = mMediaPuller->stop();
160e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
161e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
162a438123bd96c7faf145683876702387efe5628d9Andreas Huber    mConverter.clear();
163a438123bd96c7faf145683876702387efe5628d9Andreas Huber
164e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mStarted = false;
165e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
166e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return err;
167e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber}
168e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
169d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber////////////////////////////////////////////////////////////////////////////////
170d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
171d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas HuberWifiDisplaySource::PlaybackSession::PlaybackSession(
172d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const sp<ANetworkSession> &netSession,
1730b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber        const sp<AMessage> &notify,
174bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        const in_addr &interfaceAddr,
1750b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber        bool legacyMode)
176d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    : mNetSession(netSession),
177d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mNotify(notify),
178bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber      mInterfaceAddr(interfaceAddr),
1790b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber      mLegacyMode(legacyMode),
180d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mLastLifesignUs(),
181e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber      mVideoTrackIndex(-1),
182d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mTSQueue(new ABuffer(12 + kMaxNumTSPacketsPerRTPPacket * 188)),
183d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mPrevTimeUs(-1ll),
184bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber      mTransportMode(TRANSPORT_UDP),
185d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTPChannel(0),
186d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTCPChannel(0),
187d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTPPort(0),
188d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTPSessionID(0),
189d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTCPSessionID(0),
190bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber      mClientRTPPort(0),
191bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber      mClientRTCPPort(0),
192bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber      mRTPConnected(false),
193bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber      mRTCPConnected(false),
194d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTPSeqNo(0),
195d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mLastNTPTime(0),
196d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mLastRTPTime(0),
197d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mNumRTPSent(0),
198d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mNumRTPOctetsSent(0),
199d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mNumSRsSent(0),
200d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mSendSRPending(false),
201d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mFirstPacketTimeUs(-1ll),
202dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber      mHistoryLength(0),
203dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber      mTotalBytesSent(0ll)
204774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#if LOG_TRANSPORT_STREAM
205774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber      ,mLogFile(NULL)
206774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#endif
207774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber{
208d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mTSQueue->setRange(0, 12);
209774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber
210774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#if LOG_TRANSPORT_STREAM
211774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber    mLogFile = fopen("/system/etc/log.ts", "wb");
212774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#endif
213d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
214d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
215d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::init(
216d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const char *clientIP, int32_t clientRtp, int32_t clientRtcp,
217bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        TransportMode transportMode) {
218bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    mClientIP = clientIP;
219bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
220d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    status_t err = setupPacketizer();
221d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
222d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (err != OK) {
223d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return err;
224d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
225d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
226bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    mTransportMode = transportMode;
227bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
228bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (transportMode == TRANSPORT_TCP_INTERLEAVED) {
229d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTPChannel = clientRtp;
230d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTCPChannel = clientRtcp;
231d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTPPort = 0;
232d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTPSessionID = 0;
233d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTCPSessionID = 0;
234d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
235d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        updateLiveness();
236d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return OK;
237d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
238d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
239d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mRTPChannel = 0;
240d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mRTCPChannel = 0;
241d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
242bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mTransportMode == TRANSPORT_TCP) {
243bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        // XXX This is wrong, we need to allocate sockets here, we only
244bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        // need to do this because the dongles are not establishing their
245bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        // end until after PLAY instead of before SETUP.
246bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        mRTPPort = 20000;
247bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        mRTPSessionID = 0;
248bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        mRTCPSessionID = 0;
249bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        mClientRTPPort = clientRtp;
250bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        mClientRTCPPort = clientRtcp;
251bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
252bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        updateLiveness();
253bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        return OK;
254bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    }
255bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
256d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    int serverRtp;
257d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
258d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> rtpNotify = new AMessage(kWhatRTPNotify, id());
259d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> rtcpNotify = new AMessage(kWhatRTCPNotify, id());
260d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    for (serverRtp = 15550;; serverRtp += 2) {
261d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        int32_t rtpSession;
262bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        if (mTransportMode == TRANSPORT_UDP) {
263bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            err = mNetSession->createUDPSession(
264bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        serverRtp, clientIP, clientRtp,
265bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        rtpNotify, &rtpSession);
266bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        } else {
267bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            err = mNetSession->createTCPDatagramSession(
268bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        serverRtp, clientIP, clientRtp,
269bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        rtpNotify, &rtpSession);
270bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        }
271d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
272d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (err != OK) {
273d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            ALOGI("failed to create RTP socket on port %d", serverRtp);
274d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            continue;
275d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
276d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
277d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (clientRtcp < 0) {
278d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            // No RTCP.
279d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
280d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mRTPPort = serverRtp;
281d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mRTPSessionID = rtpSession;
282d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mRTCPSessionID = 0;
283d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
284d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            ALOGI("rtpSessionId = %d", rtpSession);
285d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
286d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
287d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
288d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        int32_t rtcpSession;
289bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        if (mTransportMode == TRANSPORT_UDP) {
290bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            err = mNetSession->createUDPSession(
291bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    serverRtp + 1, clientIP, clientRtcp,
292bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    rtcpNotify, &rtcpSession);
293bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        } else {
294bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            err = mNetSession->createTCPDatagramSession(
295bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    serverRtp + 1, clientIP, clientRtcp,
296bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    rtcpNotify, &rtcpSession);
297bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        }
298d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
299d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (err == OK) {
300d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mRTPPort = serverRtp;
301d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mRTPSessionID = rtpSession;
302d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mRTCPSessionID = rtcpSession;
303d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
304d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            ALOGI("rtpSessionID = %d, rtcpSessionID = %d", rtpSession, rtcpSession);
305d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
306d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
307d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
308d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        ALOGI("failed to create RTCP socket on port %d", serverRtp + 1);
309d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mNetSession->destroySession(rtpSession);
310d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
311d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
312d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mRTPPort == 0) {
313d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return UNKNOWN_ERROR;
314d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
315d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
316d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    updateLiveness();
317d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
318d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
319d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
320d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
321d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas HuberWifiDisplaySource::PlaybackSession::~PlaybackSession() {
322774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#if LOG_TRANSPORT_STREAM
323774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber    if (mLogFile != NULL) {
324774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber        fclose(mLogFile);
325774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber        mLogFile = NULL;
326774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber    }
327774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#endif
328d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
329d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
330d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberint32_t WifiDisplaySource::PlaybackSession::getRTPPort() const {
331d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mRTPPort;
332d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
333d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
334d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberint64_t WifiDisplaySource::PlaybackSession::getLastLifesignUs() const {
335d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mLastLifesignUs;
336d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
337d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
338d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::updateLiveness() {
339d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mLastLifesignUs = ALooper::GetNowUs();
340d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
341d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
342d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::play() {
343d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    updateLiveness();
344d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
345bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    return OK;
346bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber}
347bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
348bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::finishPlay() {
349bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    // XXX Give the dongle 3 secs to bind its sockets.
350bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    (new AMessage(kWhatFinishPlay, id()))->post(3000000ll);
351bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    return OK;
352bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber}
353bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
354bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::onFinishPlay() {
355bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mTransportMode != TRANSPORT_TCP) {
356bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        return onFinishPlay2();
357bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    }
358bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
359bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    sp<AMessage> rtpNotify = new AMessage(kWhatRTPNotify, id());
360bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
361bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    status_t err = mNetSession->createTCPDatagramSession(
362bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                mRTPPort, mClientIP.c_str(), mClientRTPPort,
363bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                rtpNotify, &mRTPSessionID);
364bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
365bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (err != OK) {
366bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        return err;
367bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    }
368bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
369bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mClientRTCPPort >= 0) {
370bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        sp<AMessage> rtcpNotify = new AMessage(kWhatRTCPNotify, id());
371bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
372bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        err = mNetSession->createTCPDatagramSession(
373bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                mRTPPort + 1, mClientIP.c_str(), mClientRTCPPort,
374bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                rtcpNotify, &mRTCPSessionID);
375bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    }
376bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
377bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    return err;
378bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber}
379bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
380bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::onFinishPlay2() {
381d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mRTCPSessionID != 0) {
382d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        scheduleSendSR();
383d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
384d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
385e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (mSerializer != NULL) {
386e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        return mSerializer->start();
387e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
388e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
389e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    for (size_t i = 0; i < mTracks.size(); ++i) {
390e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        status_t err = mTracks.editValueAt(i)->start();
391e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
392e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        if (err != OK) {
393e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            for (size_t j = 0; j < i; ++j) {
394e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                mTracks.editValueAt(j)->stop();
395e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            }
396e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
397e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            return err;
398e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        }
399e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
400e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
401bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    sp<AMessage> notify = mNotify->dup();
402bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    notify->setInt32("what", kWhatSessionEstablished);
403bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    notify->post();
404bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
405e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return OK;
406d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
407d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
408d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::pause() {
409d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    updateLiveness();
410d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
411d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
412d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
413d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
414a438123bd96c7faf145683876702387efe5628d9Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::destroy() {
415a438123bd96c7faf145683876702387efe5628d9Andreas Huber    mTracks.clear();
416a438123bd96c7faf145683876702387efe5628d9Andreas Huber
417a438123bd96c7faf145683876702387efe5628d9Andreas Huber    mPacketizer.clear();
418a438123bd96c7faf145683876702387efe5628d9Andreas Huber
419a438123bd96c7faf145683876702387efe5628d9Andreas Huber    if (mSerializer != NULL) {
420a438123bd96c7faf145683876702387efe5628d9Andreas Huber        mSerializer->stop();
421a438123bd96c7faf145683876702387efe5628d9Andreas Huber
422a438123bd96c7faf145683876702387efe5628d9Andreas Huber        looper()->unregisterHandler(mSerializer->id());
423a438123bd96c7faf145683876702387efe5628d9Andreas Huber        mSerializer.clear();
424a438123bd96c7faf145683876702387efe5628d9Andreas Huber    }
425a438123bd96c7faf145683876702387efe5628d9Andreas Huber
426a438123bd96c7faf145683876702387efe5628d9Andreas Huber    mTracks.clear();
427a438123bd96c7faf145683876702387efe5628d9Andreas Huber
428a438123bd96c7faf145683876702387efe5628d9Andreas Huber    if (mSerializerLooper != NULL) {
429a438123bd96c7faf145683876702387efe5628d9Andreas Huber        mSerializerLooper->stop();
430a438123bd96c7faf145683876702387efe5628d9Andreas Huber        mSerializerLooper.clear();
431a438123bd96c7faf145683876702387efe5628d9Andreas Huber    }
432a438123bd96c7faf145683876702387efe5628d9Andreas Huber
433a438123bd96c7faf145683876702387efe5628d9Andreas Huber    if (mLegacyMode) {
434a438123bd96c7faf145683876702387efe5628d9Andreas Huber        sp<IServiceManager> sm = defaultServiceManager();
435a438123bd96c7faf145683876702387efe5628d9Andreas Huber        sp<IBinder> binder = sm->getService(String16("SurfaceFlinger"));
436a438123bd96c7faf145683876702387efe5628d9Andreas Huber        sp<ISurfaceComposer> service = interface_cast<ISurfaceComposer>(binder);
437a438123bd96c7faf145683876702387efe5628d9Andreas Huber        CHECK(service != NULL);
438a438123bd96c7faf145683876702387efe5628d9Andreas Huber
439a438123bd96c7faf145683876702387efe5628d9Andreas Huber        service->connectDisplay(NULL);
440a438123bd96c7faf145683876702387efe5628d9Andreas Huber    }
441a438123bd96c7faf145683876702387efe5628d9Andreas Huber
442a438123bd96c7faf145683876702387efe5628d9Andreas Huber    if (mRTCPSessionID != 0) {
443a438123bd96c7faf145683876702387efe5628d9Andreas Huber        mNetSession->destroySession(mRTCPSessionID);
444a438123bd96c7faf145683876702387efe5628d9Andreas Huber    }
445a438123bd96c7faf145683876702387efe5628d9Andreas Huber
446a438123bd96c7faf145683876702387efe5628d9Andreas Huber    if (mRTPSessionID != 0) {
447a438123bd96c7faf145683876702387efe5628d9Andreas Huber        mNetSession->destroySession(mRTPSessionID);
448a438123bd96c7faf145683876702387efe5628d9Andreas Huber    }
449a438123bd96c7faf145683876702387efe5628d9Andreas Huber
450a438123bd96c7faf145683876702387efe5628d9Andreas Huber    return OK;
451a438123bd96c7faf145683876702387efe5628d9Andreas Huber}
452a438123bd96c7faf145683876702387efe5628d9Andreas Huber
453d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::onMessageReceived(
454d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const sp<AMessage> &msg) {
455d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    switch (msg->what()) {
456d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        case kWhatRTPNotify:
457d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        case kWhatRTCPNotify:
458d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        {
459d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            int32_t reason;
460d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            CHECK(msg->findInt32("reason", &reason));
461d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
462d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            switch (reason) {
463d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                case ANetworkSession::kWhatError:
464d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                {
465d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    int32_t sessionID;
466d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findInt32("sessionID", &sessionID));
467d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
468d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    int32_t err;
469d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findInt32("err", &err));
470d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
471d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    int32_t errorOccuredDuringSend;
472d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findInt32("send", &errorOccuredDuringSend));
473d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
474d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    AString detail;
475d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findString("detail", &detail));
476d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
477d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    if (msg->what() == kWhatRTPNotify
478d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                            && !errorOccuredDuringSend) {
479d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        // This is ok, we don't expect to receive anything on
480d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        // the RTP socket.
481d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        break;
482d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
483d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
484d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    ALOGE("An error occurred during %s in session %d "
485d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          "(%d, '%s' (%s)).",
486d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          errorOccuredDuringSend ? "send" : "receive",
487d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          sessionID,
488d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          err,
489d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          detail.c_str(),
490d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          strerror(-err));
491d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
492d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    mNetSession->destroySession(sessionID);
493d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
494d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    if (sessionID == mRTPSessionID) {
495d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        mRTPSessionID = 0;
496d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    } else if (sessionID == mRTCPSessionID) {
497d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        mRTCPSessionID = 0;
498d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
499d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
500d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    // Inform WifiDisplaySource of our premature death (wish).
501d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    sp<AMessage> notify = mNotify->dup();
502d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    notify->setInt32("what", kWhatSessionDead);
503d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    notify->post();
504d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    break;
505d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
506d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
507d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                case ANetworkSession::kWhatDatagram:
508d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                {
509d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    int32_t sessionID;
510d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findInt32("sessionID", &sessionID));
511d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
512d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    sp<ABuffer> data;
513d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findBuffer("data", &data));
514d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
515d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    status_t err;
516d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    if (msg->what() == kWhatRTCPNotify) {
517d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        err = parseRTCP(data);
518d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
519d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    break;
520d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
521d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
522bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                case ANetworkSession::kWhatConnected:
523bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                {
524bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    CHECK_EQ(mTransportMode, TRANSPORT_TCP);
525bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
526bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    int32_t sessionID;
527bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    CHECK(msg->findInt32("sessionID", &sessionID));
528bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
529bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    if (sessionID == mRTPSessionID) {
530bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        CHECK(!mRTPConnected);
531bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        mRTPConnected = true;
532bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        ALOGI("RTP Session now connected.");
533bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    } else if (sessionID == mRTCPSessionID) {
534bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        CHECK(!mRTCPConnected);
535bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        mRTCPConnected = true;
536bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        ALOGI("RTCP Session now connected.");
537bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    } else {
538bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        TRESPASS();
539bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    }
540bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
541bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    if (mRTPConnected
542bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                            && (mClientRTCPPort < 0 || mRTCPConnected)) {
543bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        onFinishPlay2();
544bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    }
545bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    break;
546bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                }
547bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
548d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                default:
549d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    TRESPASS();
550d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
551d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
552d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
553d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
554d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        case kWhatSendSR:
555d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        {
556d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mSendSRPending = false;
557d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
558d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            if (mRTCPSessionID == 0) {
559d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
560d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
561d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
562d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            onSendSR();
563d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
564d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            scheduleSendSR();
565d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
566d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
567d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
568d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        case kWhatSerializerNotify:
569d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        {
570d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            int32_t what;
571d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            CHECK(msg->findInt32("what", &what));
572d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
573d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            if (what == Serializer::kWhatEOS) {
574d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ALOGI("input eos");
575d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
576d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                for (size_t i = 0; i < mTracks.size(); ++i) {
577d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#if FAKE_VIDEO
578d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    sp<AMessage> msg = new AMessage(kWhatConverterNotify, id());
579d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    msg->setInt32("what", Converter::kWhatEOS);
580d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    msg->setSize("trackIndex", i);
581d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    msg->post();
582d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#else
583d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    mTracks.valueAt(i)->converter()->signalEOS();
584d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#endif
585d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
586d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            } else {
587d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK_EQ(what, Serializer::kWhatAccessUnit);
588d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
589d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                size_t trackIndex;
590d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK(msg->findSize("trackIndex", &trackIndex));
591d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
592d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                sp<ABuffer> accessUnit;
593d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK(msg->findBuffer("accessUnit", &accessUnit));
594d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
595d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#if FAKE_VIDEO
596d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                int64_t timeUs;
597d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
598d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
599d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                void *mbuf;
600d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK(accessUnit->meta()->findPointer("mediaBuffer", &mbuf));
601d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
602d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ((MediaBuffer *)mbuf)->release();
603d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                mbuf = NULL;
604d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
605d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                sp<AMessage> msg = new AMessage(kWhatConverterNotify, id());
606d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                msg->setInt32("what", Converter::kWhatAccessUnit);
607d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                msg->setSize("trackIndex", trackIndex);
608d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                msg->setBuffer("accessUnit", accessUnit);
609d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                msg->post();
610d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#else
611d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                mTracks.valueFor(trackIndex)->converter()
612d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    ->feedAccessUnit(accessUnit);
613d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#endif
614d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
615d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
616d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
617d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
618d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        case kWhatConverterNotify:
619d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        {
620d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            int32_t what;
621d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            CHECK(msg->findInt32("what", &what));
622d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
623d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            size_t trackIndex;
624d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            CHECK(msg->findSize("trackIndex", &trackIndex));
625d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
626d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            if (what == Converter::kWhatAccessUnit) {
627d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                const sp<Track> &track = mTracks.valueFor(trackIndex);
628d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
629d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                uint32_t flags = 0;
630d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
631d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ssize_t packetizerTrackIndex = track->packetizerTrackIndex();
632d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                if (packetizerTrackIndex < 0) {
633d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    flags = TSPacketizer::EMIT_PAT_AND_PMT;
634d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
635d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    packetizerTrackIndex =
636d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        mPacketizer->addTrack(track->getFormat());
637d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
638d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    if (packetizerTrackIndex >= 0) {
639d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        track->setPacketizerTrackIndex(packetizerTrackIndex);
640d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
641d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
642d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
643d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                if (packetizerTrackIndex >= 0) {
644d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    sp<ABuffer> accessUnit;
645d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findBuffer("accessUnit", &accessUnit));
646d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
647d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    int64_t timeUs;
648d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
649d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
650d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    if (mPrevTimeUs < 0ll || mPrevTimeUs + 100000ll >= timeUs) {
651d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        flags |= TSPacketizer::EMIT_PCR;
652d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        mPrevTimeUs = timeUs;
653d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
654d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
655d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    sp<ABuffer> packets;
656d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    mPacketizer->packetize(
657d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                            packetizerTrackIndex, accessUnit, &packets, flags);
658d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
659d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    for (size_t offset = 0;
660d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                            offset < packets->size(); offset += 188) {
661d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        bool lastTSPacket = (offset + 188 >= packets->size());
662d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
663e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                        // We're only going to flush video, audio packets are
664e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                        // much more frequent and would waste all that space
665e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                        // available in a full sized UDP packet.
666e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                        bool flush =
667e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                            lastTSPacket
668e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                                && ((ssize_t)trackIndex == mVideoTrackIndex);
669e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
670d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        appendTSData(
671d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                                packets->data() + offset,
672d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                                188,
673d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                                true /* timeDiscontinuity */,
674e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                                flush);
675d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
676774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber
677774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#if LOG_TRANSPORT_STREAM
678774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber                    if (mLogFile != NULL) {
679774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber                        fwrite(packets->data(), 1, packets->size(), mLogFile);
680774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber                    }
681774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#endif
682d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
683d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            } else if (what == Converter::kWhatEOS) {
684d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK_EQ(what, Converter::kWhatEOS);
685d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
686d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ALOGI("output EOS on track %d", trackIndex);
687d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
688d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ssize_t index = mTracks.indexOfKey(trackIndex);
689d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK_GE(index, 0);
690d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
691d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#if !FAKE_VIDEO
692d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                const sp<Converter> &converter =
693d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    mTracks.valueAt(index)->converter();
694d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                looper()->unregisterHandler(converter->id());
695d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#endif
696d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
697d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                mTracks.removeItemsAt(index);
698d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
699d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                if (mTracks.isEmpty()) {
700d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    ALOGI("Reached EOS");
701d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
702d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            } else {
703d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK_EQ(what, Converter::kWhatError);
704d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
705d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                status_t err;
706d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK(msg->findInt32("err", &err));
707d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
708d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ALOGE("converter signaled error %d", err);
709d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
710d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
711d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
712d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
713bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        case kWhatFinishPlay:
714bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        {
715bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            onFinishPlay();
716bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            break;
717bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        }
718bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
719d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        default:
720d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            TRESPASS();
721d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
722d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
723d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
724d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::setupPacketizer() {
725d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> msg = new AMessage(kWhatSerializerNotify, id());
726d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
727e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mPacketizer = new TSPacketizer;
728d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
729d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#if FAKE_VIDEO
730e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return addFakeSources();
731d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#else
732e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    status_t err = addVideoSource();
733d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
734e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (err != OK) {
735e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        return err;
736e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
737e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
738e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return addAudioSource();
739e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber#endif
740e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber}
741d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
742e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::addFakeSources() {
743d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#if FAKE_VIDEO
744e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mSerializerLooper = new ALooper;
745e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mSerializerLooper->setName("serializer_looper");
746e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mSerializerLooper->start();
747e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
748e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<AMessage> msg = new AMessage(kWhatSerializerNotify, id());
749e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mSerializer = new Serializer(
750e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            true /* throttled */, msg);
751e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
752e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mSerializerLooper->registerHandler(mSerializer);
753e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
754d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    DataSource::RegisterDefaultSniffers();
755d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
756d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<DataSource> dataSource =
757d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        DataSource::CreateFromURI(
758d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                "/system/etc/inception_1500.mp4");
759d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
760d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK(dataSource != NULL);
761d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
762d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
763d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK(extractor != NULL);
764d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
765d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    bool haveAudio = false;
766d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    bool haveVideo = false;
767d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    for (size_t i = 0; i < extractor->countTracks(); ++i) {
768d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        sp<MetaData> meta = extractor->getTrackMetaData(i);
769d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
770d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const char *mime;
771d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        CHECK(meta->findCString(kKeyMIMEType, &mime));
772d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
773d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        bool useTrack = false;
774d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (!strncasecmp(mime, "audio/", 6) && !haveAudio) {
775d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            useTrack = true;
776d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            haveAudio = true;
777d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        } else if (!strncasecmp(mime, "video/", 6) && !haveVideo) {
778d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            useTrack = true;
779d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            haveVideo = true;
780d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
781d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
782d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (!useTrack) {
783d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            continue;
784d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
785d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
786d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        sp<MediaSource> source = extractor->getTrack(i);
787d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
788d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        ssize_t index = mSerializer->addSource(source);
789d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        CHECK_GE(index, 0);
790d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
791d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        sp<AMessage> format;
792d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        status_t err = convertMetaDataToMessage(source->getFormat(), &format);
793d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        CHECK_EQ(err, (status_t)OK);
794d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
795d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mTracks.add(index, new Track(format));
796d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
797d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK(haveAudio || haveVideo);
798e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber#endif
799d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
800e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return OK;
801e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber}
802d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
803e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::addSource(
804e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        bool isVideo, const sp<MediaSource> &source, size_t *numInputBuffers) {
805e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber#if USE_SERIALIZER
806e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (mSerializer == NULL) {
807e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        mSerializerLooper = new ALooper;
808e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        mSerializerLooper->setName("serializer_looper");
809e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        mSerializerLooper->start();
810e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
811e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        sp<AMessage> msg = new AMessage(kWhatSerializerNotify, id());
812e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        mSerializer = new Serializer(
813e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                false /* throttled */, msg);
814e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
815e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        mSerializerLooper->registerHandler(mSerializer);
816e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
817d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#else
818e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<ALooper> pullLooper = new ALooper;
819e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    pullLooper->setName("pull_looper");
820e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
821e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    pullLooper->start(
822e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            false /* runOnCallingThread */,
823e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            false /* canCallJava */,
824e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            PRIORITY_DEFAULT);
825d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#endif
826d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
827e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<ALooper> codecLooper = new ALooper;
828e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    codecLooper->setName("codec_looper");
829e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
830e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    codecLooper->start(
831e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            false /* runOnCallingThread */,
832e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            false /* canCallJava */,
833e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            PRIORITY_DEFAULT);
834e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
835e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    size_t trackIndex;
836e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
837e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<AMessage> notify;
838e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
839e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber#if USE_SERIALIZER
840e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    trackIndex = mSerializer->addSource(source);
841e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber#else
842e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    trackIndex = mTracks.size();
843e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
844e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    notify = new AMessage(kWhatSerializerNotify, id());
845e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    notify->setSize("trackIndex", trackIndex);
846e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<MediaPuller> puller = new MediaPuller(source, notify);
847e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    pullLooper->registerHandler(puller);
848e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber#endif
849d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
850d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> format;
851d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    status_t err = convertMetaDataToMessage(source->getFormat(), &format);
852d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK_EQ(err, (status_t)OK);
853d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
854e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (isVideo) {
855e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        format->setInt32("store-metadata-in-buffers", true);
856d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
857e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        format->setInt32(
858e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                "color-format", OMX_COLOR_FormatAndroidOpaque);
859e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
860d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
861e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    notify = new AMessage(kWhatConverterNotify, id());
862e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    notify->setSize("trackIndex", trackIndex);
863d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
864d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<Converter> converter =
865e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        new Converter(notify, codecLooper, format);
86666e72bc85fb762876baff60ef29de729da93cf26Andreas Huber    CHECK_EQ(converter->initCheck(), (status_t)OK);
86766e72bc85fb762876baff60ef29de729da93cf26Andreas Huber
868d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    looper()->registerHandler(converter);
869d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
870e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (numInputBuffers != NULL) {
871e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        *numInputBuffers = converter->getInputBufferCount();
872e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
87366e72bc85fb762876baff60ef29de729da93cf26Andreas Huber
874e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber#if USE_SERIALIZER
875e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mTracks.add(trackIndex, new Track(NULL, codecLooper, NULL, converter));
876e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber#else
877e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mTracks.add(trackIndex, new Track(pullLooper, codecLooper, puller, converter));
878e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber#endif
879e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
880e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (isVideo) {
881e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        mVideoTrackIndex = trackIndex;
882e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
883e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
884e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return OK;
885e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber}
886e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
887e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::addVideoSource() {
888e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<SurfaceMediaSource> source = new SurfaceMediaSource(width(), height());
889e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
890e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<MediaSource> videoSource =
891e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            new RepeaterSource(source, 30.0 /* rateHz */);
892e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
893e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    size_t numInputBuffers;
894e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    status_t err = addSource(true /* isVideo */, videoSource, &numInputBuffers);
895e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
896e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (err != OK) {
897e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        return err;
898e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
89966e72bc85fb762876baff60ef29de729da93cf26Andreas Huber
90066e72bc85fb762876baff60ef29de729da93cf26Andreas Huber    // Add one reference to account for the serializer.
9015a832f87b680ead3606c4448a0a82c0e556d1b93Andreas Huber    err = source->setMaxAcquiredBufferCount(numInputBuffers);
90266e72bc85fb762876baff60ef29de729da93cf26Andreas Huber    CHECK_EQ(err, (status_t)OK);
90366e72bc85fb762876baff60ef29de729da93cf26Andreas Huber
9040b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber    mBufferQueue = source->getBufferQueue();
9050b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber
9060b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber    if (mLegacyMode) {
907e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        sp<IServiceManager> sm = defaultServiceManager();
908e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        sp<IBinder> binder = sm->getService(String16("SurfaceFlinger"));
909e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        sp<ISurfaceComposer> service = interface_cast<ISurfaceComposer>(binder);
910e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        CHECK(service != NULL);
911e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
9120b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber        service->connectDisplay(mBufferQueue);
9130b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber    }
914d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
915e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return OK;
916e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber}
917e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
918e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::addAudioSource() {
919082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber    sp<AudioSource> audioSource = new AudioSource(
9201646a0fed94c30a44128b3c379736def4b332033Andreas Huber            AUDIO_SOURCE_REMOTE_SUBMIX,
921082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber            48000 /* sampleRate */,
9221646a0fed94c30a44128b3c379736def4b332033Andreas Huber            2 /* channelCount */);
923082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber
9247977e85f7287f2b0e7a5de94e853e6073736e03bAndreas Huber    if (audioSource->initCheck() == OK) {
9257977e85f7287f2b0e7a5de94e853e6073736e03bAndreas Huber        audioSource->setUseLooperTime(true);
926082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber
927e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        return addSource(
928e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                false /* isVideo */, audioSource, NULL /* numInputBuffers */);
9297977e85f7287f2b0e7a5de94e853e6073736e03bAndreas Huber    }
930e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
931e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    ALOGW("Unable to instantiate audio source");
932082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber
933d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
934d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
935d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
9360b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Hubersp<ISurfaceTexture> WifiDisplaySource::PlaybackSession::getSurfaceTexture() {
9370b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber    return mBufferQueue;
9380b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber}
9390b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber
9400b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huberint32_t WifiDisplaySource::PlaybackSession::width() const {
9417977e85f7287f2b0e7a5de94e853e6073736e03bAndreas Huber    return mLegacyMode ? 720 : 1280;
9420b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber}
9430b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber
9440b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huberint32_t WifiDisplaySource::PlaybackSession::height() const {
9457977e85f7287f2b0e7a5de94e853e6073736e03bAndreas Huber    return mLegacyMode ? 1280 : 720;
9460b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber}
9470b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber
948d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::scheduleSendSR() {
949d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mSendSRPending) {
950d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return;
951d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
952d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
953d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mSendSRPending = true;
954d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    (new AMessage(kWhatSendSR, id()))->post(kSendSRIntervalUs);
955d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
956d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
957d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::addSR(const sp<ABuffer> &buffer) {
958d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint8_t *data = buffer->data() + buffer->size();
959d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
960d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    // TODO: Use macros/utility functions to clean up all the bitshifts below.
961d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
962d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[0] = 0x80 | 0;
963d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[1] = 200;  // SR
964d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[2] = 0;
965d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[3] = 6;
966d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[4] = kSourceID >> 24;
967d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[5] = (kSourceID >> 16) & 0xff;
968d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[6] = (kSourceID >> 8) & 0xff;
969d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[7] = kSourceID & 0xff;
970d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
971d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[8] = mLastNTPTime >> (64 - 8);
972d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[9] = (mLastNTPTime >> (64 - 16)) & 0xff;
973d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[10] = (mLastNTPTime >> (64 - 24)) & 0xff;
974d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[11] = (mLastNTPTime >> 32) & 0xff;
975d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[12] = (mLastNTPTime >> 24) & 0xff;
976d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[13] = (mLastNTPTime >> 16) & 0xff;
977d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[14] = (mLastNTPTime >> 8) & 0xff;
978d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[15] = mLastNTPTime & 0xff;
979d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
980d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[16] = (mLastRTPTime >> 24) & 0xff;
981d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[17] = (mLastRTPTime >> 16) & 0xff;
982d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[18] = (mLastRTPTime >> 8) & 0xff;
983d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[19] = mLastRTPTime & 0xff;
984d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
985d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[20] = mNumRTPSent >> 24;
986d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[21] = (mNumRTPSent >> 16) & 0xff;
987d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[22] = (mNumRTPSent >> 8) & 0xff;
988d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[23] = mNumRTPSent & 0xff;
989d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
990d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[24] = mNumRTPOctetsSent >> 24;
991d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[25] = (mNumRTPOctetsSent >> 16) & 0xff;
992d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[26] = (mNumRTPOctetsSent >> 8) & 0xff;
993d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[27] = mNumRTPOctetsSent & 0xff;
994d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
995d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    buffer->setRange(buffer->offset(), buffer->size() + 28);
996d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
997d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
998d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::addSDES(const sp<ABuffer> &buffer) {
999d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint8_t *data = buffer->data() + buffer->size();
1000d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[0] = 0x80 | 1;
1001d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[1] = 202;  // SDES
1002d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[4] = kSourceID >> 24;
1003d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[5] = (kSourceID >> 16) & 0xff;
1004d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[6] = (kSourceID >> 8) & 0xff;
1005d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[7] = kSourceID & 0xff;
1006d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1007d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    size_t offset = 8;
1008d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1009d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = 1;  // CNAME
1010d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1011d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    static const char *kCNAME = "someone@somewhere";
1012d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = strlen(kCNAME);
1013d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1014d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    memcpy(&data[offset], kCNAME, strlen(kCNAME));
1015d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    offset += strlen(kCNAME);
1016d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1017d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = 7;  // NOTE
1018d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1019d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    static const char *kNOTE = "Hell's frozen over.";
1020d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = strlen(kNOTE);
1021d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1022d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    memcpy(&data[offset], kNOTE, strlen(kNOTE));
1023d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    offset += strlen(kNOTE);
1024d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1025d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = 0;
1026d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1027d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if ((offset % 4) > 0) {
1028d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        size_t count = 4 - (offset % 4);
1029d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        switch (count) {
1030d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 3:
1031d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                data[offset++] = 0;
1032d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 2:
1033d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                data[offset++] = 0;
1034d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 1:
1035d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                data[offset++] = 0;
1036d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1037d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1038d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1039d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    size_t numWords = (offset / 4) - 1;
1040d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[2] = numWords >> 8;
1041d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[3] = numWords & 0xff;
1042d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1043d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    buffer->setRange(buffer->offset(), buffer->size() + offset);
1044d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1045d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1046d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber// static
1047d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberuint64_t WifiDisplaySource::PlaybackSession::GetNowNTP() {
1048d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint64_t nowUs = ALooper::GetNowUs();
1049d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1050d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll;
1051d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1052d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint64_t hi = nowUs / 1000000ll;
1053d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint64_t lo = ((1ll << 32) * (nowUs % 1000000ll)) / 1000000ll;
1054d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1055d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return (hi << 32) | lo;
1056d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1057d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1058d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::onSendSR() {
1059d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<ABuffer> buffer = new ABuffer(1500);
1060d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    buffer->setRange(0, 0);
1061d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1062d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    addSR(buffer);
1063d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    addSDES(buffer);
1064d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1065bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mTransportMode == TRANSPORT_TCP_INTERLEAVED) {
1066d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        sp<AMessage> notify = mNotify->dup();
1067d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        notify->setInt32("what", kWhatBinaryData);
1068d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        notify->setInt32("channel", mRTCPChannel);
1069d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        notify->setBuffer("data", buffer);
1070d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        notify->post();
1071d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    } else {
1072bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        sendPacket(mRTCPSessionID, buffer->data(), buffer->size());
1073d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1074d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1075d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    ++mNumSRsSent;
1076d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1077d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1078d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberssize_t WifiDisplaySource::PlaybackSession::appendTSData(
1079d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const void *data, size_t size, bool timeDiscontinuity, bool flush) {
1080d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK_EQ(size, 188);
1081d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1082d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK_LE(mTSQueue->size() + size, mTSQueue->capacity());
1083d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1084d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    memcpy(mTSQueue->data() + mTSQueue->size(), data, size);
1085d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mTSQueue->setRange(0, mTSQueue->size() + size);
1086d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1087d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (flush || mTSQueue->size() == mTSQueue->capacity()) {
1088d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        // flush
1089d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1090d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        int64_t nowUs = ALooper::GetNowUs();
1091d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (mFirstPacketTimeUs < 0ll) {
1092d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mFirstPacketTimeUs = nowUs;
1093d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1094d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1095d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        // 90kHz time scale
1096d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        uint32_t rtpTime = ((nowUs - mFirstPacketTimeUs) * 9ll) / 100ll;
1097d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1098d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        uint8_t *rtp = mTSQueue->data();
1099d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[0] = 0x80;
1100d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[1] = 33 | (timeDiscontinuity ? (1 << 7) : 0);  // M-bit
1101d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[2] = (mRTPSeqNo >> 8) & 0xff;
1102d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[3] = mRTPSeqNo & 0xff;
1103d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[4] = rtpTime >> 24;
1104d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[5] = (rtpTime >> 16) & 0xff;
1105d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[6] = (rtpTime >> 8) & 0xff;
1106d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[7] = rtpTime & 0xff;
1107d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[8] = kSourceID >> 24;
1108d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[9] = (kSourceID >> 16) & 0xff;
1109d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[10] = (kSourceID >> 8) & 0xff;
1110d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[11] = kSourceID & 0xff;
1111d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1112d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        ++mRTPSeqNo;
1113d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        ++mNumRTPSent;
1114d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mNumRTPOctetsSent += mTSQueue->size() - 12;
1115d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1116d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mLastRTPTime = rtpTime;
1117d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mLastNTPTime = GetNowNTP();
1118d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1119bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        if (mTransportMode == TRANSPORT_TCP_INTERLEAVED) {
1120d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            sp<AMessage> notify = mNotify->dup();
1121d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            notify->setInt32("what", kWhatBinaryData);
1122d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1123d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            sp<ABuffer> data = new ABuffer(mTSQueue->size());
1124d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            memcpy(data->data(), rtp, mTSQueue->size());
1125d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1126d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            notify->setInt32("channel", mRTPChannel);
1127d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            notify->setBuffer("data", data);
1128d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            notify->post();
1129d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        } else {
1130bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            sendPacket(mRTPSessionID, rtp, mTSQueue->size());
1131dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber
1132dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber            mTotalBytesSent += mTSQueue->size();
1133dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber            int64_t delayUs = ALooper::GetNowUs() - mFirstPacketTimeUs;
1134dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber
1135dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber            if (delayUs > 0ll) {
1136dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber                ALOGV("approx. net bandwidth used: %.2f Mbit/sec",
1137dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber                        mTotalBytesSent * 8.0 / delayUs);
1138dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber            }
1139d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1140d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1141d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mTSQueue->setInt32Data(mRTPSeqNo - 1);
1142d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mHistory.push_back(mTSQueue);
1143d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        ++mHistoryLength;
1144d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1145d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (mHistoryLength > kMaxHistoryLength) {
1146d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mTSQueue = *mHistory.begin();
1147d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mHistory.erase(mHistory.begin());
1148d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1149d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            --mHistoryLength;
1150d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        } else {
1151d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mTSQueue = new ABuffer(12 + kMaxNumTSPacketsPerRTPPacket * 188);
1152d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1153d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1154d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mTSQueue->setRange(0, 12);
1155d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1156d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1157d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return size;
1158d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1159d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1160d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::parseRTCP(
1161d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const sp<ABuffer> &buffer) {
1162d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    const uint8_t *data = buffer->data();
1163d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    size_t size = buffer->size();
1164d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1165d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    while (size > 0) {
1166d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (size < 8) {
1167d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            // Too short to be a valid RTCP header
1168d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            return ERROR_MALFORMED;
1169d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1170d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1171d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if ((data[0] >> 6) != 2) {
1172d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            // Unsupported version.
1173d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            return ERROR_UNSUPPORTED;
1174d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1175d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1176d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (data[0] & 0x20) {
1177d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            // Padding present.
1178d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1179d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            size_t paddingLength = data[size - 1];
1180d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1181d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            if (paddingLength + 12 > size) {
1182d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                // If we removed this much padding we'd end up with something
1183d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                // that's too short to be a valid RTP header.
1184d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                return ERROR_MALFORMED;
1185d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
1186d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1187d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            size -= paddingLength;
1188d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1189d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1190d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        size_t headerLength = 4 * (data[2] << 8 | data[3]) + 4;
1191d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1192d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (size < headerLength) {
1193d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            // Only received a partial packet?
1194d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            return ERROR_MALFORMED;
1195d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1196d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1197d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        switch (data[1]) {
1198d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 200:
1199d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 201:  // RR
1200d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 202:  // SDES
1201d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 203:
1202d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 204:  // APP
1203d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
1204d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1205d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 205:  // TSFB (transport layer specific feedback)
1206d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                parseTSFB(data, headerLength);
1207d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
1208d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1209d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 206:  // PSFB (payload specific feedback)
1210d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                hexdump(data, headerLength);
1211d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
1212d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1213d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            default:
1214d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            {
1215d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ALOGW("Unknown RTCP packet type %u of size %d",
1216d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                     (unsigned)data[1], headerLength);
1217d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
1218d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
1219d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1220d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1221d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        data += headerLength;
1222d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        size -= headerLength;
1223d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1224d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1225d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
1226d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1227d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1228d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::parseTSFB(
1229d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const uint8_t *data, size_t size) {
1230d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if ((data[0] & 0x1f) != 1) {
1231d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return ERROR_UNSUPPORTED;  // We only support NACK for now.
1232d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1233d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1234d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint32_t srcId = U32_AT(&data[8]);
1235d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (srcId != kSourceID) {
1236d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return ERROR_MALFORMED;
1237d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1238d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1239d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    for (size_t i = 12; i < size; i += 4) {
1240d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        uint16_t seqNo = U16_AT(&data[i]);
1241d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        uint16_t blp = U16_AT(&data[i + 2]);
1242d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1243d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        List<sp<ABuffer> >::iterator it = mHistory.begin();
1244d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        bool found = false;
1245d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        while (it != mHistory.end()) {
1246d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            const sp<ABuffer> &buffer = *it;
1247d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1248d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            uint16_t bufferSeqNo = buffer->int32Data() & 0xffff;
1249d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1250d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            if (bufferSeqNo == seqNo) {
1251bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                sendPacket(mRTPSessionID, buffer->data(), buffer->size());
1252d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1253d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                found = true;
1254d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
1255d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
1256d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1257d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            ++it;
1258d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1259d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1260d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (found) {
1261d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            ALOGI("retransmitting seqNo %d", seqNo);
1262d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        } else {
1263d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            ALOGI("seqNo %d no longer available", seqNo);
1264d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1265d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1266d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1267d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
1268d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1269d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1270496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Hubervoid WifiDisplaySource::PlaybackSession::requestIDRFrame() {
1271496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber    for (size_t i = 0; i < mTracks.size(); ++i) {
1272496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber        const sp<Track> &track = mTracks.valueAt(i);
1273496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber
1274496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber        track->converter()->requestIDRFrame();
1275496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber    }
1276496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber}
1277496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber
1278bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::sendPacket(
1279bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        int32_t sessionID, const void *data, size_t size) {
1280bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    return mNetSession->sendRequest(sessionID, data, size);
1281bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber}
1282bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
1283d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}  // namespace android
1284d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1285