PlaybackSession.cpp revision 5131d127a042ee88f903370be88845dc8c9f8578
1/*
2 * Copyright 2012, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "PlaybackSession"
19#include <utils/Log.h>
20
21#include "PlaybackSession.h"
22
23#include "Converter.h"
24#include "MediaPuller.h"
25#include "RepeaterSource.h"
26#include "Sender.h"
27#include "TSPacketizer.h"
28#include "include/avc_utils.h"
29#include "WifiDisplaySource.h"
30
31#include <binder/IServiceManager.h>
32#include <gui/ISurfaceComposer.h>
33#include <gui/SurfaceComposerClient.h>
34#include <media/IHDCP.h>
35#include <media/stagefright/foundation/ABitReader.h>
36#include <media/stagefright/foundation/ABuffer.h>
37#include <media/stagefright/foundation/ADebug.h>
38#include <media/stagefright/foundation/AMessage.h>
39#include <media/stagefright/foundation/hexdump.h>
40#include <media/stagefright/AudioSource.h>
41#include <media/stagefright/DataSource.h>
42#include <media/stagefright/MediaDefs.h>
43#include <media/stagefright/MediaErrors.h>
44#include <media/stagefright/MediaExtractor.h>
45#include <media/stagefright/MediaSource.h>
46#include <media/stagefright/MetaData.h>
47#include <media/stagefright/MPEG2TSWriter.h>
48#include <media/stagefright/SurfaceMediaSource.h>
49#include <media/stagefright/Utils.h>
50
51#include <OMX_IVCommon.h>
52
53namespace android {
54
55struct WifiDisplaySource::PlaybackSession::Track : public AHandler {
56    enum {
57        kWhatStopped,
58    };
59
60    Track(const sp<AMessage> &notify,
61          const sp<ALooper> &pullLooper,
62          const sp<ALooper> &codecLooper,
63          const sp<MediaPuller> &mediaPuller,
64          const sp<Converter> &converter);
65
66    void setRepeaterSource(const sp<RepeaterSource> &source);
67
68    sp<AMessage> getFormat();
69    bool isAudio() const;
70
71    const sp<Converter> &converter() const;
72    ssize_t packetizerTrackIndex() const;
73
74    void setPacketizerTrackIndex(size_t index);
75
76    status_t start();
77    void stopAsync();
78
79    void pause();
80    void resume();
81
82    void queueAccessUnit(const sp<ABuffer> &accessUnit);
83    sp<ABuffer> dequeueAccessUnit();
84
85    bool hasOutputBuffer(int64_t *timeUs) const;
86    void queueOutputBuffer(const sp<ABuffer> &accessUnit);
87    sp<ABuffer> dequeueOutputBuffer();
88
89#if SUSPEND_VIDEO_IF_IDLE
90    bool isSuspended() const;
91#endif
92
93    size_t countQueuedOutputBuffers() const {
94        return mQueuedOutputBuffers.size();
95    }
96
97    void requestIDRFrame();
98
99protected:
100    virtual void onMessageReceived(const sp<AMessage> &msg);
101    virtual ~Track();
102
103private:
104    enum {
105        kWhatMediaPullerStopped,
106    };
107
108    sp<AMessage> mNotify;
109    sp<ALooper> mPullLooper;
110    sp<ALooper> mCodecLooper;
111    sp<MediaPuller> mMediaPuller;
112    sp<Converter> mConverter;
113    bool mStarted;
114    ssize_t mPacketizerTrackIndex;
115    bool mIsAudio;
116    List<sp<ABuffer> > mQueuedAccessUnits;
117    sp<RepeaterSource> mRepeaterSource;
118    List<sp<ABuffer> > mQueuedOutputBuffers;
119    int64_t mLastOutputBufferQueuedTimeUs;
120
121    static bool IsAudioFormat(const sp<AMessage> &format);
122
123    DISALLOW_EVIL_CONSTRUCTORS(Track);
124};
125
126WifiDisplaySource::PlaybackSession::Track::Track(
127        const sp<AMessage> &notify,
128        const sp<ALooper> &pullLooper,
129        const sp<ALooper> &codecLooper,
130        const sp<MediaPuller> &mediaPuller,
131        const sp<Converter> &converter)
132    : mNotify(notify),
133      mPullLooper(pullLooper),
134      mCodecLooper(codecLooper),
135      mMediaPuller(mediaPuller),
136      mConverter(converter),
137      mStarted(false),
138      mPacketizerTrackIndex(-1),
139      mIsAudio(IsAudioFormat(mConverter->getOutputFormat())),
140      mLastOutputBufferQueuedTimeUs(-1ll) {
141}
142
143WifiDisplaySource::PlaybackSession::Track::~Track() {
144    CHECK(!mStarted);
145}
146
147// static
148bool WifiDisplaySource::PlaybackSession::Track::IsAudioFormat(
149        const sp<AMessage> &format) {
150    AString mime;
151    CHECK(format->findString("mime", &mime));
152
153    return !strncasecmp(mime.c_str(), "audio/", 6);
154}
155
156sp<AMessage> WifiDisplaySource::PlaybackSession::Track::getFormat() {
157    return mConverter->getOutputFormat();
158}
159
160bool WifiDisplaySource::PlaybackSession::Track::isAudio() const {
161    return mIsAudio;
162}
163
164const sp<Converter> &WifiDisplaySource::PlaybackSession::Track::converter() const {
165    return mConverter;
166}
167
168ssize_t WifiDisplaySource::PlaybackSession::Track::packetizerTrackIndex() const {
169    return mPacketizerTrackIndex;
170}
171
172void WifiDisplaySource::PlaybackSession::Track::setPacketizerTrackIndex(size_t index) {
173    CHECK_LT(mPacketizerTrackIndex, 0);
174    mPacketizerTrackIndex = index;
175}
176
177status_t WifiDisplaySource::PlaybackSession::Track::start() {
178    ALOGV("Track::start isAudio=%d", mIsAudio);
179
180    CHECK(!mStarted);
181
182    status_t err = OK;
183
184    if (mMediaPuller != NULL) {
185        err = mMediaPuller->start();
186    }
187
188    if (err == OK) {
189        mStarted = true;
190    }
191
192    return err;
193}
194
195void WifiDisplaySource::PlaybackSession::Track::stopAsync() {
196    ALOGV("Track::stopAsync isAudio=%d", mIsAudio);
197
198    mConverter->shutdownAsync();
199
200    sp<AMessage> msg = new AMessage(kWhatMediaPullerStopped, id());
201
202    if (mStarted && mMediaPuller != NULL) {
203        if (mRepeaterSource != NULL) {
204            // Let's unblock MediaPuller's MediaSource::read().
205            mRepeaterSource->wakeUp();
206        }
207
208        mMediaPuller->stopAsync(msg);
209    } else {
210        msg->post();
211    }
212}
213
214void WifiDisplaySource::PlaybackSession::Track::pause() {
215    mMediaPuller->pause();
216}
217
218void WifiDisplaySource::PlaybackSession::Track::resume() {
219    mMediaPuller->resume();
220}
221
222void WifiDisplaySource::PlaybackSession::Track::onMessageReceived(
223        const sp<AMessage> &msg) {
224    switch (msg->what()) {
225        case kWhatMediaPullerStopped:
226        {
227            mConverter.clear();
228
229            mStarted = false;
230
231            sp<AMessage> notify = mNotify->dup();
232            notify->setInt32("what", kWhatStopped);
233            notify->post();
234
235            ALOGI("kWhatStopped %s posted", mIsAudio ? "audio" : "video");
236            break;
237        }
238
239        default:
240            TRESPASS();
241    }
242}
243
244void WifiDisplaySource::PlaybackSession::Track::queueAccessUnit(
245        const sp<ABuffer> &accessUnit) {
246    mQueuedAccessUnits.push_back(accessUnit);
247}
248
249sp<ABuffer> WifiDisplaySource::PlaybackSession::Track::dequeueAccessUnit() {
250    if (mQueuedAccessUnits.empty()) {
251        return NULL;
252    }
253
254    sp<ABuffer> accessUnit = *mQueuedAccessUnits.begin();
255    CHECK(accessUnit != NULL);
256
257    mQueuedAccessUnits.erase(mQueuedAccessUnits.begin());
258
259    return accessUnit;
260}
261
262void WifiDisplaySource::PlaybackSession::Track::setRepeaterSource(
263        const sp<RepeaterSource> &source) {
264    mRepeaterSource = source;
265}
266
267void WifiDisplaySource::PlaybackSession::Track::requestIDRFrame() {
268    if (mIsAudio) {
269        return;
270    }
271
272    if (mRepeaterSource != NULL) {
273        mRepeaterSource->wakeUp();
274    }
275
276    mConverter->requestIDRFrame();
277}
278
279bool WifiDisplaySource::PlaybackSession::Track::hasOutputBuffer(
280        int64_t *timeUs) const {
281    *timeUs = 0ll;
282
283    if (mQueuedOutputBuffers.empty()) {
284        return false;
285    }
286
287    const sp<ABuffer> &outputBuffer = *mQueuedOutputBuffers.begin();
288
289    CHECK(outputBuffer->meta()->findInt64("timeUs", timeUs));
290
291    return true;
292}
293
294void WifiDisplaySource::PlaybackSession::Track::queueOutputBuffer(
295        const sp<ABuffer> &accessUnit) {
296    mQueuedOutputBuffers.push_back(accessUnit);
297    mLastOutputBufferQueuedTimeUs = ALooper::GetNowUs();
298}
299
300sp<ABuffer> WifiDisplaySource::PlaybackSession::Track::dequeueOutputBuffer() {
301    CHECK(!mQueuedOutputBuffers.empty());
302
303    sp<ABuffer> outputBuffer = *mQueuedOutputBuffers.begin();
304    mQueuedOutputBuffers.erase(mQueuedOutputBuffers.begin());
305
306    return outputBuffer;
307}
308
309#if SUSPEND_VIDEO_IF_IDLE
310bool WifiDisplaySource::PlaybackSession::Track::isSuspended() const {
311    if (!mQueuedOutputBuffers.empty()) {
312        return false;
313    }
314
315    if (mLastOutputBufferQueuedTimeUs < 0ll) {
316        // We've never seen an output buffer queued, but tracks start
317        // out live, not suspended.
318        return false;
319    }
320
321    // If we've not seen new output data for 60ms or more, we consider
322    // this track suspended for the time being.
323    return (ALooper::GetNowUs() - mLastOutputBufferQueuedTimeUs) > 60000ll;
324}
325#endif
326
327////////////////////////////////////////////////////////////////////////////////
328
329WifiDisplaySource::PlaybackSession::PlaybackSession(
330        const sp<ANetworkSession> &netSession,
331        const sp<AMessage> &notify,
332        const in_addr &interfaceAddr,
333        const sp<IHDCP> &hdcp)
334    : mNetSession(netSession),
335      mNotify(notify),
336      mInterfaceAddr(interfaceAddr),
337      mHDCP(hdcp),
338      mWeAreDead(false),
339      mPaused(false),
340      mLastLifesignUs(),
341      mVideoTrackIndex(-1),
342      mPrevTimeUs(-1ll),
343      mAllTracksHavePacketizerIndex(false) {
344}
345
346status_t WifiDisplaySource::PlaybackSession::init(
347        const char *clientIP, int32_t clientRtp, int32_t clientRtcp,
348        Sender::TransportMode transportMode,
349        bool usePCMAudio) {
350    status_t err = setupPacketizer(usePCMAudio);
351
352    if (err != OK) {
353        return err;
354    }
355
356    sp<AMessage> notify = new AMessage(kWhatSenderNotify, id());
357    mSender = new Sender(mNetSession, notify);
358
359    mSenderLooper = new ALooper;
360    mSenderLooper->setName("sender_looper");
361
362    mSenderLooper->start(
363            false /* runOnCallingThread */,
364            false /* canCallJava */,
365            PRIORITY_AUDIO);
366
367    mSenderLooper->registerHandler(mSender);
368
369    err = mSender->init(clientIP, clientRtp, clientRtcp, transportMode);
370
371    if (err != OK) {
372        return err;
373    }
374
375    updateLiveness();
376
377    return OK;
378}
379
380WifiDisplaySource::PlaybackSession::~PlaybackSession() {
381}
382
383int32_t WifiDisplaySource::PlaybackSession::getRTPPort() const {
384    return mSender->getRTPPort();
385}
386
387int64_t WifiDisplaySource::PlaybackSession::getLastLifesignUs() const {
388    return mLastLifesignUs;
389}
390
391void WifiDisplaySource::PlaybackSession::updateLiveness() {
392    mLastLifesignUs = ALooper::GetNowUs();
393}
394
395status_t WifiDisplaySource::PlaybackSession::play() {
396    updateLiveness();
397
398    (new AMessage(kWhatResume, id()))->post();
399
400    return OK;
401}
402
403status_t WifiDisplaySource::PlaybackSession::finishPlay() {
404    // XXX Give the dongle a second to bind its sockets.
405    (new AMessage(kWhatFinishPlay, id()))->post(1000000ll);
406    return OK;
407}
408
409status_t WifiDisplaySource::PlaybackSession::onFinishPlay() {
410    return mSender->finishInit();
411}
412
413status_t WifiDisplaySource::PlaybackSession::onFinishPlay2() {
414    mSender->scheduleSendSR();
415
416    for (size_t i = 0; i < mTracks.size(); ++i) {
417        CHECK_EQ((status_t)OK, mTracks.editValueAt(i)->start());
418    }
419
420    sp<AMessage> notify = mNotify->dup();
421    notify->setInt32("what", kWhatSessionEstablished);
422    notify->post();
423
424    return OK;
425}
426
427status_t WifiDisplaySource::PlaybackSession::pause() {
428    updateLiveness();
429
430    (new AMessage(kWhatPause, id()))->post();
431
432    return OK;
433}
434
435void WifiDisplaySource::PlaybackSession::destroyAsync() {
436    ALOGI("destroyAsync");
437
438    for (size_t i = 0; i < mTracks.size(); ++i) {
439        mTracks.valueAt(i)->stopAsync();
440    }
441}
442
443void WifiDisplaySource::PlaybackSession::onMessageReceived(
444        const sp<AMessage> &msg) {
445    switch (msg->what()) {
446        case kWhatConverterNotify:
447        {
448            if (mWeAreDead) {
449                ALOGV("dropping msg '%s' because we're dead",
450                      msg->debugString().c_str());
451
452                break;
453            }
454
455            int32_t what;
456            CHECK(msg->findInt32("what", &what));
457
458            size_t trackIndex;
459            CHECK(msg->findSize("trackIndex", &trackIndex));
460
461            if (what == Converter::kWhatAccessUnit) {
462                const sp<Track> &track = mTracks.valueFor(trackIndex);
463
464                ssize_t packetizerTrackIndex = track->packetizerTrackIndex();
465
466                if (packetizerTrackIndex < 0) {
467                    sp<AMessage> trackFormat = track->getFormat()->dup();
468                    if (mHDCP != NULL && !track->isAudio()) {
469                        // HDCP2.0 _and_ HDCP 2.1 specs say to set the version
470                        // inside the HDCP descriptor to 0x20!!!
471                        trackFormat->setInt32("hdcp-version", 0x20);
472                    }
473                    packetizerTrackIndex = mPacketizer->addTrack(trackFormat);
474
475                    CHECK_GE(packetizerTrackIndex, 0);
476
477                    track->setPacketizerTrackIndex(packetizerTrackIndex);
478
479                    if (allTracksHavePacketizerIndex()) {
480                        status_t err = packetizeQueuedAccessUnits();
481
482                        if (err != OK) {
483                            notifySessionDead();
484                            break;
485                        }
486                    }
487                }
488
489                sp<ABuffer> accessUnit;
490                CHECK(msg->findBuffer("accessUnit", &accessUnit));
491
492                if (!allTracksHavePacketizerIndex()) {
493                    track->queueAccessUnit(accessUnit);
494                    break;
495                }
496
497                track->queueOutputBuffer(accessUnit);
498
499                drainAccessUnits();
500                break;
501            } else if (what == Converter::kWhatEOS) {
502                CHECK_EQ(what, Converter::kWhatEOS);
503
504                ALOGI("output EOS on track %d", trackIndex);
505
506                ssize_t index = mTracks.indexOfKey(trackIndex);
507                CHECK_GE(index, 0);
508
509                const sp<Converter> &converter =
510                    mTracks.valueAt(index)->converter();
511                looper()->unregisterHandler(converter->id());
512
513                mTracks.removeItemsAt(index);
514
515                if (mTracks.isEmpty()) {
516                    ALOGI("Reached EOS");
517                }
518            } else {
519                CHECK_EQ(what, Converter::kWhatError);
520
521                status_t err;
522                CHECK(msg->findInt32("err", &err));
523
524                ALOGE("converter signaled error %d", err);
525
526                notifySessionDead();
527            }
528            break;
529        }
530
531        case kWhatSenderNotify:
532        {
533            int32_t what;
534            CHECK(msg->findInt32("what", &what));
535
536            if (what == Sender::kWhatInitDone) {
537                onFinishPlay2();
538            } else if (what == Sender::kWhatSessionDead) {
539                notifySessionDead();
540            } else {
541                TRESPASS();
542            }
543
544            break;
545        }
546
547        case kWhatFinishPlay:
548        {
549            onFinishPlay();
550            break;
551        }
552
553        case kWhatTrackNotify:
554        {
555            int32_t what;
556            CHECK(msg->findInt32("what", &what));
557
558            size_t trackIndex;
559            CHECK(msg->findSize("trackIndex", &trackIndex));
560
561            if (what == Track::kWhatStopped) {
562                ALOGI("Track %d stopped", trackIndex);
563
564                sp<Track> track = mTracks.valueFor(trackIndex);
565                looper()->unregisterHandler(track->id());
566                mTracks.removeItem(trackIndex);
567                track.clear();
568
569                if (!mTracks.isEmpty()) {
570                    ALOGI("not all tracks are stopped yet");
571                    break;
572                }
573
574                mSenderLooper->unregisterHandler(mSender->id());
575                mSender.clear();
576                mSenderLooper.clear();
577
578                mPacketizer.clear();
579
580                sp<AMessage> notify = mNotify->dup();
581                notify->setInt32("what", kWhatSessionDestroyed);
582                notify->post();
583            }
584            break;
585        }
586
587        case kWhatPacketize:
588        {
589            size_t trackIndex;
590            CHECK(msg->findSize("trackIndex", &trackIndex));
591
592            sp<ABuffer> accessUnit;
593            CHECK(msg->findBuffer("accessUnit", &accessUnit));
594
595#if 0
596            if ((ssize_t)trackIndex == mVideoTrackIndex) {
597                int64_t nowUs = ALooper::GetNowUs();
598                static int64_t prevNowUs = 0ll;
599
600                ALOGI("sending AU, dNowUs=%lld us", nowUs - prevNowUs);
601
602                prevNowUs = nowUs;
603            }
604#endif
605
606            break;
607        }
608
609        case kWhatPause:
610        {
611            if (mPaused) {
612                break;
613            }
614
615            for (size_t i = 0; i < mTracks.size(); ++i) {
616                mTracks.editValueAt(i)->pause();
617            }
618
619            mPaused = true;
620            break;
621        }
622
623        case kWhatResume:
624        {
625            if (!mPaused) {
626                break;
627            }
628
629            for (size_t i = 0; i < mTracks.size(); ++i) {
630                mTracks.editValueAt(i)->resume();
631            }
632
633            mPaused = false;
634            break;
635        }
636
637        default:
638            TRESPASS();
639    }
640}
641
642status_t WifiDisplaySource::PlaybackSession::setupPacketizer(bool usePCMAudio) {
643    mPacketizer = new TSPacketizer;
644
645    status_t err = addVideoSource();
646
647    if (err != OK) {
648        return err;
649    }
650
651    return addAudioSource(usePCMAudio);
652}
653
654status_t WifiDisplaySource::PlaybackSession::addSource(
655        bool isVideo, const sp<MediaSource> &source, bool isRepeaterSource,
656        bool usePCMAudio, size_t *numInputBuffers) {
657    CHECK(!usePCMAudio || !isVideo);
658    CHECK(!isRepeaterSource || isVideo);
659
660    sp<ALooper> pullLooper = new ALooper;
661    pullLooper->setName("pull_looper");
662
663    pullLooper->start(
664            false /* runOnCallingThread */,
665            false /* canCallJava */,
666            PRIORITY_AUDIO);
667
668    sp<ALooper> codecLooper = new ALooper;
669    codecLooper->setName("codec_looper");
670
671    codecLooper->start(
672            false /* runOnCallingThread */,
673            false /* canCallJava */,
674            PRIORITY_AUDIO);
675
676    size_t trackIndex;
677
678    sp<AMessage> notify;
679
680    trackIndex = mTracks.size();
681
682    sp<AMessage> format;
683    status_t err = convertMetaDataToMessage(source->getFormat(), &format);
684    CHECK_EQ(err, (status_t)OK);
685
686    if (isVideo) {
687        format->setInt32("store-metadata-in-buffers", true);
688
689        format->setInt32(
690                "color-format", OMX_COLOR_FormatAndroidOpaque);
691    }
692
693    notify = new AMessage(kWhatConverterNotify, id());
694    notify->setSize("trackIndex", trackIndex);
695
696    sp<Converter> converter =
697        new Converter(notify, codecLooper, format, usePCMAudio);
698
699    err = converter->initCheck();
700    if (err != OK) {
701        ALOGE("%s converter returned err %d", isVideo ? "video" : "audio", err);
702        return err;
703    }
704
705    looper()->registerHandler(converter);
706
707    notify = new AMessage(Converter::kWhatMediaPullerNotify, converter->id());
708    notify->setSize("trackIndex", trackIndex);
709
710    sp<MediaPuller> puller = new MediaPuller(source, notify);
711    pullLooper->registerHandler(puller);
712
713    if (numInputBuffers != NULL) {
714        *numInputBuffers = converter->getInputBufferCount();
715    }
716
717    notify = new AMessage(kWhatTrackNotify, id());
718    notify->setSize("trackIndex", trackIndex);
719
720    sp<Track> track = new Track(
721            notify, pullLooper, codecLooper, puller, converter);
722
723    if (isRepeaterSource) {
724        track->setRepeaterSource(static_cast<RepeaterSource *>(source.get()));
725    }
726
727    looper()->registerHandler(track);
728
729    mTracks.add(trackIndex, track);
730
731    if (isVideo) {
732        mVideoTrackIndex = trackIndex;
733    }
734
735    return OK;
736}
737
738status_t WifiDisplaySource::PlaybackSession::addVideoSource() {
739    sp<SurfaceMediaSource> source = new SurfaceMediaSource(width(), height());
740
741    source->setUseAbsoluteTimestamps();
742
743#if 1
744    sp<RepeaterSource> videoSource =
745        new RepeaterSource(source, 30.0 /* rateHz */);
746#endif
747
748#if 1
749    size_t numInputBuffers;
750    status_t err = addSource(
751            true /* isVideo */, videoSource, true /* isRepeaterSource */,
752            false /* usePCMAudio */, &numInputBuffers);
753#else
754    size_t numInputBuffers;
755    status_t err = addSource(
756            true /* isVideo */, source, false /* isRepeaterSource */,
757            false /* usePCMAudio */, &numInputBuffers);
758#endif
759
760    if (err != OK) {
761        return err;
762    }
763
764    err = source->setMaxAcquiredBufferCount(numInputBuffers);
765    CHECK_EQ(err, (status_t)OK);
766
767    mBufferQueue = source->getBufferQueue();
768
769    return OK;
770}
771
772status_t WifiDisplaySource::PlaybackSession::addAudioSource(bool usePCMAudio) {
773    sp<AudioSource> audioSource = new AudioSource(
774            AUDIO_SOURCE_REMOTE_SUBMIX,
775            48000 /* sampleRate */,
776            2 /* channelCount */);
777
778    if (audioSource->initCheck() == OK) {
779        return addSource(
780                false /* isVideo */, audioSource, false /* isRepeaterSource */,
781                usePCMAudio, NULL /* numInputBuffers */);
782    }
783
784    ALOGW("Unable to instantiate audio source");
785
786    return OK;
787}
788
789sp<ISurfaceTexture> WifiDisplaySource::PlaybackSession::getSurfaceTexture() {
790    return mBufferQueue;
791}
792
793int32_t WifiDisplaySource::PlaybackSession::width() const {
794#if USE_1080P
795    return 1920;
796#else
797    return 1280;
798#endif
799}
800
801int32_t WifiDisplaySource::PlaybackSession::height() const {
802#if USE_1080P
803    return 1080;
804#else
805    return 720;
806#endif
807}
808
809void WifiDisplaySource::PlaybackSession::requestIDRFrame() {
810    for (size_t i = 0; i < mTracks.size(); ++i) {
811        const sp<Track> &track = mTracks.valueAt(i);
812
813        track->requestIDRFrame();
814    }
815}
816
817bool WifiDisplaySource::PlaybackSession::allTracksHavePacketizerIndex() {
818    if (mAllTracksHavePacketizerIndex) {
819        return true;
820    }
821
822    for (size_t i = 0; i < mTracks.size(); ++i) {
823        if (mTracks.valueAt(i)->packetizerTrackIndex() < 0) {
824            return false;
825        }
826    }
827
828    mAllTracksHavePacketizerIndex = true;
829
830    return true;
831}
832
833status_t WifiDisplaySource::PlaybackSession::packetizeAccessUnit(
834        size_t trackIndex, sp<ABuffer> accessUnit,
835        sp<ABuffer> *packets) {
836    const sp<Track> &track = mTracks.valueFor(trackIndex);
837
838    uint32_t flags = 0;
839
840    bool isHDCPEncrypted = false;
841    uint64_t inputCTR;
842    uint8_t HDCP_private_data[16];
843
844    bool manuallyPrependSPSPPS =
845        !track->isAudio()
846        && track->converter()->needToManuallyPrependSPSPPS()
847        && IsIDR(accessUnit);
848
849    if (mHDCP != NULL && !track->isAudio()) {
850        isHDCPEncrypted = true;
851
852        if (manuallyPrependSPSPPS) {
853            accessUnit = mPacketizer->prependCSD(
854                    track->packetizerTrackIndex(), accessUnit);
855        }
856
857        status_t err = mHDCP->encrypt(
858                accessUnit->data(), accessUnit->size(),
859                trackIndex  /* streamCTR */,
860                &inputCTR,
861                accessUnit->data());
862
863        if (err != OK) {
864            ALOGE("Failed to HDCP-encrypt media data (err %d)",
865                  err);
866
867            return err;
868        }
869
870        HDCP_private_data[0] = 0x00;
871
872        HDCP_private_data[1] =
873            (((trackIndex >> 30) & 3) << 1) | 1;
874
875        HDCP_private_data[2] = (trackIndex >> 22) & 0xff;
876
877        HDCP_private_data[3] =
878            (((trackIndex >> 15) & 0x7f) << 1) | 1;
879
880        HDCP_private_data[4] = (trackIndex >> 7) & 0xff;
881
882        HDCP_private_data[5] =
883            ((trackIndex & 0x7f) << 1) | 1;
884
885        HDCP_private_data[6] = 0x00;
886
887        HDCP_private_data[7] =
888            (((inputCTR >> 60) & 0x0f) << 1) | 1;
889
890        HDCP_private_data[8] = (inputCTR >> 52) & 0xff;
891
892        HDCP_private_data[9] =
893            (((inputCTR >> 45) & 0x7f) << 1) | 1;
894
895        HDCP_private_data[10] = (inputCTR >> 37) & 0xff;
896
897        HDCP_private_data[11] =
898            (((inputCTR >> 30) & 0x7f) << 1) | 1;
899
900        HDCP_private_data[12] = (inputCTR >> 22) & 0xff;
901
902        HDCP_private_data[13] =
903            (((inputCTR >> 15) & 0x7f) << 1) | 1;
904
905        HDCP_private_data[14] = (inputCTR >> 7) & 0xff;
906
907        HDCP_private_data[15] =
908            ((inputCTR & 0x7f) << 1) | 1;
909
910#if 0
911        ALOGI("HDCP_private_data:");
912        hexdump(HDCP_private_data, sizeof(HDCP_private_data));
913
914        ABitReader br(HDCP_private_data, sizeof(HDCP_private_data));
915        CHECK_EQ(br.getBits(13), 0);
916        CHECK_EQ(br.getBits(2), (trackIndex >> 30) & 3);
917        CHECK_EQ(br.getBits(1), 1u);
918        CHECK_EQ(br.getBits(15), (trackIndex >> 15) & 0x7fff);
919        CHECK_EQ(br.getBits(1), 1u);
920        CHECK_EQ(br.getBits(15), trackIndex & 0x7fff);
921        CHECK_EQ(br.getBits(1), 1u);
922        CHECK_EQ(br.getBits(11), 0);
923        CHECK_EQ(br.getBits(4), (inputCTR >> 60) & 0xf);
924        CHECK_EQ(br.getBits(1), 1u);
925        CHECK_EQ(br.getBits(15), (inputCTR >> 45) & 0x7fff);
926        CHECK_EQ(br.getBits(1), 1u);
927        CHECK_EQ(br.getBits(15), (inputCTR >> 30) & 0x7fff);
928        CHECK_EQ(br.getBits(1), 1u);
929        CHECK_EQ(br.getBits(15), (inputCTR >> 15) & 0x7fff);
930        CHECK_EQ(br.getBits(1), 1u);
931        CHECK_EQ(br.getBits(15), inputCTR & 0x7fff);
932        CHECK_EQ(br.getBits(1), 1u);
933#endif
934
935        flags |= TSPacketizer::IS_ENCRYPTED;
936    } else if (manuallyPrependSPSPPS) {
937        flags |= TSPacketizer::PREPEND_SPS_PPS_TO_IDR_FRAMES;
938    }
939
940    int64_t timeUs = ALooper::GetNowUs();
941    if (mPrevTimeUs < 0ll || mPrevTimeUs + 100000ll <= timeUs) {
942        flags |= TSPacketizer::EMIT_PCR;
943        flags |= TSPacketizer::EMIT_PAT_AND_PMT;
944
945        mPrevTimeUs = timeUs;
946    }
947
948    mPacketizer->packetize(
949            track->packetizerTrackIndex(), accessUnit, packets, flags,
950            !isHDCPEncrypted ? NULL : HDCP_private_data,
951            !isHDCPEncrypted ? 0 : sizeof(HDCP_private_data),
952            track->isAudio() ? 2 : 0 /* numStuffingBytes */);
953
954    return OK;
955}
956
957status_t WifiDisplaySource::PlaybackSession::packetizeQueuedAccessUnits() {
958    for (;;) {
959        bool gotMoreData = false;
960        for (size_t i = 0; i < mTracks.size(); ++i) {
961            size_t trackIndex = mTracks.keyAt(i);
962            const sp<Track> &track = mTracks.valueAt(i);
963
964            sp<ABuffer> accessUnit = track->dequeueAccessUnit();
965            if (accessUnit != NULL) {
966                track->queueOutputBuffer(accessUnit);
967                gotMoreData = true;
968            }
969        }
970
971        if (!gotMoreData) {
972            break;
973        }
974    }
975
976    return OK;
977}
978
979void WifiDisplaySource::PlaybackSession::notifySessionDead() {
980    // Inform WifiDisplaySource of our premature death (wish).
981    sp<AMessage> notify = mNotify->dup();
982    notify->setInt32("what", kWhatSessionDead);
983    notify->post();
984
985    mWeAreDead = true;
986}
987
988void WifiDisplaySource::PlaybackSession::drainAccessUnits() {
989    ALOGV("audio/video has %d/%d buffers ready.",
990            mTracks.valueFor(1)->countQueuedOutputBuffers(),
991            mTracks.valueFor(0)->countQueuedOutputBuffers());
992
993    while (drainAccessUnit()) {
994    }
995}
996
997bool WifiDisplaySource::PlaybackSession::drainAccessUnit() {
998    ssize_t minTrackIndex = -1;
999    int64_t minTimeUs = -1ll;
1000
1001    for (size_t i = 0; i < mTracks.size(); ++i) {
1002        const sp<Track> &track = mTracks.valueAt(i);
1003
1004        int64_t timeUs;
1005        if (track->hasOutputBuffer(&timeUs)) {
1006            if (minTrackIndex < 0 || timeUs < minTimeUs) {
1007                minTrackIndex = mTracks.keyAt(i);
1008                minTimeUs = timeUs;
1009            }
1010        }
1011#if SUSPEND_VIDEO_IF_IDLE
1012        else if (!track->isSuspended()) {
1013            // We still consider this track "live", so it should keep
1014            // delivering output data whose time stamps we'll have to
1015            // consider for proper interleaving.
1016            return false;
1017        }
1018#else
1019        else {
1020            // We need access units available on all tracks to be able to
1021            // dequeue the earliest one.
1022            return false;
1023        }
1024#endif
1025    }
1026
1027    if (minTrackIndex < 0) {
1028        return false;
1029    }
1030
1031    const sp<Track> &track = mTracks.valueFor(minTrackIndex);
1032    sp<ABuffer> accessUnit = track->dequeueOutputBuffer();
1033
1034    sp<ABuffer> packets;
1035    status_t err = packetizeAccessUnit(minTrackIndex, accessUnit, &packets);
1036
1037    if (err != OK) {
1038        notifySessionDead();
1039        return false;
1040    }
1041
1042    if ((ssize_t)minTrackIndex == mVideoTrackIndex) {
1043        packets->meta()->setInt32("isVideo", 1);
1044    }
1045    mSender->queuePackets(minTimeUs, packets);
1046
1047#if 0
1048    if (minTrackIndex == mVideoTrackIndex) {
1049        int64_t nowUs = ALooper::GetNowUs();
1050
1051        // Latency from "data acquired" to "ready to send if we wanted to".
1052        ALOGI("[%s] latencyUs = %lld ms",
1053              minTrackIndex == mVideoTrackIndex ? "video" : "audio",
1054              (nowUs - minTimeUs) / 1000ll);
1055    }
1056#endif
1057
1058    return true;
1059}
1060
1061}  // namespace android
1062
1063