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