PlaybackSession.cpp revision efd9c63dc846dd3dea2c979fe2a9d6770e73f9ac
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>
32b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber#include <media/IHDCP.h>
33d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/foundation/ABuffer.h>
34d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/foundation/ADebug.h>
35d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/foundation/AMessage.h>
36d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/foundation/hexdump.h>
37082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber#include <media/stagefright/AudioSource.h>
38d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/DataSource.h>
39d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MediaDefs.h>
40d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MediaErrors.h>
41d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MediaExtractor.h>
42d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MediaSource.h>
43d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MetaData.h>
44d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MPEG2TSWriter.h>
45d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/SurfaceMediaSource.h>
46d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/Utils.h>
47d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
48d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <OMX_IVCommon.h>
49d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
50bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber//#define FAKE_VIDEO            1
51bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber#define USE_SERIALIZER          0
52d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
53d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubernamespace android {
54d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
55d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatic size_t kMaxRTPPacketSize = 1500;
56d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatic size_t kMaxNumTSPacketsPerRTPPacket = (kMaxRTPPacketSize - 12) / 188;
57d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
58d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstruct WifiDisplaySource::PlaybackSession::Track : public RefBase {
59e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    Track(const sp<ALooper> &pullLooper,
60e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber          const sp<ALooper> &codecLooper,
61e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber          const sp<MediaPuller> &mediaPuller,
62e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber          const sp<Converter> &converter);
63e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
64d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    Track(const sp<AMessage> &format);
65d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
66d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> getFormat();
67b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber    bool isAudio() const;
68d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
69d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    const sp<Converter> &converter() const;
70d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    ssize_t packetizerTrackIndex() const;
71d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
72d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    void setPacketizerTrackIndex(size_t index);
73d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
74e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    status_t start();
75e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    status_t stop();
76e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
77d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberprotected:
78d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    virtual ~Track();
79d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
80d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberprivate:
81e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<ALooper> mPullLooper;
82e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<ALooper> mCodecLooper;
83e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<MediaPuller> mMediaPuller;
84d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<Converter> mConverter;
85d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> mFormat;
86e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    bool mStarted;
87d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    ssize_t mPacketizerTrackIndex;
88b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber    bool mIsAudio;
89b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
90b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber    static bool IsAudioFormat(const sp<AMessage> &format);
91d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
92d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    DISALLOW_EVIL_CONSTRUCTORS(Track);
93d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber};
94d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
95e1957358f11031a554c57d4fb46988dd6044acc1Andreas HuberWifiDisplaySource::PlaybackSession::Track::Track(
96e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        const sp<ALooper> &pullLooper,
97e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        const sp<ALooper> &codecLooper,
98e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        const sp<MediaPuller> &mediaPuller,
99e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        const sp<Converter> &converter)
100e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    : mPullLooper(pullLooper),
101e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber      mCodecLooper(codecLooper),
102e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber      mMediaPuller(mediaPuller),
103e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber      mConverter(converter),
104e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber      mStarted(false),
105b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber      mPacketizerTrackIndex(-1),
106b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber      mIsAudio(IsAudioFormat(mConverter->getOutputFormat())) {
107d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
108d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
109d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas HuberWifiDisplaySource::PlaybackSession::Track::Track(const sp<AMessage> &format)
110d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    : mFormat(format),
111b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber      mPacketizerTrackIndex(-1),
112b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber      mIsAudio(IsAudioFormat(mFormat)) {
113d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
114d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
115d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas HuberWifiDisplaySource::PlaybackSession::Track::~Track() {
116e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    stop();
117d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
118d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
119b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber// static
120b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huberbool WifiDisplaySource::PlaybackSession::Track::IsAudioFormat(
121b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber        const sp<AMessage> &format) {
122b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber    AString mime;
123b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber    CHECK(format->findString("mime", &mime));
124b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
125b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber    return !strncasecmp(mime.c_str(), "audio/", 6);
126b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber}
127b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
128d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubersp<AMessage> WifiDisplaySource::PlaybackSession::Track::getFormat() {
129d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mFormat != NULL) {
130d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return mFormat;
131d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
132d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
133d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mConverter->getOutputFormat();
134d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
135d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
136b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huberbool WifiDisplaySource::PlaybackSession::Track::isAudio() const {
137b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber    return mIsAudio;
138b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber}
139b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
140d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberconst sp<Converter> &WifiDisplaySource::PlaybackSession::Track::converter() const {
141d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mConverter;
142d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
143d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
144d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberssize_t WifiDisplaySource::PlaybackSession::Track::packetizerTrackIndex() const {
145d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mPacketizerTrackIndex;
146d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
147d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
148d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::Track::setPacketizerTrackIndex(size_t index) {
149d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK_LT(mPacketizerTrackIndex, 0);
150d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mPacketizerTrackIndex = index;
151d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
152d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
153e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::Track::start() {
154e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (mStarted) {
155e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        return INVALID_OPERATION;
156e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
157e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
158e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    status_t err = OK;
159e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
160e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (mMediaPuller != NULL) {
161e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        err = mMediaPuller->start();
162e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
163e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
164e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (err == OK) {
165e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        mStarted = true;
166e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
167e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
168e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return err;
169e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber}
170e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
171e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::Track::stop() {
172e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (!mStarted) {
173e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        return INVALID_OPERATION;
174e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
175e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
176e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    status_t err = OK;
177e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
178e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (mMediaPuller != NULL) {
179e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        err = mMediaPuller->stop();
180e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
181e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
182a438123bd96c7faf145683876702387efe5628d9Andreas Huber    mConverter.clear();
183a438123bd96c7faf145683876702387efe5628d9Andreas Huber
184e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mStarted = false;
185e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
186e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return err;
187e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber}
188e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
189d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber////////////////////////////////////////////////////////////////////////////////
190d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
191d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas HuberWifiDisplaySource::PlaybackSession::PlaybackSession(
192d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const sp<ANetworkSession> &netSession,
1930b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber        const sp<AMessage> &notify,
194bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        const in_addr &interfaceAddr,
195b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber        bool legacyMode,
196b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber        const sp<IHDCP> &hdcp)
197d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    : mNetSession(netSession),
198d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mNotify(notify),
199bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber      mInterfaceAddr(interfaceAddr),
2000b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber      mLegacyMode(legacyMode),
201b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber      mHDCP(hdcp),
202d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mLastLifesignUs(),
203e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber      mVideoTrackIndex(-1),
204d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mTSQueue(new ABuffer(12 + kMaxNumTSPacketsPerRTPPacket * 188)),
205d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mPrevTimeUs(-1ll),
206bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber      mTransportMode(TRANSPORT_UDP),
207d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTPChannel(0),
208d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTCPChannel(0),
209d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTPPort(0),
210d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTPSessionID(0),
211d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTCPSessionID(0),
212efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
213efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber      mRTPRetransmissionSessionID(0),
214efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber      mRTCPRetransmissionSessionID(0),
215efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
216bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber      mClientRTPPort(0),
217bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber      mClientRTCPPort(0),
218bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber      mRTPConnected(false),
219bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber      mRTCPConnected(false),
220d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTPSeqNo(0),
221efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
222efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber      mRTPRetransmissionSeqNo(0),
223efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
224d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mLastNTPTime(0),
225d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mLastRTPTime(0),
226d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mNumRTPSent(0),
227d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mNumRTPOctetsSent(0),
228d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mNumSRsSent(0),
229d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mSendSRPending(false),
230d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mFirstPacketTimeUs(-1ll),
231dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber      mHistoryLength(0),
232dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber      mTotalBytesSent(0ll)
233774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#if LOG_TRANSPORT_STREAM
234774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber      ,mLogFile(NULL)
235774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#endif
236774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber{
237d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mTSQueue->setRange(0, 12);
238774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber
239774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#if LOG_TRANSPORT_STREAM
240774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber    mLogFile = fopen("/system/etc/log.ts", "wb");
241774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#endif
242d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
243d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
244d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::init(
245d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const char *clientIP, int32_t clientRtp, int32_t clientRtcp,
246bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        TransportMode transportMode) {
247bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    mClientIP = clientIP;
248bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
249d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    status_t err = setupPacketizer();
250d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
251d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (err != OK) {
252d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return err;
253d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
254d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
255bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    mTransportMode = transportMode;
256bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
257bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (transportMode == TRANSPORT_TCP_INTERLEAVED) {
258d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTPChannel = clientRtp;
259d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTCPChannel = clientRtcp;
260d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTPPort = 0;
261d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTPSessionID = 0;
262d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTCPSessionID = 0;
263d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
264d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        updateLiveness();
265d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return OK;
266d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
267d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
268d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mRTPChannel = 0;
269d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mRTCPChannel = 0;
270d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
271bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mTransportMode == TRANSPORT_TCP) {
272bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        // XXX This is wrong, we need to allocate sockets here, we only
273bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        // need to do this because the dongles are not establishing their
274bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        // end until after PLAY instead of before SETUP.
275bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        mRTPPort = 20000;
276bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        mRTPSessionID = 0;
277bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        mRTCPSessionID = 0;
278bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        mClientRTPPort = clientRtp;
279bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        mClientRTCPPort = clientRtcp;
280bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
281bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        updateLiveness();
282bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        return OK;
283bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    }
284bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
285d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    int serverRtp;
286d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
287d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> rtpNotify = new AMessage(kWhatRTPNotify, id());
288d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> rtcpNotify = new AMessage(kWhatRTCPNotify, id());
289efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
290efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
291efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber    sp<AMessage> rtpRetransmissionNotify =
292efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        new AMessage(kWhatRTPRetransmissionNotify, id());
293efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
294efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber    sp<AMessage> rtcpRetransmissionNotify =
295efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        new AMessage(kWhatRTCPRetransmissionNotify, id());
296efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
297efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
298d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    for (serverRtp = 15550;; serverRtp += 2) {
299d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        int32_t rtpSession;
300bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        if (mTransportMode == TRANSPORT_UDP) {
301bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            err = mNetSession->createUDPSession(
302bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        serverRtp, clientIP, clientRtp,
303bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        rtpNotify, &rtpSession);
304bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        } else {
305bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            err = mNetSession->createTCPDatagramSession(
306bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        serverRtp, clientIP, clientRtp,
307bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        rtpNotify, &rtpSession);
308bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        }
309d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
310d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (err != OK) {
311d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            ALOGI("failed to create RTP socket on port %d", serverRtp);
312d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            continue;
313d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
314d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
315efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        int32_t rtcpSession = 0;
316d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
317efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        if (clientRtcp >= 0) {
318efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            if (mTransportMode == TRANSPORT_UDP) {
319efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                err = mNetSession->createUDPSession(
320efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        serverRtp + 1, clientIP, clientRtcp,
321efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        rtcpNotify, &rtcpSession);
322efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            } else {
323efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                err = mNetSession->createTCPDatagramSession(
324efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        serverRtp + 1, clientIP, clientRtcp,
325efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        rtcpNotify, &rtcpSession);
326efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            }
327d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
328efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            if (err != OK) {
329efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                ALOGI("failed to create RTCP socket on port %d", serverRtp + 1);
330efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
331efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                mNetSession->destroySession(rtpSession);
332efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                continue;
333efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            }
334d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
335d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
336efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
337bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        if (mTransportMode == TRANSPORT_UDP) {
338efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            int32_t rtpRetransmissionSession;
339efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
340bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            err = mNetSession->createUDPSession(
341efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        serverRtp + kRetransmissionPortOffset,
342efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        clientIP,
343efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        clientRtp + kRetransmissionPortOffset,
344efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        rtpRetransmissionNotify,
345efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        &rtpRetransmissionSession);
346efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
347efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            if (err != OK) {
348efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                mNetSession->destroySession(rtcpSession);
349efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                mNetSession->destroySession(rtpSession);
350efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                continue;
351efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            }
352d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
353efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            CHECK_GE(clientRtcp, 0);
354d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
355efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            int32_t rtcpRetransmissionSession;
356efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            err = mNetSession->createUDPSession(
357efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        serverRtp + 1 + kRetransmissionPortOffset,
358efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        clientIP,
359efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        clientRtp + 1 + kRetransmissionPortOffset,
360efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        rtcpRetransmissionNotify,
361efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        &rtcpRetransmissionSession);
362efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
363efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            if (err != OK) {
364efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                mNetSession->destroySession(rtpRetransmissionSession);
365efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                mNetSession->destroySession(rtcpSession);
366efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                mNetSession->destroySession(rtpSession);
367efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                continue;
368efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            }
369efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
370efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            mRTPRetransmissionSessionID = rtpRetransmissionSession;
371efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            mRTCPRetransmissionSessionID = rtcpRetransmissionSession;
372efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
373efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            ALOGI("rtpRetransmissionSessionID = %d, "
374efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                  "rtcpRetransmissionSessionID = %d",
375efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                  rtpRetransmissionSession, rtcpRetransmissionSession);
376d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
377efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
378efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
379efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        mRTPPort = serverRtp;
380efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        mRTPSessionID = rtpSession;
381efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        mRTCPSessionID = rtcpSession;
382d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
383efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        ALOGI("rtpSessionID = %d, rtcpSessionID = %d", rtpSession, rtcpSession);
384efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        break;
385d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
386d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
387d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mRTPPort == 0) {
388d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return UNKNOWN_ERROR;
389d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
390d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
391d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    updateLiveness();
392d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
393d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
394d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
395d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
396d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas HuberWifiDisplaySource::PlaybackSession::~PlaybackSession() {
397774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#if LOG_TRANSPORT_STREAM
398774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber    if (mLogFile != NULL) {
399774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber        fclose(mLogFile);
400774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber        mLogFile = NULL;
401774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber    }
402774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#endif
403d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
404d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
405d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberint32_t WifiDisplaySource::PlaybackSession::getRTPPort() const {
406d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mRTPPort;
407d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
408d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
409d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberint64_t WifiDisplaySource::PlaybackSession::getLastLifesignUs() const {
410d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mLastLifesignUs;
411d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
412d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
413d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::updateLiveness() {
414d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mLastLifesignUs = ALooper::GetNowUs();
415d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
416d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
417d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::play() {
418d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    updateLiveness();
419d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
420bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    return OK;
421bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber}
422bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
423bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::finishPlay() {
424bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    // XXX Give the dongle 3 secs to bind its sockets.
425bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    (new AMessage(kWhatFinishPlay, id()))->post(3000000ll);
426bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    return OK;
427bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber}
428bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
429bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::onFinishPlay() {
430bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mTransportMode != TRANSPORT_TCP) {
431bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        return onFinishPlay2();
432bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    }
433bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
434bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    sp<AMessage> rtpNotify = new AMessage(kWhatRTPNotify, id());
435bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
436bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    status_t err = mNetSession->createTCPDatagramSession(
437bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                mRTPPort, mClientIP.c_str(), mClientRTPPort,
438bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                rtpNotify, &mRTPSessionID);
439bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
440bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (err != OK) {
441bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        return err;
442bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    }
443bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
444bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mClientRTCPPort >= 0) {
445bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        sp<AMessage> rtcpNotify = new AMessage(kWhatRTCPNotify, id());
446bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
447bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        err = mNetSession->createTCPDatagramSession(
448bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                mRTPPort + 1, mClientIP.c_str(), mClientRTCPPort,
449bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                rtcpNotify, &mRTCPSessionID);
450bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    }
451bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
452bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    return err;
453bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber}
454bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
455bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::onFinishPlay2() {
456d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mRTCPSessionID != 0) {
457d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        scheduleSendSR();
458d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
459d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
460e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (mSerializer != NULL) {
461e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        return mSerializer->start();
462e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
463e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
464e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    for (size_t i = 0; i < mTracks.size(); ++i) {
465e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        status_t err = mTracks.editValueAt(i)->start();
466e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
467e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        if (err != OK) {
468e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            for (size_t j = 0; j < i; ++j) {
469e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                mTracks.editValueAt(j)->stop();
470e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            }
471e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
472e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            return err;
473e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        }
474e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
475e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
476bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    sp<AMessage> notify = mNotify->dup();
477bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    notify->setInt32("what", kWhatSessionEstablished);
478bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    notify->post();
479bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
480e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return OK;
481d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
482d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
483d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::pause() {
484d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    updateLiveness();
485d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
486d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
487d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
488d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
489a438123bd96c7faf145683876702387efe5628d9Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::destroy() {
490a438123bd96c7faf145683876702387efe5628d9Andreas Huber    mTracks.clear();
491a438123bd96c7faf145683876702387efe5628d9Andreas Huber
492a438123bd96c7faf145683876702387efe5628d9Andreas Huber    mPacketizer.clear();
493a438123bd96c7faf145683876702387efe5628d9Andreas Huber
494a438123bd96c7faf145683876702387efe5628d9Andreas Huber    if (mSerializer != NULL) {
495a438123bd96c7faf145683876702387efe5628d9Andreas Huber        mSerializer->stop();
496a438123bd96c7faf145683876702387efe5628d9Andreas Huber
497a438123bd96c7faf145683876702387efe5628d9Andreas Huber        looper()->unregisterHandler(mSerializer->id());
498a438123bd96c7faf145683876702387efe5628d9Andreas Huber        mSerializer.clear();
499a438123bd96c7faf145683876702387efe5628d9Andreas Huber    }
500a438123bd96c7faf145683876702387efe5628d9Andreas Huber
501a438123bd96c7faf145683876702387efe5628d9Andreas Huber    mTracks.clear();
502a438123bd96c7faf145683876702387efe5628d9Andreas Huber
503a438123bd96c7faf145683876702387efe5628d9Andreas Huber    if (mSerializerLooper != NULL) {
504a438123bd96c7faf145683876702387efe5628d9Andreas Huber        mSerializerLooper->stop();
505a438123bd96c7faf145683876702387efe5628d9Andreas Huber        mSerializerLooper.clear();
506a438123bd96c7faf145683876702387efe5628d9Andreas Huber    }
507a438123bd96c7faf145683876702387efe5628d9Andreas Huber
508a438123bd96c7faf145683876702387efe5628d9Andreas Huber    if (mLegacyMode) {
509a438123bd96c7faf145683876702387efe5628d9Andreas Huber        sp<IServiceManager> sm = defaultServiceManager();
510a438123bd96c7faf145683876702387efe5628d9Andreas Huber        sp<IBinder> binder = sm->getService(String16("SurfaceFlinger"));
511a438123bd96c7faf145683876702387efe5628d9Andreas Huber        sp<ISurfaceComposer> service = interface_cast<ISurfaceComposer>(binder);
512a438123bd96c7faf145683876702387efe5628d9Andreas Huber        CHECK(service != NULL);
513a438123bd96c7faf145683876702387efe5628d9Andreas Huber
514a438123bd96c7faf145683876702387efe5628d9Andreas Huber        service->connectDisplay(NULL);
515a438123bd96c7faf145683876702387efe5628d9Andreas Huber    }
516a438123bd96c7faf145683876702387efe5628d9Andreas Huber
517efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
518efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber    if (mRTCPRetransmissionSessionID != 0) {
519efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        mNetSession->destroySession(mRTCPRetransmissionSessionID);
520efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber    }
521efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
522efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber    if (mRTPRetransmissionSessionID != 0) {
523efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        mNetSession->destroySession(mRTPRetransmissionSessionID);
524efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber    }
525efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
526efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
527a438123bd96c7faf145683876702387efe5628d9Andreas Huber    if (mRTCPSessionID != 0) {
528a438123bd96c7faf145683876702387efe5628d9Andreas Huber        mNetSession->destroySession(mRTCPSessionID);
529a438123bd96c7faf145683876702387efe5628d9Andreas Huber    }
530a438123bd96c7faf145683876702387efe5628d9Andreas Huber
531a438123bd96c7faf145683876702387efe5628d9Andreas Huber    if (mRTPSessionID != 0) {
532a438123bd96c7faf145683876702387efe5628d9Andreas Huber        mNetSession->destroySession(mRTPSessionID);
533a438123bd96c7faf145683876702387efe5628d9Andreas Huber    }
534a438123bd96c7faf145683876702387efe5628d9Andreas Huber
535a438123bd96c7faf145683876702387efe5628d9Andreas Huber    return OK;
536a438123bd96c7faf145683876702387efe5628d9Andreas Huber}
537a438123bd96c7faf145683876702387efe5628d9Andreas Huber
538d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::onMessageReceived(
539d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const sp<AMessage> &msg) {
540d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    switch (msg->what()) {
541d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        case kWhatRTPNotify:
542d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        case kWhatRTCPNotify:
543efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
544efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        case kWhatRTPRetransmissionNotify:
545efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        case kWhatRTCPRetransmissionNotify:
546efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
547d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        {
548d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            int32_t reason;
549d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            CHECK(msg->findInt32("reason", &reason));
550d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
551d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            switch (reason) {
552d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                case ANetworkSession::kWhatError:
553d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                {
554d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    int32_t sessionID;
555d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findInt32("sessionID", &sessionID));
556d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
557d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    int32_t err;
558d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findInt32("err", &err));
559d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
560d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    int32_t errorOccuredDuringSend;
561d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findInt32("send", &errorOccuredDuringSend));
562d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
563d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    AString detail;
564d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findString("detail", &detail));
565d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
566efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    if ((msg->what() == kWhatRTPNotify
567efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
568efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                            || msg->what() == kWhatRTPRetransmissionNotify
569efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
570efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        ) && !errorOccuredDuringSend) {
571d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        // This is ok, we don't expect to receive anything on
572d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        // the RTP socket.
573d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        break;
574d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
575d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
576d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    ALOGE("An error occurred during %s in session %d "
577d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          "(%d, '%s' (%s)).",
578d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          errorOccuredDuringSend ? "send" : "receive",
579d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          sessionID,
580d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          err,
581d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          detail.c_str(),
582d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          strerror(-err));
583d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
584d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    mNetSession->destroySession(sessionID);
585d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
586d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    if (sessionID == mRTPSessionID) {
587d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        mRTPSessionID = 0;
588d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    } else if (sessionID == mRTCPSessionID) {
589d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        mRTCPSessionID = 0;
590d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
591efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
592efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    else if (sessionID == mRTPRetransmissionSessionID) {
593efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        mRTPRetransmissionSessionID = 0;
594efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    } else if (sessionID == mRTCPRetransmissionSessionID) {
595efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        mRTCPRetransmissionSessionID = 0;
596efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    }
597efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
598d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
599d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    // Inform WifiDisplaySource of our premature death (wish).
600d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    sp<AMessage> notify = mNotify->dup();
601d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    notify->setInt32("what", kWhatSessionDead);
602d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    notify->post();
603d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    break;
604d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
605d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
606d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                case ANetworkSession::kWhatDatagram:
607d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                {
608d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    int32_t sessionID;
609d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findInt32("sessionID", &sessionID));
610d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
611d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    sp<ABuffer> data;
612d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findBuffer("data", &data));
613d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
614d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    status_t err;
615efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    if (msg->what() == kWhatRTCPNotify
616efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
617efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                            || msg->what() == kWhatRTCPRetransmissionNotify
618efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
619efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                       )
620efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    {
621d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        err = parseRTCP(data);
622d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
623d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    break;
624d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
625d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
626bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                case ANetworkSession::kWhatConnected:
627bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                {
628bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    CHECK_EQ(mTransportMode, TRANSPORT_TCP);
629bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
630bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    int32_t sessionID;
631bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    CHECK(msg->findInt32("sessionID", &sessionID));
632bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
633bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    if (sessionID == mRTPSessionID) {
634bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        CHECK(!mRTPConnected);
635bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        mRTPConnected = true;
636bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        ALOGI("RTP Session now connected.");
637bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    } else if (sessionID == mRTCPSessionID) {
638bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        CHECK(!mRTCPConnected);
639bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        mRTCPConnected = true;
640bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        ALOGI("RTCP Session now connected.");
641bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    } else {
642bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        TRESPASS();
643bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    }
644bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
645bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    if (mRTPConnected
646bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                            && (mClientRTCPPort < 0 || mRTCPConnected)) {
647bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        onFinishPlay2();
648bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    }
649bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    break;
650bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                }
651bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
652d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                default:
653d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    TRESPASS();
654d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
655d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
656d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
657d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
658d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        case kWhatSendSR:
659d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        {
660d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mSendSRPending = false;
661d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
662d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            if (mRTCPSessionID == 0) {
663d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
664d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
665d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
666d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            onSendSR();
667d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
668d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            scheduleSendSR();
669d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
670d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
671d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
672d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        case kWhatSerializerNotify:
673d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        {
674d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            int32_t what;
675d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            CHECK(msg->findInt32("what", &what));
676d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
677d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            if (what == Serializer::kWhatEOS) {
678d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ALOGI("input eos");
679d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
680d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                for (size_t i = 0; i < mTracks.size(); ++i) {
681d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#if FAKE_VIDEO
682d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    sp<AMessage> msg = new AMessage(kWhatConverterNotify, id());
683d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    msg->setInt32("what", Converter::kWhatEOS);
684d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    msg->setSize("trackIndex", i);
685d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    msg->post();
686d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#else
687d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    mTracks.valueAt(i)->converter()->signalEOS();
688d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#endif
689d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
690d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            } else {
691d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK_EQ(what, Serializer::kWhatAccessUnit);
692d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
693d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                size_t trackIndex;
694d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK(msg->findSize("trackIndex", &trackIndex));
695d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
696d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                sp<ABuffer> accessUnit;
697d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK(msg->findBuffer("accessUnit", &accessUnit));
698d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
699d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#if FAKE_VIDEO
700d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                int64_t timeUs;
701d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
702d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
703d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                void *mbuf;
704d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK(accessUnit->meta()->findPointer("mediaBuffer", &mbuf));
705d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
706d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ((MediaBuffer *)mbuf)->release();
707d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                mbuf = NULL;
708d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
709d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                sp<AMessage> msg = new AMessage(kWhatConverterNotify, id());
710d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                msg->setInt32("what", Converter::kWhatAccessUnit);
711d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                msg->setSize("trackIndex", trackIndex);
712d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                msg->setBuffer("accessUnit", accessUnit);
713d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                msg->post();
714d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#else
715d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                mTracks.valueFor(trackIndex)->converter()
716d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    ->feedAccessUnit(accessUnit);
717d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#endif
718d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
719d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
720d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
721d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
722d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        case kWhatConverterNotify:
723d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        {
724d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            int32_t what;
725d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            CHECK(msg->findInt32("what", &what));
726d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
727d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            size_t trackIndex;
728d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            CHECK(msg->findSize("trackIndex", &trackIndex));
729d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
730d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            if (what == Converter::kWhatAccessUnit) {
731d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                const sp<Track> &track = mTracks.valueFor(trackIndex);
732d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
733d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                uint32_t flags = 0;
734d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
735d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ssize_t packetizerTrackIndex = track->packetizerTrackIndex();
736d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                if (packetizerTrackIndex < 0) {
737d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    flags = TSPacketizer::EMIT_PAT_AND_PMT;
738d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
739d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    packetizerTrackIndex =
740d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        mPacketizer->addTrack(track->getFormat());
741d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
742d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    if (packetizerTrackIndex >= 0) {
743d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        track->setPacketizerTrackIndex(packetizerTrackIndex);
744d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
745d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
746d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
747d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                if (packetizerTrackIndex >= 0) {
748d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    sp<ABuffer> accessUnit;
749d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findBuffer("accessUnit", &accessUnit));
750d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
751b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                    bool isHDCPEncrypted = false;
752b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                    uint64_t inputCTR;
753b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                    uint8_t HDCP_private_data[16];
754b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                    if (mHDCP != NULL && !track->isAudio()) {
755b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        isHDCPEncrypted = true;
756b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
757b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        status_t err = mHDCP->encrypt(
758b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                                accessUnit->data(), accessUnit->size(),
759b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                                trackIndex  /* streamCTR */,
760b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                                &inputCTR,
761b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                                accessUnit->data());
762b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
763b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        if (err != OK) {
764b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            ALOGI("Failed to HDCP-encrypt media data (err %d)",
765b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                                  err);
766b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
767b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            // Inform WifiDisplaySource of our premature death
768b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            // (wish).
769b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            sp<AMessage> notify = mNotify->dup();
770b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            notify->setInt32("what", kWhatSessionDead);
771b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            notify->post();
772b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            break;
773b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        }
774b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
775b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        HDCP_private_data[0] = 0x00;
776b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
777b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        HDCP_private_data[1] =
778b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            (((trackIndex >> 30) & 3) << 1) | 1;
779b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
780b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        HDCP_private_data[2] = (trackIndex >> 22) & 0xff;
781b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
782b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        HDCP_private_data[3] =
783b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            (((trackIndex >> 15) & 0x7f) << 1) | 1;
784b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
785b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        HDCP_private_data[4] = (trackIndex >> 7) & 0xff;
786b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
787b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        HDCP_private_data[5] =
788b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            ((trackIndex & 0x7f) << 1) | 1;
789b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
790b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        HDCP_private_data[6] = 0x00;
791b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
792b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        HDCP_private_data[7] =
793b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            (((inputCTR >> 60) & 0x0f) << 1) | 1;
794b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
795b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        HDCP_private_data[8] = (inputCTR >> 52) & 0xff;
796b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
797b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        HDCP_private_data[9] =
798b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            (((inputCTR >> 45) & 0x7f) << 1) | 1;
799b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
800b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        HDCP_private_data[10] = (inputCTR >> 37) & 0xff;
801b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
802b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        HDCP_private_data[11] =
803b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            (((inputCTR >> 30) & 0x7f) << 1) | 1;
804b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
805b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        HDCP_private_data[12] = (inputCTR >> 22) & 0xff;
806b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
807b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        HDCP_private_data[13] =
808b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            (((inputCTR >> 15) & 0x7f) << 1) | 1;
809b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
810b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        HDCP_private_data[14] = (inputCTR >> 7) & 0xff;
811b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
812b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        HDCP_private_data[15] =
813b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            ((inputCTR & 0x7f) << 1) | 1;
814b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
815b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        flags |= TSPacketizer::IS_ENCRYPTED;
816b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                    }
817b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
818d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    int64_t timeUs;
819d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
820d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
821d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    if (mPrevTimeUs < 0ll || mPrevTimeUs + 100000ll >= timeUs) {
822d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        flags |= TSPacketizer::EMIT_PCR;
823d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        mPrevTimeUs = timeUs;
824d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
825d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
826d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    sp<ABuffer> packets;
827d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    mPacketizer->packetize(
828b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            packetizerTrackIndex, accessUnit, &packets, flags,
829b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            isHDCPEncrypted ? NULL : HDCP_private_data,
830b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            isHDCPEncrypted ? 0 : sizeof(HDCP_private_data));
831d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
832d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    for (size_t offset = 0;
833d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                            offset < packets->size(); offset += 188) {
834d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        bool lastTSPacket = (offset + 188 >= packets->size());
835d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
836e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                        // We're only going to flush video, audio packets are
837e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                        // much more frequent and would waste all that space
838e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                        // available in a full sized UDP packet.
839e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                        bool flush =
840e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                            lastTSPacket
841e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                                && ((ssize_t)trackIndex == mVideoTrackIndex);
842e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
843d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        appendTSData(
844d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                                packets->data() + offset,
845d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                                188,
846d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                                true /* timeDiscontinuity */,
847e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                                flush);
848d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
849774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber
850774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#if LOG_TRANSPORT_STREAM
851774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber                    if (mLogFile != NULL) {
852774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber                        fwrite(packets->data(), 1, packets->size(), mLogFile);
853774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber                    }
854774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#endif
855d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
856d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            } else if (what == Converter::kWhatEOS) {
857d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK_EQ(what, Converter::kWhatEOS);
858d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
859d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ALOGI("output EOS on track %d", trackIndex);
860d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
861d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ssize_t index = mTracks.indexOfKey(trackIndex);
862d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK_GE(index, 0);
863d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
864d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#if !FAKE_VIDEO
865d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                const sp<Converter> &converter =
866d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    mTracks.valueAt(index)->converter();
867d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                looper()->unregisterHandler(converter->id());
868d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#endif
869d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
870d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                mTracks.removeItemsAt(index);
871d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
872d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                if (mTracks.isEmpty()) {
873d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    ALOGI("Reached EOS");
874d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
875d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            } else {
876d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK_EQ(what, Converter::kWhatError);
877d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
878d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                status_t err;
879d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK(msg->findInt32("err", &err));
880d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
881d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ALOGE("converter signaled error %d", err);
882d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
883d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
884d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
885d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
886bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        case kWhatFinishPlay:
887bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        {
888bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            onFinishPlay();
889bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            break;
890bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        }
891bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
892d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        default:
893d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            TRESPASS();
894d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
895d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
896d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
897d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::setupPacketizer() {
898d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> msg = new AMessage(kWhatSerializerNotify, id());
899d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
900e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mPacketizer = new TSPacketizer;
901d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
902d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#if FAKE_VIDEO
903e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return addFakeSources();
904d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#else
905e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    status_t err = addVideoSource();
906d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
907e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (err != OK) {
908e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        return err;
909e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
910e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
911e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return addAudioSource();
912e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber#endif
913e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber}
914d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
915e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::addFakeSources() {
916d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#if FAKE_VIDEO
917e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mSerializerLooper = new ALooper;
918e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mSerializerLooper->setName("serializer_looper");
919e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mSerializerLooper->start();
920e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
921e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<AMessage> msg = new AMessage(kWhatSerializerNotify, id());
922e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mSerializer = new Serializer(
923e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            true /* throttled */, msg);
924e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
925e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mSerializerLooper->registerHandler(mSerializer);
926e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
927d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    DataSource::RegisterDefaultSniffers();
928d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
929d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<DataSource> dataSource =
930d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        DataSource::CreateFromURI(
931d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                "/system/etc/inception_1500.mp4");
932d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
933d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK(dataSource != NULL);
934d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
935d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
936d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK(extractor != NULL);
937d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
938d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    bool haveAudio = false;
939d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    bool haveVideo = false;
940d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    for (size_t i = 0; i < extractor->countTracks(); ++i) {
941d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        sp<MetaData> meta = extractor->getTrackMetaData(i);
942d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
943d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const char *mime;
944d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        CHECK(meta->findCString(kKeyMIMEType, &mime));
945d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
946d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        bool useTrack = false;
947d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (!strncasecmp(mime, "audio/", 6) && !haveAudio) {
948d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            useTrack = true;
949d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            haveAudio = true;
950d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        } else if (!strncasecmp(mime, "video/", 6) && !haveVideo) {
951d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            useTrack = true;
952d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            haveVideo = true;
953d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
954d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
955d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (!useTrack) {
956d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            continue;
957d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
958d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
959d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        sp<MediaSource> source = extractor->getTrack(i);
960d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
961d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        ssize_t index = mSerializer->addSource(source);
962d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        CHECK_GE(index, 0);
963d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
964d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        sp<AMessage> format;
965d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        status_t err = convertMetaDataToMessage(source->getFormat(), &format);
966d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        CHECK_EQ(err, (status_t)OK);
967d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
968d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mTracks.add(index, new Track(format));
969d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
970d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK(haveAudio || haveVideo);
971e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber#endif
972d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
973e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return OK;
974e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber}
975d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
976e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::addSource(
977e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        bool isVideo, const sp<MediaSource> &source, size_t *numInputBuffers) {
978e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber#if USE_SERIALIZER
979e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (mSerializer == NULL) {
980e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        mSerializerLooper = new ALooper;
981e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        mSerializerLooper->setName("serializer_looper");
982e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        mSerializerLooper->start();
983e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
984e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        sp<AMessage> msg = new AMessage(kWhatSerializerNotify, id());
985e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        mSerializer = new Serializer(
986e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                false /* throttled */, msg);
987e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
988e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        mSerializerLooper->registerHandler(mSerializer);
989e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
990d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#else
991e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<ALooper> pullLooper = new ALooper;
992e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    pullLooper->setName("pull_looper");
993e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
994e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    pullLooper->start(
995e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            false /* runOnCallingThread */,
996e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            false /* canCallJava */,
997e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            PRIORITY_DEFAULT);
998d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#endif
999d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1000e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<ALooper> codecLooper = new ALooper;
1001e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    codecLooper->setName("codec_looper");
1002e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
1003e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    codecLooper->start(
1004e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            false /* runOnCallingThread */,
1005e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            false /* canCallJava */,
1006e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            PRIORITY_DEFAULT);
1007e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
1008e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    size_t trackIndex;
1009e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
1010e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<AMessage> notify;
1011e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
1012e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber#if USE_SERIALIZER
1013e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    trackIndex = mSerializer->addSource(source);
1014e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber#else
1015e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    trackIndex = mTracks.size();
1016e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
1017e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    notify = new AMessage(kWhatSerializerNotify, id());
1018e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    notify->setSize("trackIndex", trackIndex);
1019e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<MediaPuller> puller = new MediaPuller(source, notify);
1020e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    pullLooper->registerHandler(puller);
1021e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber#endif
1022d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1023d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> format;
1024d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    status_t err = convertMetaDataToMessage(source->getFormat(), &format);
1025d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK_EQ(err, (status_t)OK);
1026d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1027e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (isVideo) {
1028e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        format->setInt32("store-metadata-in-buffers", true);
1029d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1030e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        format->setInt32(
1031e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                "color-format", OMX_COLOR_FormatAndroidOpaque);
1032e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
1033d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1034e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    notify = new AMessage(kWhatConverterNotify, id());
1035e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    notify->setSize("trackIndex", trackIndex);
1036d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1037d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<Converter> converter =
1038e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        new Converter(notify, codecLooper, format);
103966e72bc85fb762876baff60ef29de729da93cf26Andreas Huber    CHECK_EQ(converter->initCheck(), (status_t)OK);
104066e72bc85fb762876baff60ef29de729da93cf26Andreas Huber
1041d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    looper()->registerHandler(converter);
1042d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1043e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (numInputBuffers != NULL) {
1044e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        *numInputBuffers = converter->getInputBufferCount();
1045e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
104666e72bc85fb762876baff60ef29de729da93cf26Andreas Huber
1047e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber#if USE_SERIALIZER
1048e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mTracks.add(trackIndex, new Track(NULL, codecLooper, NULL, converter));
1049e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber#else
1050e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mTracks.add(trackIndex, new Track(pullLooper, codecLooper, puller, converter));
1051e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber#endif
1052e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
1053e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (isVideo) {
1054e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        mVideoTrackIndex = trackIndex;
1055e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
1056e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
1057e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return OK;
1058e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber}
1059e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
1060e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::addVideoSource() {
1061e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<SurfaceMediaSource> source = new SurfaceMediaSource(width(), height());
1062e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
1063e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<MediaSource> videoSource =
1064e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            new RepeaterSource(source, 30.0 /* rateHz */);
1065e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
1066e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    size_t numInputBuffers;
1067e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    status_t err = addSource(true /* isVideo */, videoSource, &numInputBuffers);
1068e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
1069e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (err != OK) {
1070e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        return err;
1071e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
107266e72bc85fb762876baff60ef29de729da93cf26Andreas Huber
107366e72bc85fb762876baff60ef29de729da93cf26Andreas Huber    // Add one reference to account for the serializer.
10745a832f87b680ead3606c4448a0a82c0e556d1b93Andreas Huber    err = source->setMaxAcquiredBufferCount(numInputBuffers);
107566e72bc85fb762876baff60ef29de729da93cf26Andreas Huber    CHECK_EQ(err, (status_t)OK);
107666e72bc85fb762876baff60ef29de729da93cf26Andreas Huber
10770b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber    mBufferQueue = source->getBufferQueue();
10780b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber
10790b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber    if (mLegacyMode) {
1080e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        sp<IServiceManager> sm = defaultServiceManager();
1081e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        sp<IBinder> binder = sm->getService(String16("SurfaceFlinger"));
1082e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        sp<ISurfaceComposer> service = interface_cast<ISurfaceComposer>(binder);
1083e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        CHECK(service != NULL);
1084e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
10850b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber        service->connectDisplay(mBufferQueue);
10860b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber    }
1087d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1088e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return OK;
1089e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber}
1090e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
1091e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::addAudioSource() {
1092082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber    sp<AudioSource> audioSource = new AudioSource(
10931646a0fed94c30a44128b3c379736def4b332033Andreas Huber            AUDIO_SOURCE_REMOTE_SUBMIX,
1094082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber            48000 /* sampleRate */,
10951646a0fed94c30a44128b3c379736def4b332033Andreas Huber            2 /* channelCount */);
1096082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber
10977977e85f7287f2b0e7a5de94e853e6073736e03bAndreas Huber    if (audioSource->initCheck() == OK) {
10987977e85f7287f2b0e7a5de94e853e6073736e03bAndreas Huber        audioSource->setUseLooperTime(true);
1099082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber
1100e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        return addSource(
1101e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                false /* isVideo */, audioSource, NULL /* numInputBuffers */);
11027977e85f7287f2b0e7a5de94e853e6073736e03bAndreas Huber    }
1103e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
1104e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    ALOGW("Unable to instantiate audio source");
1105082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber
1106d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
1107d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1108d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
11090b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Hubersp<ISurfaceTexture> WifiDisplaySource::PlaybackSession::getSurfaceTexture() {
11100b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber    return mBufferQueue;
11110b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber}
11120b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber
11130b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huberint32_t WifiDisplaySource::PlaybackSession::width() const {
11147977e85f7287f2b0e7a5de94e853e6073736e03bAndreas Huber    return mLegacyMode ? 720 : 1280;
11150b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber}
11160b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber
11170b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huberint32_t WifiDisplaySource::PlaybackSession::height() const {
11187977e85f7287f2b0e7a5de94e853e6073736e03bAndreas Huber    return mLegacyMode ? 1280 : 720;
11190b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber}
11200b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber
1121d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::scheduleSendSR() {
1122d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mSendSRPending) {
1123d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return;
1124d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1125d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1126d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mSendSRPending = true;
1127d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    (new AMessage(kWhatSendSR, id()))->post(kSendSRIntervalUs);
1128d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1129d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1130d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::addSR(const sp<ABuffer> &buffer) {
1131d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint8_t *data = buffer->data() + buffer->size();
1132d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1133d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    // TODO: Use macros/utility functions to clean up all the bitshifts below.
1134d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1135d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[0] = 0x80 | 0;
1136d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[1] = 200;  // SR
1137d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[2] = 0;
1138d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[3] = 6;
1139d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[4] = kSourceID >> 24;
1140d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[5] = (kSourceID >> 16) & 0xff;
1141d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[6] = (kSourceID >> 8) & 0xff;
1142d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[7] = kSourceID & 0xff;
1143d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1144d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[8] = mLastNTPTime >> (64 - 8);
1145d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[9] = (mLastNTPTime >> (64 - 16)) & 0xff;
1146d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[10] = (mLastNTPTime >> (64 - 24)) & 0xff;
1147d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[11] = (mLastNTPTime >> 32) & 0xff;
1148d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[12] = (mLastNTPTime >> 24) & 0xff;
1149d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[13] = (mLastNTPTime >> 16) & 0xff;
1150d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[14] = (mLastNTPTime >> 8) & 0xff;
1151d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[15] = mLastNTPTime & 0xff;
1152d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1153d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[16] = (mLastRTPTime >> 24) & 0xff;
1154d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[17] = (mLastRTPTime >> 16) & 0xff;
1155d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[18] = (mLastRTPTime >> 8) & 0xff;
1156d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[19] = mLastRTPTime & 0xff;
1157d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1158d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[20] = mNumRTPSent >> 24;
1159d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[21] = (mNumRTPSent >> 16) & 0xff;
1160d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[22] = (mNumRTPSent >> 8) & 0xff;
1161d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[23] = mNumRTPSent & 0xff;
1162d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1163d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[24] = mNumRTPOctetsSent >> 24;
1164d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[25] = (mNumRTPOctetsSent >> 16) & 0xff;
1165d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[26] = (mNumRTPOctetsSent >> 8) & 0xff;
1166d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[27] = mNumRTPOctetsSent & 0xff;
1167d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1168d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    buffer->setRange(buffer->offset(), buffer->size() + 28);
1169d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1170d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1171d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::addSDES(const sp<ABuffer> &buffer) {
1172d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint8_t *data = buffer->data() + buffer->size();
1173d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[0] = 0x80 | 1;
1174d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[1] = 202;  // SDES
1175d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[4] = kSourceID >> 24;
1176d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[5] = (kSourceID >> 16) & 0xff;
1177d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[6] = (kSourceID >> 8) & 0xff;
1178d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[7] = kSourceID & 0xff;
1179d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1180d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    size_t offset = 8;
1181d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1182d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = 1;  // CNAME
1183d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1184d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    static const char *kCNAME = "someone@somewhere";
1185d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = strlen(kCNAME);
1186d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1187d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    memcpy(&data[offset], kCNAME, strlen(kCNAME));
1188d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    offset += strlen(kCNAME);
1189d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1190d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = 7;  // NOTE
1191d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1192d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    static const char *kNOTE = "Hell's frozen over.";
1193d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = strlen(kNOTE);
1194d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1195d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    memcpy(&data[offset], kNOTE, strlen(kNOTE));
1196d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    offset += strlen(kNOTE);
1197d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1198d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = 0;
1199d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1200d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if ((offset % 4) > 0) {
1201d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        size_t count = 4 - (offset % 4);
1202d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        switch (count) {
1203d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 3:
1204d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                data[offset++] = 0;
1205d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 2:
1206d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                data[offset++] = 0;
1207d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 1:
1208d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                data[offset++] = 0;
1209d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1210d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1211d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1212d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    size_t numWords = (offset / 4) - 1;
1213d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[2] = numWords >> 8;
1214d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[3] = numWords & 0xff;
1215d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1216d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    buffer->setRange(buffer->offset(), buffer->size() + offset);
1217d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1218d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1219d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber// static
1220d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberuint64_t WifiDisplaySource::PlaybackSession::GetNowNTP() {
1221d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint64_t nowUs = ALooper::GetNowUs();
1222d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1223d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll;
1224d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1225d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint64_t hi = nowUs / 1000000ll;
1226d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint64_t lo = ((1ll << 32) * (nowUs % 1000000ll)) / 1000000ll;
1227d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1228d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return (hi << 32) | lo;
1229d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1230d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1231d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::onSendSR() {
1232d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<ABuffer> buffer = new ABuffer(1500);
1233d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    buffer->setRange(0, 0);
1234d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1235d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    addSR(buffer);
1236d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    addSDES(buffer);
1237d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1238bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mTransportMode == TRANSPORT_TCP_INTERLEAVED) {
1239d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        sp<AMessage> notify = mNotify->dup();
1240d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        notify->setInt32("what", kWhatBinaryData);
1241d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        notify->setInt32("channel", mRTCPChannel);
1242d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        notify->setBuffer("data", buffer);
1243d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        notify->post();
1244d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    } else {
1245bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        sendPacket(mRTCPSessionID, buffer->data(), buffer->size());
1246d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1247d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1248d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    ++mNumSRsSent;
1249d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1250d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1251d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberssize_t WifiDisplaySource::PlaybackSession::appendTSData(
1252d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const void *data, size_t size, bool timeDiscontinuity, bool flush) {
1253d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK_EQ(size, 188);
1254d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1255d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK_LE(mTSQueue->size() + size, mTSQueue->capacity());
1256d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1257d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    memcpy(mTSQueue->data() + mTSQueue->size(), data, size);
1258d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mTSQueue->setRange(0, mTSQueue->size() + size);
1259d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1260d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (flush || mTSQueue->size() == mTSQueue->capacity()) {
1261d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        // flush
1262d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1263d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        int64_t nowUs = ALooper::GetNowUs();
1264d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (mFirstPacketTimeUs < 0ll) {
1265d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mFirstPacketTimeUs = nowUs;
1266d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1267d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1268d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        // 90kHz time scale
1269d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        uint32_t rtpTime = ((nowUs - mFirstPacketTimeUs) * 9ll) / 100ll;
1270d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1271d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        uint8_t *rtp = mTSQueue->data();
1272d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[0] = 0x80;
1273d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[1] = 33 | (timeDiscontinuity ? (1 << 7) : 0);  // M-bit
1274d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[2] = (mRTPSeqNo >> 8) & 0xff;
1275d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[3] = mRTPSeqNo & 0xff;
1276d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[4] = rtpTime >> 24;
1277d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[5] = (rtpTime >> 16) & 0xff;
1278d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[6] = (rtpTime >> 8) & 0xff;
1279d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[7] = rtpTime & 0xff;
1280d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[8] = kSourceID >> 24;
1281d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[9] = (kSourceID >> 16) & 0xff;
1282d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[10] = (kSourceID >> 8) & 0xff;
1283d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[11] = kSourceID & 0xff;
1284d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1285d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        ++mRTPSeqNo;
1286d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        ++mNumRTPSent;
1287d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mNumRTPOctetsSent += mTSQueue->size() - 12;
1288d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1289d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mLastRTPTime = rtpTime;
1290d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mLastNTPTime = GetNowNTP();
1291d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1292bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        if (mTransportMode == TRANSPORT_TCP_INTERLEAVED) {
1293d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            sp<AMessage> notify = mNotify->dup();
1294d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            notify->setInt32("what", kWhatBinaryData);
1295d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1296d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            sp<ABuffer> data = new ABuffer(mTSQueue->size());
1297d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            memcpy(data->data(), rtp, mTSQueue->size());
1298d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1299d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            notify->setInt32("channel", mRTPChannel);
1300d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            notify->setBuffer("data", data);
1301d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            notify->post();
1302d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        } else {
1303bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            sendPacket(mRTPSessionID, rtp, mTSQueue->size());
1304dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber
1305dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber            mTotalBytesSent += mTSQueue->size();
1306dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber            int64_t delayUs = ALooper::GetNowUs() - mFirstPacketTimeUs;
1307dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber
1308dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber            if (delayUs > 0ll) {
1309dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber                ALOGV("approx. net bandwidth used: %.2f Mbit/sec",
1310dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber                        mTotalBytesSent * 8.0 / delayUs);
1311dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber            }
1312d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1313d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1314d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mTSQueue->setInt32Data(mRTPSeqNo - 1);
1315d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mHistory.push_back(mTSQueue);
1316d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        ++mHistoryLength;
1317d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1318d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (mHistoryLength > kMaxHistoryLength) {
1319d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mTSQueue = *mHistory.begin();
1320d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mHistory.erase(mHistory.begin());
1321d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1322d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            --mHistoryLength;
1323d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        } else {
1324d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mTSQueue = new ABuffer(12 + kMaxNumTSPacketsPerRTPPacket * 188);
1325d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1326d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1327d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mTSQueue->setRange(0, 12);
1328d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1329d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1330d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return size;
1331d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1332d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1333d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::parseRTCP(
1334d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const sp<ABuffer> &buffer) {
1335d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    const uint8_t *data = buffer->data();
1336d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    size_t size = buffer->size();
1337d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1338d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    while (size > 0) {
1339d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (size < 8) {
1340d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            // Too short to be a valid RTCP header
1341d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            return ERROR_MALFORMED;
1342d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1343d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1344d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if ((data[0] >> 6) != 2) {
1345d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            // Unsupported version.
1346d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            return ERROR_UNSUPPORTED;
1347d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1348d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1349d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (data[0] & 0x20) {
1350d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            // Padding present.
1351d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1352d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            size_t paddingLength = data[size - 1];
1353d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1354d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            if (paddingLength + 12 > size) {
1355d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                // If we removed this much padding we'd end up with something
1356d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                // that's too short to be a valid RTP header.
1357d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                return ERROR_MALFORMED;
1358d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
1359d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1360d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            size -= paddingLength;
1361d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1362d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1363d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        size_t headerLength = 4 * (data[2] << 8 | data[3]) + 4;
1364d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1365d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (size < headerLength) {
1366d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            // Only received a partial packet?
1367d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            return ERROR_MALFORMED;
1368d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1369d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1370d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        switch (data[1]) {
1371d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 200:
1372d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 201:  // RR
1373d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 202:  // SDES
1374d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 203:
1375d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 204:  // APP
1376d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
1377d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1378efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
1379d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 205:  // TSFB (transport layer specific feedback)
1380d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                parseTSFB(data, headerLength);
1381d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
1382efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
1383d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1384d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 206:  // PSFB (payload specific feedback)
1385d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                hexdump(data, headerLength);
1386d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
1387d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1388d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            default:
1389d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            {
1390d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ALOGW("Unknown RTCP packet type %u of size %d",
1391d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                     (unsigned)data[1], headerLength);
1392d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
1393d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
1394d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1395d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1396d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        data += headerLength;
1397d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        size -= headerLength;
1398d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1399d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1400d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
1401d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1402d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1403efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
1404d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::parseTSFB(
1405d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const uint8_t *data, size_t size) {
1406d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if ((data[0] & 0x1f) != 1) {
1407d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return ERROR_UNSUPPORTED;  // We only support NACK for now.
1408d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1409d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1410d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint32_t srcId = U32_AT(&data[8]);
1411d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (srcId != kSourceID) {
1412d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return ERROR_MALFORMED;
1413d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1414d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1415d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    for (size_t i = 12; i < size; i += 4) {
1416d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        uint16_t seqNo = U16_AT(&data[i]);
1417d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        uint16_t blp = U16_AT(&data[i + 2]);
1418d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1419d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        List<sp<ABuffer> >::iterator it = mHistory.begin();
1420efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        bool foundSeqNo = false;
1421d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        while (it != mHistory.end()) {
1422d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            const sp<ABuffer> &buffer = *it;
1423d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1424d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            uint16_t bufferSeqNo = buffer->int32Data() & 0xffff;
1425d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1426efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            bool retransmit = false;
1427d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            if (bufferSeqNo == seqNo) {
1428efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                retransmit = true;
1429efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            } else if (blp != 0) {
1430efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                for (size_t i = 0; i < 16; ++i) {
1431efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    if ((blp & (1 << i))
1432efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        && (bufferSeqNo == ((seqNo + i + 1) & 0xffff))) {
1433efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        blp &= ~(1 << i);
1434efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        retransmit = true;
1435efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    }
1436efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                }
1437efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            }
1438d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1439efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            if (retransmit) {
1440efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                ALOGI("retransmitting seqNo %d", bufferSeqNo);
1441efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
1442efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                sp<ABuffer> retransRTP = new ABuffer(2 + buffer->size());
1443efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                uint8_t *rtp = retransRTP->data();
1444efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                memcpy(rtp, buffer->data(), 12);
1445efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                rtp[2] = (mRTPRetransmissionSeqNo >> 8) & 0xff;
1446efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                rtp[3] = mRTPRetransmissionSeqNo & 0xff;
1447efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                rtp[12] = (bufferSeqNo >> 8) & 0xff;
1448efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                rtp[13] = bufferSeqNo & 0xff;
1449efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                memcpy(&rtp[14], buffer->data() + 12, buffer->size() - 12);
1450efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
1451efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                ++mRTPRetransmissionSeqNo;
1452efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
1453efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                sendPacket(
1454efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        mRTPRetransmissionSessionID,
1455efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        retransRTP->data(), retransRTP->size());
1456efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
1457efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                if (bufferSeqNo == seqNo) {
1458efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    foundSeqNo = true;
1459efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                }
1460efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
1461efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                if (foundSeqNo && blp == 0) {
1462efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    break;
1463efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                }
1464d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
1465d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1466d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            ++it;
1467d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1468d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1469efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        if (!foundSeqNo || blp != 0) {
1470efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            ALOGI("Some sequence numbers were no longer available for "
1471efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                  "retransmission");
1472d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1473d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1474d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1475d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
1476d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1477efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
1478d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1479496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Hubervoid WifiDisplaySource::PlaybackSession::requestIDRFrame() {
1480496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber    for (size_t i = 0; i < mTracks.size(); ++i) {
1481496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber        const sp<Track> &track = mTracks.valueAt(i);
1482496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber
1483496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber        track->converter()->requestIDRFrame();
1484496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber    }
1485496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber}
1486496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber
1487bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::sendPacket(
1488bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        int32_t sessionID, const void *data, size_t size) {
1489bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    return mNetSession->sendRequest(sessionID, data, size);
1490bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber}
1491bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
1492d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}  // namespace android
1493d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1494