PlaybackSession.cpp revision e399acc9d9f3b7af72106c4209e4bb40de37aa6a
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 "TSPacketizer.h"
27e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber#include "include/avc_utils.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>
33e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber#include <media/stagefright/foundation/ABitReader.h>
34d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/foundation/ABuffer.h>
35d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/foundation/ADebug.h>
36d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/foundation/AMessage.h>
37d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/foundation/hexdump.h>
38082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber#include <media/stagefright/AudioSource.h>
39d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/DataSource.h>
40d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MediaDefs.h>
41d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MediaErrors.h>
42d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MediaExtractor.h>
43d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MediaSource.h>
44d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MetaData.h>
45d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/MPEG2TSWriter.h>
46d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/SurfaceMediaSource.h>
47d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <media/stagefright/Utils.h>
48d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
49d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber#include <OMX_IVCommon.h>
50d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
51d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubernamespace android {
52d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
53d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatic size_t kMaxRTPPacketSize = 1500;
54d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatic size_t kMaxNumTSPacketsPerRTPPacket = (kMaxRTPPacketSize - 12) / 188;
55d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
56d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstruct WifiDisplaySource::PlaybackSession::Track : public RefBase {
57e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    Track(const sp<ALooper> &pullLooper,
58e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber          const sp<ALooper> &codecLooper,
59e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber          const sp<MediaPuller> &mediaPuller,
60e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber          const sp<Converter> &converter);
61e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
62d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    Track(const sp<AMessage> &format);
63d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
64d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> getFormat();
65b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber    bool isAudio() const;
66d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
67d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    const sp<Converter> &converter() const;
68d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    ssize_t packetizerTrackIndex() const;
69d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
70d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    void setPacketizerTrackIndex(size_t index);
71d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
72e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    status_t start();
73e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    status_t stop();
74e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
7528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    void queueAccessUnit(const sp<ABuffer> &accessUnit);
7628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    sp<ABuffer> dequeueAccessUnit();
7728e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
78d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberprotected:
79d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    virtual ~Track();
80d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
81d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberprivate:
82e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<ALooper> mPullLooper;
83e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<ALooper> mCodecLooper;
84e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<MediaPuller> mMediaPuller;
85d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<Converter> mConverter;
86d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> mFormat;
87e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    bool mStarted;
88d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    ssize_t mPacketizerTrackIndex;
89b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber    bool mIsAudio;
9028e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    List<sp<ABuffer> > mQueuedAccessUnits;
91b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
92b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber    static bool IsAudioFormat(const sp<AMessage> &format);
93d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
94d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    DISALLOW_EVIL_CONSTRUCTORS(Track);
95d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber};
96d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
97e1957358f11031a554c57d4fb46988dd6044acc1Andreas HuberWifiDisplaySource::PlaybackSession::Track::Track(
98e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        const sp<ALooper> &pullLooper,
99e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        const sp<ALooper> &codecLooper,
100e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        const sp<MediaPuller> &mediaPuller,
101e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        const sp<Converter> &converter)
102e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    : mPullLooper(pullLooper),
103e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber      mCodecLooper(codecLooper),
104e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber      mMediaPuller(mediaPuller),
105e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber      mConverter(converter),
106e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber      mStarted(false),
107b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber      mPacketizerTrackIndex(-1),
108b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber      mIsAudio(IsAudioFormat(mConverter->getOutputFormat())) {
109d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
110d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
111d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas HuberWifiDisplaySource::PlaybackSession::Track::Track(const sp<AMessage> &format)
112d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    : mFormat(format),
113b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber      mPacketizerTrackIndex(-1),
114b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber      mIsAudio(IsAudioFormat(mFormat)) {
115d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
116d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
117d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas HuberWifiDisplaySource::PlaybackSession::Track::~Track() {
118e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    stop();
119d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
120d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
121b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber// static
122b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huberbool WifiDisplaySource::PlaybackSession::Track::IsAudioFormat(
123b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber        const sp<AMessage> &format) {
124b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber    AString mime;
125b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber    CHECK(format->findString("mime", &mime));
126b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
127b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber    return !strncasecmp(mime.c_str(), "audio/", 6);
128b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber}
129b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
130d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubersp<AMessage> WifiDisplaySource::PlaybackSession::Track::getFormat() {
131d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mFormat != NULL) {
132d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return mFormat;
133d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
134d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
135d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mConverter->getOutputFormat();
136d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
137d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
138b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huberbool WifiDisplaySource::PlaybackSession::Track::isAudio() const {
139b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber    return mIsAudio;
140b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber}
141b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
142d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberconst sp<Converter> &WifiDisplaySource::PlaybackSession::Track::converter() const {
143d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mConverter;
144d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
145d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
146d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberssize_t WifiDisplaySource::PlaybackSession::Track::packetizerTrackIndex() const {
147d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mPacketizerTrackIndex;
148d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
149d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
150d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::Track::setPacketizerTrackIndex(size_t index) {
151d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK_LT(mPacketizerTrackIndex, 0);
152d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mPacketizerTrackIndex = index;
153d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
154d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
155e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::Track::start() {
156e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (mStarted) {
157e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        return INVALID_OPERATION;
158e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
159e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
160e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    status_t err = OK;
161e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
162e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (mMediaPuller != NULL) {
163e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        err = mMediaPuller->start();
164e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
165e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
166e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (err == OK) {
167e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        mStarted = true;
168e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
169e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
170e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return err;
171e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber}
172e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
173e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::Track::stop() {
174e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (!mStarted) {
175e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        return INVALID_OPERATION;
176e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
177e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
178e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    status_t err = OK;
179e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
180e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (mMediaPuller != NULL) {
181e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        err = mMediaPuller->stop();
182e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
183e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
184a438123bd96c7faf145683876702387efe5628d9Andreas Huber    mConverter.clear();
185a438123bd96c7faf145683876702387efe5628d9Andreas Huber
186e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mStarted = false;
187e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
188e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return err;
189e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber}
190e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
19128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Hubervoid WifiDisplaySource::PlaybackSession::Track::queueAccessUnit(
19228e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        const sp<ABuffer> &accessUnit) {
19328e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    mQueuedAccessUnits.push_back(accessUnit);
19428e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber}
19528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
19628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Hubersp<ABuffer> WifiDisplaySource::PlaybackSession::Track::dequeueAccessUnit() {
19728e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    if (mQueuedAccessUnits.empty()) {
19828e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        return NULL;
19928e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    }
20028e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
20128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    sp<ABuffer> accessUnit = *mQueuedAccessUnits.begin();
20228e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    CHECK(accessUnit != NULL);
20328e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
20428e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    mQueuedAccessUnits.erase(mQueuedAccessUnits.begin());
20528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
20628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    return accessUnit;
20728e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber}
20828e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
209d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber////////////////////////////////////////////////////////////////////////////////
210d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
211d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas HuberWifiDisplaySource::PlaybackSession::PlaybackSession(
212d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const sp<ANetworkSession> &netSession,
2130b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber        const sp<AMessage> &notify,
214bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        const in_addr &interfaceAddr,
215b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber        const sp<IHDCP> &hdcp)
216d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    : mNetSession(netSession),
217d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mNotify(notify),
218bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber      mInterfaceAddr(interfaceAddr),
219b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber      mHDCP(hdcp),
220d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mLastLifesignUs(),
221e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber      mVideoTrackIndex(-1),
222d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mTSQueue(new ABuffer(12 + kMaxNumTSPacketsPerRTPPacket * 188)),
223d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mPrevTimeUs(-1ll),
224bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber      mTransportMode(TRANSPORT_UDP),
22528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber      mAllTracksHavePacketizerIndex(false),
226d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTPChannel(0),
227d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTCPChannel(0),
228d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTPPort(0),
229d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTPSessionID(0),
230d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTCPSessionID(0),
231efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
232efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber      mRTPRetransmissionSessionID(0),
233efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber      mRTCPRetransmissionSessionID(0),
234efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
235bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber      mClientRTPPort(0),
236bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber      mClientRTCPPort(0),
237bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber      mRTPConnected(false),
238bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber      mRTCPConnected(false),
239d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mRTPSeqNo(0),
240efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
241efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber      mRTPRetransmissionSeqNo(0),
242efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
243d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mLastNTPTime(0),
244d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mLastRTPTime(0),
245d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mNumRTPSent(0),
246d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mNumRTPOctetsSent(0),
247d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mNumSRsSent(0),
248d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mSendSRPending(false),
249d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber      mFirstPacketTimeUs(-1ll),
250dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber      mHistoryLength(0),
251dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber      mTotalBytesSent(0ll)
252774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#if LOG_TRANSPORT_STREAM
253774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber      ,mLogFile(NULL)
254774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#endif
255774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber{
256d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mTSQueue->setRange(0, 12);
257774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber
258774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#if LOG_TRANSPORT_STREAM
259774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber    mLogFile = fopen("/system/etc/log.ts", "wb");
260774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#endif
261d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
262d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
263d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::init(
264d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const char *clientIP, int32_t clientRtp, int32_t clientRtcp,
265bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        TransportMode transportMode) {
266bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    mClientIP = clientIP;
267bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
268d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    status_t err = setupPacketizer();
269d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
270d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (err != OK) {
271d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return err;
272d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
273d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
274bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    mTransportMode = transportMode;
275bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
276bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (transportMode == TRANSPORT_TCP_INTERLEAVED) {
277d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTPChannel = clientRtp;
278d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTCPChannel = clientRtcp;
279d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTPPort = 0;
280d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTPSessionID = 0;
281d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mRTCPSessionID = 0;
282d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
283d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        updateLiveness();
284d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return OK;
285d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
286d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
287d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mRTPChannel = 0;
288d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mRTCPChannel = 0;
289d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
290bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mTransportMode == TRANSPORT_TCP) {
291bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        // XXX This is wrong, we need to allocate sockets here, we only
292bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        // need to do this because the dongles are not establishing their
293bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        // end until after PLAY instead of before SETUP.
294bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        mRTPPort = 20000;
295bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        mRTPSessionID = 0;
296bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        mRTCPSessionID = 0;
297bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        mClientRTPPort = clientRtp;
298bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        mClientRTCPPort = clientRtcp;
299bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
300bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        updateLiveness();
301bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        return OK;
302bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    }
303bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
304d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    int serverRtp;
305d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
306d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> rtpNotify = new AMessage(kWhatRTPNotify, id());
307d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> rtcpNotify = new AMessage(kWhatRTCPNotify, id());
308efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
309efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
310efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber    sp<AMessage> rtpRetransmissionNotify =
311efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        new AMessage(kWhatRTPRetransmissionNotify, id());
312efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
313efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber    sp<AMessage> rtcpRetransmissionNotify =
314efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        new AMessage(kWhatRTCPRetransmissionNotify, id());
315efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
316efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
317d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    for (serverRtp = 15550;; serverRtp += 2) {
318d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        int32_t rtpSession;
319bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        if (mTransportMode == TRANSPORT_UDP) {
320bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            err = mNetSession->createUDPSession(
321bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        serverRtp, clientIP, clientRtp,
322bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        rtpNotify, &rtpSession);
323bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        } else {
324bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            err = mNetSession->createTCPDatagramSession(
325bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        serverRtp, clientIP, clientRtp,
326bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        rtpNotify, &rtpSession);
327bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        }
328d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
329d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (err != OK) {
330d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            ALOGI("failed to create RTP socket on port %d", serverRtp);
331d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            continue;
332d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
333d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
334efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        int32_t rtcpSession = 0;
335d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
336efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        if (clientRtcp >= 0) {
337efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            if (mTransportMode == TRANSPORT_UDP) {
338efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                err = mNetSession->createUDPSession(
339efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        serverRtp + 1, clientIP, clientRtcp,
340efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        rtcpNotify, &rtcpSession);
341efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            } else {
342efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                err = mNetSession->createTCPDatagramSession(
343efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        serverRtp + 1, clientIP, clientRtcp,
344efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        rtcpNotify, &rtcpSession);
345efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            }
346d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
347efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            if (err != OK) {
348efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                ALOGI("failed to create RTCP socket on port %d", serverRtp + 1);
349efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
350efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                mNetSession->destroySession(rtpSession);
351efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                continue;
352efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            }
353d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
354d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
355efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
356bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        if (mTransportMode == TRANSPORT_UDP) {
357efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            int32_t rtpRetransmissionSession;
358efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
359bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            err = mNetSession->createUDPSession(
360efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        serverRtp + kRetransmissionPortOffset,
361efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        clientIP,
362efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        clientRtp + kRetransmissionPortOffset,
363efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        rtpRetransmissionNotify,
364efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        &rtpRetransmissionSession);
365efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
366efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            if (err != OK) {
367efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                mNetSession->destroySession(rtcpSession);
368efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                mNetSession->destroySession(rtpSession);
369efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                continue;
370efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            }
371d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
372efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            CHECK_GE(clientRtcp, 0);
373d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
374efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            int32_t rtcpRetransmissionSession;
375efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            err = mNetSession->createUDPSession(
376efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        serverRtp + 1 + kRetransmissionPortOffset,
377efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        clientIP,
378efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        clientRtp + 1 + kRetransmissionPortOffset,
379efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        rtcpRetransmissionNotify,
380efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        &rtcpRetransmissionSession);
381efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
382efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            if (err != OK) {
383efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                mNetSession->destroySession(rtpRetransmissionSession);
384efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                mNetSession->destroySession(rtcpSession);
385efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                mNetSession->destroySession(rtpSession);
386efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                continue;
387efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            }
388efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
389efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            mRTPRetransmissionSessionID = rtpRetransmissionSession;
390efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            mRTCPRetransmissionSessionID = rtcpRetransmissionSession;
391efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
392efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            ALOGI("rtpRetransmissionSessionID = %d, "
393efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                  "rtcpRetransmissionSessionID = %d",
394efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                  rtpRetransmissionSession, rtcpRetransmissionSession);
395d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
396efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
397efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
398efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        mRTPPort = serverRtp;
399efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        mRTPSessionID = rtpSession;
400efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        mRTCPSessionID = rtcpSession;
401d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
402efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        ALOGI("rtpSessionID = %d, rtcpSessionID = %d", rtpSession, rtcpSession);
403efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        break;
404d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
405d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
406d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mRTPPort == 0) {
407d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return UNKNOWN_ERROR;
408d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
409d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
410d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    updateLiveness();
411d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
412d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
413d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
414d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
415d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas HuberWifiDisplaySource::PlaybackSession::~PlaybackSession() {
416774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#if LOG_TRANSPORT_STREAM
417774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber    if (mLogFile != NULL) {
418774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber        fclose(mLogFile);
419774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber        mLogFile = NULL;
420774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber    }
421774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber#endif
422d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
423d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
424d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberint32_t WifiDisplaySource::PlaybackSession::getRTPPort() const {
425d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mRTPPort;
426d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
427d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
428d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberint64_t WifiDisplaySource::PlaybackSession::getLastLifesignUs() const {
429d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return mLastLifesignUs;
430d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
431d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
432d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::updateLiveness() {
433d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mLastLifesignUs = ALooper::GetNowUs();
434d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
435d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
436d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::play() {
437d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    updateLiveness();
438d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
439bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    return OK;
440bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber}
441bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
442bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::finishPlay() {
44392f655fe351a5f2eb7d36123d2b687d6e7e3e913Andreas Huber    // XXX Give the dongle a second to bind its sockets.
44492f655fe351a5f2eb7d36123d2b687d6e7e3e913Andreas Huber    (new AMessage(kWhatFinishPlay, id()))->post(1000000ll);
445bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    return OK;
446bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber}
447bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
448bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::onFinishPlay() {
449bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mTransportMode != TRANSPORT_TCP) {
450bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        return onFinishPlay2();
451bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    }
452bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
453bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    sp<AMessage> rtpNotify = new AMessage(kWhatRTPNotify, id());
454bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
455bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    status_t err = mNetSession->createTCPDatagramSession(
456bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                mRTPPort, mClientIP.c_str(), mClientRTPPort,
457bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                rtpNotify, &mRTPSessionID);
458bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
459bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (err != OK) {
460bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        return err;
461bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    }
462bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
463bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mClientRTCPPort >= 0) {
464bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        sp<AMessage> rtcpNotify = new AMessage(kWhatRTCPNotify, id());
465bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
466bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        err = mNetSession->createTCPDatagramSession(
467bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                mRTPPort + 1, mClientIP.c_str(), mClientRTCPPort,
468bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                rtcpNotify, &mRTCPSessionID);
469bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    }
470bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
471bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    return err;
472bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber}
473bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
474bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::onFinishPlay2() {
475d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mRTCPSessionID != 0) {
476d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        scheduleSendSR();
477d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
478d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
479e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    for (size_t i = 0; i < mTracks.size(); ++i) {
480e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        status_t err = mTracks.editValueAt(i)->start();
481e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
482e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        if (err != OK) {
483e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            for (size_t j = 0; j < i; ++j) {
484e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                mTracks.editValueAt(j)->stop();
485e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            }
486e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
487e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            return err;
488e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        }
489e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
490e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
491bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    sp<AMessage> notify = mNotify->dup();
492bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    notify->setInt32("what", kWhatSessionEstablished);
493bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    notify->post();
494bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
495e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return OK;
496d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
497d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
498d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::pause() {
499d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    updateLiveness();
500d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
501d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
502d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
503d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
504a438123bd96c7faf145683876702387efe5628d9Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::destroy() {
505a438123bd96c7faf145683876702387efe5628d9Andreas Huber    mTracks.clear();
506a438123bd96c7faf145683876702387efe5628d9Andreas Huber
507a438123bd96c7faf145683876702387efe5628d9Andreas Huber    mPacketizer.clear();
508a438123bd96c7faf145683876702387efe5628d9Andreas Huber
509a438123bd96c7faf145683876702387efe5628d9Andreas Huber    mTracks.clear();
510a438123bd96c7faf145683876702387efe5628d9Andreas Huber
511efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
512efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber    if (mRTCPRetransmissionSessionID != 0) {
513efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        mNetSession->destroySession(mRTCPRetransmissionSessionID);
514efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber    }
515efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
516efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber    if (mRTPRetransmissionSessionID != 0) {
517efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        mNetSession->destroySession(mRTPRetransmissionSessionID);
518efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber    }
519efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
520efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
521a438123bd96c7faf145683876702387efe5628d9Andreas Huber    if (mRTCPSessionID != 0) {
522a438123bd96c7faf145683876702387efe5628d9Andreas Huber        mNetSession->destroySession(mRTCPSessionID);
523a438123bd96c7faf145683876702387efe5628d9Andreas Huber    }
524a438123bd96c7faf145683876702387efe5628d9Andreas Huber
525a438123bd96c7faf145683876702387efe5628d9Andreas Huber    if (mRTPSessionID != 0) {
526a438123bd96c7faf145683876702387efe5628d9Andreas Huber        mNetSession->destroySession(mRTPSessionID);
527a438123bd96c7faf145683876702387efe5628d9Andreas Huber    }
528a438123bd96c7faf145683876702387efe5628d9Andreas Huber
529a438123bd96c7faf145683876702387efe5628d9Andreas Huber    return OK;
530a438123bd96c7faf145683876702387efe5628d9Andreas Huber}
531a438123bd96c7faf145683876702387efe5628d9Andreas Huber
532d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::onMessageReceived(
533d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const sp<AMessage> &msg) {
534d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    switch (msg->what()) {
535d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        case kWhatRTPNotify:
536d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        case kWhatRTCPNotify:
537efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
538efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        case kWhatRTPRetransmissionNotify:
539efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        case kWhatRTCPRetransmissionNotify:
540efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
541d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        {
542d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            int32_t reason;
543d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            CHECK(msg->findInt32("reason", &reason));
544d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
545d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            switch (reason) {
546d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                case ANetworkSession::kWhatError:
547d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                {
548d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    int32_t sessionID;
549d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findInt32("sessionID", &sessionID));
550d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
551d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    int32_t err;
552d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findInt32("err", &err));
553d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
554d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    int32_t errorOccuredDuringSend;
555d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findInt32("send", &errorOccuredDuringSend));
556d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
557d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    AString detail;
558d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findString("detail", &detail));
559d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
560efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    if ((msg->what() == kWhatRTPNotify
561efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
562efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                            || msg->what() == kWhatRTPRetransmissionNotify
563efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
564efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        ) && !errorOccuredDuringSend) {
565d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        // This is ok, we don't expect to receive anything on
566d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        // the RTP socket.
567d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        break;
568d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
569d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
570d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    ALOGE("An error occurred during %s in session %d "
571d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          "(%d, '%s' (%s)).",
572d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          errorOccuredDuringSend ? "send" : "receive",
573d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          sessionID,
574d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          err,
575d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          detail.c_str(),
576d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                          strerror(-err));
577d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
578d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    mNetSession->destroySession(sessionID);
579d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
580d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    if (sessionID == mRTPSessionID) {
581d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        mRTPSessionID = 0;
582d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    } else if (sessionID == mRTCPSessionID) {
583d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        mRTCPSessionID = 0;
584d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
585efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
586efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    else if (sessionID == mRTPRetransmissionSessionID) {
587efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        mRTPRetransmissionSessionID = 0;
588efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    } else if (sessionID == mRTCPRetransmissionSessionID) {
589efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        mRTCPRetransmissionSessionID = 0;
590efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    }
591efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
592d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
593d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    // Inform WifiDisplaySource of our premature death (wish).
594d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    sp<AMessage> notify = mNotify->dup();
595d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    notify->setInt32("what", kWhatSessionDead);
596d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    notify->post();
597d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    break;
598d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
599d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
600d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                case ANetworkSession::kWhatDatagram:
601d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                {
602d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    int32_t sessionID;
603d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findInt32("sessionID", &sessionID));
604d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
605d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    sp<ABuffer> data;
606d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    CHECK(msg->findBuffer("data", &data));
607d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
608d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    status_t err;
609efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    if (msg->what() == kWhatRTCPNotify
610efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
611efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                            || msg->what() == kWhatRTCPRetransmissionNotify
612efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
613efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                       )
614efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    {
615d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        err = parseRTCP(data);
616d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    }
617d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    break;
618d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
619d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
620bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                case ANetworkSession::kWhatConnected:
621bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                {
622bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    CHECK_EQ(mTransportMode, TRANSPORT_TCP);
623bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
624bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    int32_t sessionID;
625bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    CHECK(msg->findInt32("sessionID", &sessionID));
626bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
627bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    if (sessionID == mRTPSessionID) {
628bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        CHECK(!mRTPConnected);
629bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        mRTPConnected = true;
630bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        ALOGI("RTP Session now connected.");
631bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    } else if (sessionID == mRTCPSessionID) {
632bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        CHECK(!mRTCPConnected);
633bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        mRTCPConnected = true;
634bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        ALOGI("RTCP Session now connected.");
635bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    } else {
636bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        TRESPASS();
637bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    }
638bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
639bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    if (mRTPConnected
640bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                            && (mClientRTCPPort < 0 || mRTCPConnected)) {
641bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        onFinishPlay2();
642bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    }
643bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    break;
644bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                }
645bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
646d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                default:
647d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    TRESPASS();
648d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
649d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
650d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
651d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
652d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        case kWhatSendSR:
653d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        {
654d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mSendSRPending = false;
655d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
656d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            if (mRTCPSessionID == 0) {
657d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
658d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
659d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
660d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            onSendSR();
661d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
662d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            scheduleSendSR();
663d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
664d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
665d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
666207e18540fefbaf530a4fdf506d266f34ddec84fAndreas Huber        case kWhatMediaPullerNotify:
667d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        {
668d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            int32_t what;
669d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            CHECK(msg->findInt32("what", &what));
670d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
671207e18540fefbaf530a4fdf506d266f34ddec84fAndreas Huber            if (what == MediaPuller::kWhatEOS) {
672d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ALOGI("input eos");
673d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
674d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                for (size_t i = 0; i < mTracks.size(); ++i) {
675d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    mTracks.valueAt(i)->converter()->signalEOS();
676d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
677d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            } else {
678207e18540fefbaf530a4fdf506d266f34ddec84fAndreas Huber                CHECK_EQ(what, MediaPuller::kWhatAccessUnit);
679d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
680d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                size_t trackIndex;
681d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK(msg->findSize("trackIndex", &trackIndex));
682d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
683d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                sp<ABuffer> accessUnit;
684d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK(msg->findBuffer("accessUnit", &accessUnit));
685d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
686d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                mTracks.valueFor(trackIndex)->converter()
687d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    ->feedAccessUnit(accessUnit);
688d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
689d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
690d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
691d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
692d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        case kWhatConverterNotify:
693d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        {
694d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            int32_t what;
695d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            CHECK(msg->findInt32("what", &what));
696d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
697d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            size_t trackIndex;
698d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            CHECK(msg->findSize("trackIndex", &trackIndex));
699d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
700d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            if (what == Converter::kWhatAccessUnit) {
701d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                const sp<Track> &track = mTracks.valueFor(trackIndex);
702d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
703d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ssize_t packetizerTrackIndex = track->packetizerTrackIndex();
704d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
70528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                if (packetizerTrackIndex < 0) {
706d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    packetizerTrackIndex =
707d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                        mPacketizer->addTrack(track->getFormat());
708d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
70928e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                    CHECK_GE(packetizerTrackIndex, 0);
710d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
71128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                    track->setPacketizerTrackIndex(packetizerTrackIndex);
712b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
71328e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                    if (allTracksHavePacketizerIndex()) {
71428e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                        status_t err = packetizeQueuedAccessUnits();
715b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
716b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        if (err != OK) {
717b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            // Inform WifiDisplaySource of our premature death
718b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            // (wish).
719b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            sp<AMessage> notify = mNotify->dup();
720b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            notify->setInt32("what", kWhatSessionDead);
721b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            notify->post();
72228e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
723b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                            break;
724b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                        }
725b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber                    }
72628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                }
727b8c7bd418f0ee5b88923b0e0817e3a4acc53cf8dAndreas Huber
72828e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                sp<ABuffer> accessUnit;
72928e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                CHECK(msg->findBuffer("accessUnit", &accessUnit));
730d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
73128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                if (!allTracksHavePacketizerIndex()) {
73228e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                    track->queueAccessUnit(accessUnit);
73328e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                    break;
73428e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                }
735d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
73628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                status_t err = packetizeAccessUnit(trackIndex, accessUnit);
737774df0dce0116c69b6d17f2e4a4912e06138e575Andreas Huber
73828e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                if (err != OK) {
73928e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                    // Inform WifiDisplaySource of our premature death
74028e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                    // (wish).
74128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                    sp<AMessage> notify = mNotify->dup();
74228e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                    notify->setInt32("what", kWhatSessionDead);
74328e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                    notify->post();
744d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
74528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                break;
746d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            } else if (what == Converter::kWhatEOS) {
747d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK_EQ(what, Converter::kWhatEOS);
748d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
749d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ALOGI("output EOS on track %d", trackIndex);
750d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
751d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ssize_t index = mTracks.indexOfKey(trackIndex);
752d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK_GE(index, 0);
753d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
754d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                const sp<Converter> &converter =
755d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    mTracks.valueAt(index)->converter();
756d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                looper()->unregisterHandler(converter->id());
757d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
758d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                mTracks.removeItemsAt(index);
759d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
760d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                if (mTracks.isEmpty()) {
761d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                    ALOGI("Reached EOS");
762d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                }
763d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            } else {
764d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK_EQ(what, Converter::kWhatError);
765d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
766d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                status_t err;
767d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                CHECK(msg->findInt32("err", &err));
768d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
769d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ALOGE("converter signaled error %d", err);
770ea4bbfdcad9478ea19257fb19a32de68a2dfd958Andreas Huber
771ea4bbfdcad9478ea19257fb19a32de68a2dfd958Andreas Huber                // Inform WifiDisplaySource of our premature death (wish).
772ea4bbfdcad9478ea19257fb19a32de68a2dfd958Andreas Huber                sp<AMessage> notify = mNotify->dup();
773ea4bbfdcad9478ea19257fb19a32de68a2dfd958Andreas Huber                notify->setInt32("what", kWhatSessionDead);
774ea4bbfdcad9478ea19257fb19a32de68a2dfd958Andreas Huber                notify->post();
775d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
776d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            break;
777d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
778d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
779bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        case kWhatFinishPlay:
780bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        {
781bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            onFinishPlay();
782bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            break;
783bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        }
784bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
785d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        default:
786d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            TRESPASS();
787d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
788d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
789d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
790d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::setupPacketizer() {
791e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mPacketizer = new TSPacketizer;
792d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
793e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    status_t err = addVideoSource();
794d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
795e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (err != OK) {
796e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        return err;
797e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
798e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
799e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return addAudioSource();
800e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber}
801d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
802e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::addSource(
803e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        bool isVideo, const sp<MediaSource> &source, size_t *numInputBuffers) {
804e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<ALooper> pullLooper = new ALooper;
805e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    pullLooper->setName("pull_looper");
806e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
807e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    pullLooper->start(
808e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            false /* runOnCallingThread */,
809e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            false /* canCallJava */,
810ea4bbfdcad9478ea19257fb19a32de68a2dfd958Andreas Huber            PRIORITY_AUDIO);
811d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
812e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<ALooper> codecLooper = new ALooper;
813e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    codecLooper->setName("codec_looper");
814e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
815e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    codecLooper->start(
816e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            false /* runOnCallingThread */,
817e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber            false /* canCallJava */,
818ea4bbfdcad9478ea19257fb19a32de68a2dfd958Andreas Huber            PRIORITY_AUDIO);
819e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
820e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    size_t trackIndex;
821e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
822e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<AMessage> notify;
823e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
824e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    trackIndex = mTracks.size();
825e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
826207e18540fefbaf530a4fdf506d266f34ddec84fAndreas Huber    notify = new AMessage(kWhatMediaPullerNotify, id());
827e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    notify->setSize("trackIndex", trackIndex);
828e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<MediaPuller> puller = new MediaPuller(source, notify);
829e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    pullLooper->registerHandler(puller);
830d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
831d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<AMessage> format;
832d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    status_t err = convertMetaDataToMessage(source->getFormat(), &format);
833d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK_EQ(err, (status_t)OK);
834d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
835e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (isVideo) {
836e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        format->setInt32("store-metadata-in-buffers", true);
837d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
838e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        format->setInt32(
839e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                "color-format", OMX_COLOR_FormatAndroidOpaque);
840e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
841d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
842e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    notify = new AMessage(kWhatConverterNotify, id());
843e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    notify->setSize("trackIndex", trackIndex);
844d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
845d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<Converter> converter =
846e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        new Converter(notify, codecLooper, format);
84766e72bc85fb762876baff60ef29de729da93cf26Andreas Huber    CHECK_EQ(converter->initCheck(), (status_t)OK);
84866e72bc85fb762876baff60ef29de729da93cf26Andreas Huber
849d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    looper()->registerHandler(converter);
850d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
851e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (numInputBuffers != NULL) {
852e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        *numInputBuffers = converter->getInputBufferCount();
853e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
85466e72bc85fb762876baff60ef29de729da93cf26Andreas Huber
855e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    mTracks.add(trackIndex, new Track(pullLooper, codecLooper, puller, converter));
856e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
857e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (isVideo) {
858e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        mVideoTrackIndex = trackIndex;
859e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
860e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
861e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return OK;
862e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber}
863e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
864e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::addVideoSource() {
865e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<SurfaceMediaSource> source = new SurfaceMediaSource(width(), height());
866e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
867e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    sp<MediaSource> videoSource =
86872ff5903df5f409ea83f74c363a52f0745ced8b8Andreas Huber            new RepeaterSource(source, 24.0 /* rateHz */);
869e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
870e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    size_t numInputBuffers;
871e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    status_t err = addSource(true /* isVideo */, videoSource, &numInputBuffers);
872e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
873e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    if (err != OK) {
874e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        return err;
875e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    }
87666e72bc85fb762876baff60ef29de729da93cf26Andreas Huber
8775a832f87b680ead3606c4448a0a82c0e556d1b93Andreas Huber    err = source->setMaxAcquiredBufferCount(numInputBuffers);
87866e72bc85fb762876baff60ef29de729da93cf26Andreas Huber    CHECK_EQ(err, (status_t)OK);
87966e72bc85fb762876baff60ef29de729da93cf26Andreas Huber
8800b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber    mBufferQueue = source->getBufferQueue();
8810b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber
882e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    return OK;
883e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber}
884e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
885e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::addAudioSource() {
886082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber    sp<AudioSource> audioSource = new AudioSource(
8871646a0fed94c30a44128b3c379736def4b332033Andreas Huber            AUDIO_SOURCE_REMOTE_SUBMIX,
888082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber            48000 /* sampleRate */,
8891646a0fed94c30a44128b3c379736def4b332033Andreas Huber            2 /* channelCount */);
890082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber
8917977e85f7287f2b0e7a5de94e853e6073736e03bAndreas Huber    if (audioSource->initCheck() == OK) {
8927977e85f7287f2b0e7a5de94e853e6073736e03bAndreas Huber        audioSource->setUseLooperTime(true);
893082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber
894e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber        return addSource(
895e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber                false /* isVideo */, audioSource, NULL /* numInputBuffers */);
8967977e85f7287f2b0e7a5de94e853e6073736e03bAndreas Huber    }
897e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber
898e1957358f11031a554c57d4fb46988dd6044acc1Andreas Huber    ALOGW("Unable to instantiate audio source");
899082830f92373a1b9e512dbbfb940187ffa1c2c6fAndreas Huber
900d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
901d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
902d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
9030b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Hubersp<ISurfaceTexture> WifiDisplaySource::PlaybackSession::getSurfaceTexture() {
9040b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber    return mBufferQueue;
9050b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber}
9060b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber
9070b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huberint32_t WifiDisplaySource::PlaybackSession::width() const {
908207e18540fefbaf530a4fdf506d266f34ddec84fAndreas Huber    return 1280;
9090b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber}
9100b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber
9110b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huberint32_t WifiDisplaySource::PlaybackSession::height() const {
912207e18540fefbaf530a4fdf506d266f34ddec84fAndreas Huber    return 720;
9130b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber}
9140b73d4730202fcad53aefc4314a06e7b95f442f0Andreas Huber
915d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::scheduleSendSR() {
916d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (mSendSRPending) {
917d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return;
918d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
919d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
920d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mSendSRPending = true;
921d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    (new AMessage(kWhatSendSR, id()))->post(kSendSRIntervalUs);
922d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
923d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
924d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::addSR(const sp<ABuffer> &buffer) {
925d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint8_t *data = buffer->data() + buffer->size();
926d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
927d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    // TODO: Use macros/utility functions to clean up all the bitshifts below.
928d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
929d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[0] = 0x80 | 0;
930d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[1] = 200;  // SR
931d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[2] = 0;
932d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[3] = 6;
933d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[4] = kSourceID >> 24;
934d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[5] = (kSourceID >> 16) & 0xff;
935d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[6] = (kSourceID >> 8) & 0xff;
936d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[7] = kSourceID & 0xff;
937d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
938d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[8] = mLastNTPTime >> (64 - 8);
939d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[9] = (mLastNTPTime >> (64 - 16)) & 0xff;
940d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[10] = (mLastNTPTime >> (64 - 24)) & 0xff;
941d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[11] = (mLastNTPTime >> 32) & 0xff;
942d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[12] = (mLastNTPTime >> 24) & 0xff;
943d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[13] = (mLastNTPTime >> 16) & 0xff;
944d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[14] = (mLastNTPTime >> 8) & 0xff;
945d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[15] = mLastNTPTime & 0xff;
946d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
947d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[16] = (mLastRTPTime >> 24) & 0xff;
948d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[17] = (mLastRTPTime >> 16) & 0xff;
949d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[18] = (mLastRTPTime >> 8) & 0xff;
950d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[19] = mLastRTPTime & 0xff;
951d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
952d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[20] = mNumRTPSent >> 24;
953d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[21] = (mNumRTPSent >> 16) & 0xff;
954d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[22] = (mNumRTPSent >> 8) & 0xff;
955d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[23] = mNumRTPSent & 0xff;
956d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
957d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[24] = mNumRTPOctetsSent >> 24;
958d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[25] = (mNumRTPOctetsSent >> 16) & 0xff;
959d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[26] = (mNumRTPOctetsSent >> 8) & 0xff;
960d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[27] = mNumRTPOctetsSent & 0xff;
961d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
962d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    buffer->setRange(buffer->offset(), buffer->size() + 28);
963d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
964d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
965d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::addSDES(const sp<ABuffer> &buffer) {
966d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint8_t *data = buffer->data() + buffer->size();
967d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[0] = 0x80 | 1;
968d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[1] = 202;  // SDES
969d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[4] = kSourceID >> 24;
970d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[5] = (kSourceID >> 16) & 0xff;
971d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[6] = (kSourceID >> 8) & 0xff;
972d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[7] = kSourceID & 0xff;
973d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
974d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    size_t offset = 8;
975d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
976d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = 1;  // CNAME
977d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
978d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    static const char *kCNAME = "someone@somewhere";
979d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = strlen(kCNAME);
980d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
981d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    memcpy(&data[offset], kCNAME, strlen(kCNAME));
982d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    offset += strlen(kCNAME);
983d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
984d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = 7;  // NOTE
985d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
986d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    static const char *kNOTE = "Hell's frozen over.";
987d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = strlen(kNOTE);
988d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
989d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    memcpy(&data[offset], kNOTE, strlen(kNOTE));
990d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    offset += strlen(kNOTE);
991d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
992d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[offset++] = 0;
993d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
994d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if ((offset % 4) > 0) {
995d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        size_t count = 4 - (offset % 4);
996d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        switch (count) {
997d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 3:
998d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                data[offset++] = 0;
999d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 2:
1000d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                data[offset++] = 0;
1001d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 1:
1002d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                data[offset++] = 0;
1003d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1004d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1005d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1006d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    size_t numWords = (offset / 4) - 1;
1007d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[2] = numWords >> 8;
1008d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    data[3] = numWords & 0xff;
1009d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1010d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    buffer->setRange(buffer->offset(), buffer->size() + offset);
1011d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1012d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1013d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber// static
1014d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberuint64_t WifiDisplaySource::PlaybackSession::GetNowNTP() {
1015d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint64_t nowUs = ALooper::GetNowUs();
1016d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1017d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll;
1018d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1019d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint64_t hi = nowUs / 1000000ll;
1020d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint64_t lo = ((1ll << 32) * (nowUs % 1000000ll)) / 1000000ll;
1021d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1022d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return (hi << 32) | lo;
1023d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1024d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1025d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Hubervoid WifiDisplaySource::PlaybackSession::onSendSR() {
1026d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    sp<ABuffer> buffer = new ABuffer(1500);
1027d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    buffer->setRange(0, 0);
1028d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1029d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    addSR(buffer);
1030d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    addSDES(buffer);
1031d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1032bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mTransportMode == TRANSPORT_TCP_INTERLEAVED) {
1033d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        sp<AMessage> notify = mNotify->dup();
1034d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        notify->setInt32("what", kWhatBinaryData);
1035d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        notify->setInt32("channel", mRTCPChannel);
1036d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        notify->setBuffer("data", buffer);
1037d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        notify->post();
1038d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    } else {
1039bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        sendPacket(mRTCPSessionID, buffer->data(), buffer->size());
1040d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1041d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1042d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    ++mNumSRsSent;
1043d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1044d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1045d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberssize_t WifiDisplaySource::PlaybackSession::appendTSData(
1046d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const void *data, size_t size, bool timeDiscontinuity, bool flush) {
1047d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK_EQ(size, 188);
1048d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1049d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    CHECK_LE(mTSQueue->size() + size, mTSQueue->capacity());
1050d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1051d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    memcpy(mTSQueue->data() + mTSQueue->size(), data, size);
1052d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    mTSQueue->setRange(0, mTSQueue->size() + size);
1053d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1054d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (flush || mTSQueue->size() == mTSQueue->capacity()) {
1055d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        // flush
1056d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1057d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        int64_t nowUs = ALooper::GetNowUs();
1058d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (mFirstPacketTimeUs < 0ll) {
1059d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mFirstPacketTimeUs = nowUs;
1060d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1061d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1062d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        // 90kHz time scale
1063d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        uint32_t rtpTime = ((nowUs - mFirstPacketTimeUs) * 9ll) / 100ll;
1064d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1065d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        uint8_t *rtp = mTSQueue->data();
1066d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[0] = 0x80;
1067d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[1] = 33 | (timeDiscontinuity ? (1 << 7) : 0);  // M-bit
1068d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[2] = (mRTPSeqNo >> 8) & 0xff;
1069d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[3] = mRTPSeqNo & 0xff;
1070d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[4] = rtpTime >> 24;
1071d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[5] = (rtpTime >> 16) & 0xff;
1072d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[6] = (rtpTime >> 8) & 0xff;
1073d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[7] = rtpTime & 0xff;
1074d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[8] = kSourceID >> 24;
1075d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[9] = (kSourceID >> 16) & 0xff;
1076d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[10] = (kSourceID >> 8) & 0xff;
1077d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        rtp[11] = kSourceID & 0xff;
1078d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1079d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        ++mRTPSeqNo;
1080d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        ++mNumRTPSent;
1081d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mNumRTPOctetsSent += mTSQueue->size() - 12;
1082d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1083d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mLastRTPTime = rtpTime;
1084d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mLastNTPTime = GetNowNTP();
1085d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1086bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        if (mTransportMode == TRANSPORT_TCP_INTERLEAVED) {
1087d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            sp<AMessage> notify = mNotify->dup();
1088d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            notify->setInt32("what", kWhatBinaryData);
1089d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1090d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            sp<ABuffer> data = new ABuffer(mTSQueue->size());
1091d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            memcpy(data->data(), rtp, mTSQueue->size());
1092d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1093d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            notify->setInt32("channel", mRTPChannel);
1094d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            notify->setBuffer("data", data);
1095d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            notify->post();
1096d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        } else {
1097bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            sendPacket(mRTPSessionID, rtp, mTSQueue->size());
1098dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber
1099dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber            mTotalBytesSent += mTSQueue->size();
1100dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber            int64_t delayUs = ALooper::GetNowUs() - mFirstPacketTimeUs;
1101dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber
1102dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber            if (delayUs > 0ll) {
1103dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber                ALOGV("approx. net bandwidth used: %.2f Mbit/sec",
1104dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber                        mTotalBytesSent * 8.0 / delayUs);
1105dca352880e210e0ca0ff39de074540d3640ecfabAndreas Huber            }
1106d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1107d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1108d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mTSQueue->setInt32Data(mRTPSeqNo - 1);
1109d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mHistory.push_back(mTSQueue);
1110d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        ++mHistoryLength;
1111d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1112d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (mHistoryLength > kMaxHistoryLength) {
1113d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mTSQueue = *mHistory.begin();
1114d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mHistory.erase(mHistory.begin());
1115d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1116d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            --mHistoryLength;
1117d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        } else {
1118d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            mTSQueue = new ABuffer(12 + kMaxNumTSPacketsPerRTPPacket * 188);
1119d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1120d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1121d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        mTSQueue->setRange(0, 12);
1122d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1123d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1124d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return size;
1125d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1126d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1127d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::parseRTCP(
1128d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const sp<ABuffer> &buffer) {
1129d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    const uint8_t *data = buffer->data();
1130d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    size_t size = buffer->size();
1131d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1132d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    while (size > 0) {
1133d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (size < 8) {
1134d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            // Too short to be a valid RTCP header
1135d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            return ERROR_MALFORMED;
1136d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1137d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1138d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if ((data[0] >> 6) != 2) {
1139d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            // Unsupported version.
1140d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            return ERROR_UNSUPPORTED;
1141d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1142d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1143d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (data[0] & 0x20) {
1144d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            // Padding present.
1145d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1146d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            size_t paddingLength = data[size - 1];
1147d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1148d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            if (paddingLength + 12 > size) {
1149d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                // If we removed this much padding we'd end up with something
1150d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                // that's too short to be a valid RTP header.
1151d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                return ERROR_MALFORMED;
1152d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
1153d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1154d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            size -= paddingLength;
1155d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1156d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1157d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        size_t headerLength = 4 * (data[2] << 8 | data[3]) + 4;
1158d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1159d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        if (size < headerLength) {
1160d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            // Only received a partial packet?
1161d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            return ERROR_MALFORMED;
1162d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1163d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1164d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        switch (data[1]) {
1165d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 200:
1166d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 201:  // RR
1167d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 202:  // SDES
1168d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 203:
1169d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 204:  // APP
1170d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
1171d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1172efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
1173d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 205:  // TSFB (transport layer specific feedback)
1174d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                parseTSFB(data, headerLength);
1175d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
1176efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
1177d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1178d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            case 206:  // PSFB (payload specific feedback)
1179d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                hexdump(data, headerLength);
1180d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
1181d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1182d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            default:
1183d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            {
1184d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                ALOGW("Unknown RTCP packet type %u of size %d",
1185d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                     (unsigned)data[1], headerLength);
1186d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber                break;
1187d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
1188d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1189d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1190d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        data += headerLength;
1191d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        size -= headerLength;
1192d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1193d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1194d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
1195d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1196d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1197efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#if ENABLE_RETRANSMISSION
1198d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::parseTSFB(
1199d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        const uint8_t *data, size_t size) {
1200d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if ((data[0] & 0x1f) != 1) {
1201d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return ERROR_UNSUPPORTED;  // We only support NACK for now.
1202d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1203d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1204d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    uint32_t srcId = U32_AT(&data[8]);
1205d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    if (srcId != kSourceID) {
1206d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        return ERROR_MALFORMED;
1207d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1208d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1209d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    for (size_t i = 12; i < size; i += 4) {
1210d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        uint16_t seqNo = U16_AT(&data[i]);
1211d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        uint16_t blp = U16_AT(&data[i + 2]);
1212d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1213d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        List<sp<ABuffer> >::iterator it = mHistory.begin();
1214efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        bool foundSeqNo = false;
1215d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        while (it != mHistory.end()) {
1216d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            const sp<ABuffer> &buffer = *it;
1217d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1218d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            uint16_t bufferSeqNo = buffer->int32Data() & 0xffff;
1219d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1220efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            bool retransmit = false;
1221d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            if (bufferSeqNo == seqNo) {
1222efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                retransmit = true;
1223efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            } else if (blp != 0) {
1224efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                for (size_t i = 0; i < 16; ++i) {
1225efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    if ((blp & (1 << i))
1226efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        && (bufferSeqNo == ((seqNo + i + 1) & 0xffff))) {
1227efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        blp &= ~(1 << i);
1228efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        retransmit = true;
1229efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    }
1230efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                }
1231efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            }
1232d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1233efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            if (retransmit) {
1234efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                ALOGI("retransmitting seqNo %d", bufferSeqNo);
1235efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
1236efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                sp<ABuffer> retransRTP = new ABuffer(2 + buffer->size());
1237efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                uint8_t *rtp = retransRTP->data();
1238efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                memcpy(rtp, buffer->data(), 12);
1239efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                rtp[2] = (mRTPRetransmissionSeqNo >> 8) & 0xff;
1240efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                rtp[3] = mRTPRetransmissionSeqNo & 0xff;
1241efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                rtp[12] = (bufferSeqNo >> 8) & 0xff;
1242efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                rtp[13] = bufferSeqNo & 0xff;
1243efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                memcpy(&rtp[14], buffer->data() + 12, buffer->size() - 12);
1244efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
1245efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                ++mRTPRetransmissionSeqNo;
1246efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
1247efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                sendPacket(
1248efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        mRTPRetransmissionSessionID,
1249efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                        retransRTP->data(), retransRTP->size());
1250efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
1251efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                if (bufferSeqNo == seqNo) {
1252efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    foundSeqNo = true;
1253efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                }
1254efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber
1255efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                if (foundSeqNo && blp == 0) {
1256efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                    break;
1257efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                }
1258d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            }
1259d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1260d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber            ++it;
1261d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1262d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1263efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber        if (!foundSeqNo || blp != 0) {
1264efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber            ALOGI("Some sequence numbers were no longer available for "
1265efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber                  "retransmission");
1266d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber        }
1267d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    }
1268d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1269d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber    return OK;
1270d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}
1271efd9c63dc846dd3dea2c979fe2a9d6770e73f9acAndreas Huber#endif
1272d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1273496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Hubervoid WifiDisplaySource::PlaybackSession::requestIDRFrame() {
1274496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber    for (size_t i = 0; i < mTracks.size(); ++i) {
1275496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber        const sp<Track> &track = mTracks.valueAt(i);
1276496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber
1277496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber        track->converter()->requestIDRFrame();
1278496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber    }
1279496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber}
1280496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber
1281bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huberstatus_t WifiDisplaySource::PlaybackSession::sendPacket(
1282bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        int32_t sessionID, const void *data, size_t size) {
1283bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    return mNetSession->sendRequest(sessionID, data, size);
1284bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber}
1285bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
128628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huberbool WifiDisplaySource::PlaybackSession::allTracksHavePacketizerIndex() {
128728e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    if (mAllTracksHavePacketizerIndex) {
128828e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        return true;
128928e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    }
129028e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
129128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    for (size_t i = 0; i < mTracks.size(); ++i) {
129228e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        if (mTracks.valueAt(i)->packetizerTrackIndex() < 0) {
129328e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            return false;
129428e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        }
129528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    }
129628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
129728e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    mAllTracksHavePacketizerIndex = true;
129828e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
129928e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    return true;
130028e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber}
130128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
1302eb11600a248cfe5b95ddd3e5aaae02bd2ab65276Andreas Huberstatic inline size_t MIN(size_t a, size_t b) {
1303eb11600a248cfe5b95ddd3e5aaae02bd2ab65276Andreas Huber    return (a < b) ? a : b;
1304eb11600a248cfe5b95ddd3e5aaae02bd2ab65276Andreas Huber}
1305eb11600a248cfe5b95ddd3e5aaae02bd2ab65276Andreas Huber
130628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::packetizeAccessUnit(
1307e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        size_t trackIndex, sp<ABuffer> accessUnit) {
130828e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    const sp<Track> &track = mTracks.valueFor(trackIndex);
130928e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
131028e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    uint32_t flags = 0;
131128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
131228e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    bool isHDCPEncrypted = false;
131328e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    uint64_t inputCTR;
131428e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    uint8_t HDCP_private_data[16];
131528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    if (mHDCP != NULL && !track->isAudio()) {
131628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        isHDCPEncrypted = true;
131728e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
1318eb11600a248cfe5b95ddd3e5aaae02bd2ab65276Andreas Huber#if 0
1319eb11600a248cfe5b95ddd3e5aaae02bd2ab65276Andreas Huber        ALOGI("in:");
1320eb11600a248cfe5b95ddd3e5aaae02bd2ab65276Andreas Huber        hexdump(accessUnit->data(), MIN(64, accessUnit->size()));
1321eb11600a248cfe5b95ddd3e5aaae02bd2ab65276Andreas Huber#endif
1322eb11600a248cfe5b95ddd3e5aaae02bd2ab65276Andreas Huber
1323e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        if (IsIDR(accessUnit)) {
1324e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber            // XXX remove this once the encoder takes care of this.
1325e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber            accessUnit = mPacketizer->prependCSD(
1326e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber                    track->packetizerTrackIndex(), accessUnit);
1327eb11600a248cfe5b95ddd3e5aaae02bd2ab65276Andreas Huber        }
1328eb11600a248cfe5b95ddd3e5aaae02bd2ab65276Andreas Huber
132928e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        status_t err = mHDCP->encrypt(
1330e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber                accessUnit->data(), accessUnit->size(),
133128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                trackIndex  /* streamCTR */,
133228e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                &inputCTR,
133328e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                accessUnit->data());
133428e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
133528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        if (err != OK) {
133628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            ALOGE("Failed to HDCP-encrypt media data (err %d)",
133728e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                  err);
133828e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
133928e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            return err;
1340eb11600a248cfe5b95ddd3e5aaae02bd2ab65276Andreas Huber        } else {
1341eb11600a248cfe5b95ddd3e5aaae02bd2ab65276Andreas Huber#if 0
1342eb11600a248cfe5b95ddd3e5aaae02bd2ab65276Andreas Huber            ALOGI("out:");
1343eb11600a248cfe5b95ddd3e5aaae02bd2ab65276Andreas Huber            hexdump(accessUnit->data(), MIN(64, accessUnit->size()));
1344eb11600a248cfe5b95ddd3e5aaae02bd2ab65276Andreas Huber            ALOGI("inputCTR: 0x%016llx", inputCTR);
1345e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber            ALOGI("streamCTR: 0x%08x", trackIndex);
1346eb11600a248cfe5b95ddd3e5aaae02bd2ab65276Andreas Huber#endif
134728e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        }
134828e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
134928e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        HDCP_private_data[0] = 0x00;
135028e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
135128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        HDCP_private_data[1] =
135228e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            (((trackIndex >> 30) & 3) << 1) | 1;
135328e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
135428e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        HDCP_private_data[2] = (trackIndex >> 22) & 0xff;
135528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
135628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        HDCP_private_data[3] =
135728e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            (((trackIndex >> 15) & 0x7f) << 1) | 1;
135828e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
135928e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        HDCP_private_data[4] = (trackIndex >> 7) & 0xff;
136028e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
136128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        HDCP_private_data[5] =
136228e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            ((trackIndex & 0x7f) << 1) | 1;
136328e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
136428e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        HDCP_private_data[6] = 0x00;
136528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
136628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        HDCP_private_data[7] =
136728e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            (((inputCTR >> 60) & 0x0f) << 1) | 1;
136828e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
136928e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        HDCP_private_data[8] = (inputCTR >> 52) & 0xff;
137028e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
137128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        HDCP_private_data[9] =
137228e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            (((inputCTR >> 45) & 0x7f) << 1) | 1;
137328e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
137428e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        HDCP_private_data[10] = (inputCTR >> 37) & 0xff;
137528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
137628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        HDCP_private_data[11] =
137728e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            (((inputCTR >> 30) & 0x7f) << 1) | 1;
137828e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
137928e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        HDCP_private_data[12] = (inputCTR >> 22) & 0xff;
138028e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
138128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        HDCP_private_data[13] =
138228e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            (((inputCTR >> 15) & 0x7f) << 1) | 1;
138328e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
138428e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        HDCP_private_data[14] = (inputCTR >> 7) & 0xff;
138528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
138628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        HDCP_private_data[15] =
138728e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            ((inputCTR & 0x7f) << 1) | 1;
138828e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
1389e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber#if 0
1390e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        ALOGI("HDCP_private_data:");
1391e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        hexdump(HDCP_private_data, sizeof(HDCP_private_data));
1392e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber
1393e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        ABitReader br(HDCP_private_data, sizeof(HDCP_private_data));
1394e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        CHECK_EQ(br.getBits(13), 0);
1395e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        CHECK_EQ(br.getBits(2), (trackIndex >> 30) & 3);
1396e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        CHECK_EQ(br.getBits(1), 1u);
1397e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        CHECK_EQ(br.getBits(15), (trackIndex >> 15) & 0x7fff);
1398e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        CHECK_EQ(br.getBits(1), 1u);
1399e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        CHECK_EQ(br.getBits(15), trackIndex & 0x7fff);
1400e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        CHECK_EQ(br.getBits(1), 1u);
1401e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        CHECK_EQ(br.getBits(11), 0);
1402e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        CHECK_EQ(br.getBits(4), (inputCTR >> 60) & 0xf);
1403e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        CHECK_EQ(br.getBits(1), 1u);
1404e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        CHECK_EQ(br.getBits(15), (inputCTR >> 45) & 0x7fff);
1405e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        CHECK_EQ(br.getBits(1), 1u);
1406e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        CHECK_EQ(br.getBits(15), (inputCTR >> 30) & 0x7fff);
1407e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        CHECK_EQ(br.getBits(1), 1u);
1408e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        CHECK_EQ(br.getBits(15), (inputCTR >> 15) & 0x7fff);
1409e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        CHECK_EQ(br.getBits(1), 1u);
1410e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        CHECK_EQ(br.getBits(15), inputCTR & 0x7fff);
1411e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber        CHECK_EQ(br.getBits(1), 1u);
1412e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber#endif
1413e399acc9d9f3b7af72106c4209e4bb40de37aa6aAndreas Huber
141428e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        flags |= TSPacketizer::IS_ENCRYPTED;
141528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    }
141628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
141728e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    int64_t timeUs = ALooper::GetNowUs();
141828e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    if (mPrevTimeUs < 0ll || mPrevTimeUs + 100000ll <= timeUs) {
141928e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        flags |= TSPacketizer::EMIT_PCR;
142028e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        flags |= TSPacketizer::EMIT_PAT_AND_PMT;
142128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
142228e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        mPrevTimeUs = timeUs;
142328e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    }
142428e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
142528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    sp<ABuffer> packets;
142628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    mPacketizer->packetize(
142728e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            track->packetizerTrackIndex(), accessUnit, &packets, flags,
1428019aabab44e396d9a68c8126c9e0745162a4603aAndreas Huber            !isHDCPEncrypted ? NULL : HDCP_private_data,
1429019aabab44e396d9a68c8126c9e0745162a4603aAndreas Huber            !isHDCPEncrypted ? 0 : sizeof(HDCP_private_data));
143028e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
143128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    for (size_t offset = 0;
143228e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            offset < packets->size(); offset += 188) {
143328e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        bool lastTSPacket = (offset + 188 >= packets->size());
143428e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
143528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        // We're only going to flush video, audio packets are
143628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        // much more frequent and would waste all that space
143728e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        // available in a full sized UDP packet.
143828e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        bool flush =
143928e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            lastTSPacket
144028e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                && ((ssize_t)trackIndex == mVideoTrackIndex);
144128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
144228e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        appendTSData(
144328e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                packets->data() + offset,
144428e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                188,
144528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                true /* timeDiscontinuity */,
144628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                flush);
144728e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    }
144828e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
144928e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber#if LOG_TRANSPORT_STREAM
145028e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    if (mLogFile != NULL) {
145128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        fwrite(packets->data(), 1, packets->size(), mLogFile);
145228e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    }
145328e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber#endif
145428e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
145528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    return OK;
145628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber}
145728e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
145828e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huberstatus_t WifiDisplaySource::PlaybackSession::packetizeQueuedAccessUnits() {
145928e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    for (;;) {
146028e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        bool gotMoreData = false;
146128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        for (size_t i = 0; i < mTracks.size(); ++i) {
146228e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            size_t trackIndex = mTracks.keyAt(i);
146328e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            const sp<Track> &track = mTracks.valueAt(i);
146428e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
146528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            sp<ABuffer> accessUnit = track->dequeueAccessUnit();
146628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            if (accessUnit != NULL) {
146728e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                status_t err = packetizeAccessUnit(trackIndex, accessUnit);
146828e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
146928e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                if (err != OK) {
147028e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                    return err;
147128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                }
147228e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
147328e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber                gotMoreData = true;
147428e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            }
147528e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        }
147628e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
147728e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        if (!gotMoreData) {
147828e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber            break;
147928e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber        }
148028e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    }
148128e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
148228e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber    return OK;
148328e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber}
148428e17ed7e2fbb254fb99481b74db85e427c905eeAndreas Huber
1485d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber}  // namespace android
1486d7bee3a9d2ad76d073d91f0ee36d5ac5f9df480cAndreas Huber
1487