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 "include/avc_utils.h"
27#include "WifiDisplaySource.h"
28
29#include <binder/IServiceManager.h>
30#include <cutils/properties.h>
31#include <media/IHDCP.h>
32#include <media/stagefright/foundation/ABitReader.h>
33#include <media/stagefright/foundation/ABuffer.h>
34#include <media/stagefright/foundation/ADebug.h>
35#include <media/stagefright/foundation/AMessage.h>
36#include <media/stagefright/foundation/hexdump.h>
37#include <media/stagefright/AudioSource.h>
38#include <media/stagefright/DataSource.h>
39#include <media/stagefright/MediaDefs.h>
40#include <media/stagefright/MediaErrors.h>
41#include <media/stagefright/MediaSource.h>
42#include <media/stagefright/MetaData.h>
43#include <media/stagefright/NuMediaExtractor.h>
44#include <media/stagefright/SurfaceMediaSource.h>
45#include <media/stagefright/Utils.h>
46
47#include <OMX_IVCommon.h>
48
49namespace android {
50
51struct WifiDisplaySource::PlaybackSession::Track : public AHandler {
52    enum {
53        kWhatStopped,
54    };
55
56    Track(const sp<AMessage> &notify,
57          const sp<ALooper> &pullLooper,
58          const sp<ALooper> &codecLooper,
59          const sp<MediaPuller> &mediaPuller,
60          const sp<Converter> &converter);
61
62    Track(const sp<AMessage> &notify, const sp<AMessage> &format);
63
64    void setRepeaterSource(const sp<RepeaterSource> &source);
65
66    sp<AMessage> getFormat();
67    bool isAudio() const;
68
69    const sp<Converter> &converter() const;
70    const sp<RepeaterSource> &repeaterSource() const;
71
72    ssize_t mediaSenderTrackIndex() const;
73    void setMediaSenderTrackIndex(size_t index);
74
75    status_t start();
76    void stopAsync();
77
78    void pause();
79    void resume();
80
81    void queueAccessUnit(const sp<ABuffer> &accessUnit);
82    sp<ABuffer> dequeueAccessUnit();
83
84    bool hasOutputBuffer(int64_t *timeUs) const;
85    void queueOutputBuffer(const sp<ABuffer> &accessUnit);
86    sp<ABuffer> dequeueOutputBuffer();
87
88#if SUSPEND_VIDEO_IF_IDLE
89    bool isSuspended() const;
90#endif
91
92    size_t countQueuedOutputBuffers() const {
93        return mQueuedOutputBuffers.size();
94    }
95
96    void requestIDRFrame();
97
98protected:
99    virtual void onMessageReceived(const sp<AMessage> &msg);
100    virtual ~Track();
101
102private:
103    enum {
104        kWhatMediaPullerStopped,
105    };
106
107    sp<AMessage> mNotify;
108    sp<ALooper> mPullLooper;
109    sp<ALooper> mCodecLooper;
110    sp<MediaPuller> mMediaPuller;
111    sp<Converter> mConverter;
112    sp<AMessage> mFormat;
113    bool mStarted;
114    ssize_t mMediaSenderTrackIndex;
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      mIsAudio(IsAudioFormat(mConverter->getOutputFormat())),
139      mLastOutputBufferQueuedTimeUs(-1ll) {
140}
141
142WifiDisplaySource::PlaybackSession::Track::Track(
143        const sp<AMessage> &notify, const sp<AMessage> &format)
144    : mNotify(notify),
145      mFormat(format),
146      mStarted(false),
147      mIsAudio(IsAudioFormat(format)),
148      mLastOutputBufferQueuedTimeUs(-1ll) {
149}
150
151WifiDisplaySource::PlaybackSession::Track::~Track() {
152    CHECK(!mStarted);
153}
154
155// static
156bool WifiDisplaySource::PlaybackSession::Track::IsAudioFormat(
157        const sp<AMessage> &format) {
158    AString mime;
159    CHECK(format->findString("mime", &mime));
160
161    return !strncasecmp(mime.c_str(), "audio/", 6);
162}
163
164sp<AMessage> WifiDisplaySource::PlaybackSession::Track::getFormat() {
165    return mFormat != NULL ? mFormat : mConverter->getOutputFormat();
166}
167
168bool WifiDisplaySource::PlaybackSession::Track::isAudio() const {
169    return mIsAudio;
170}
171
172const sp<Converter> &WifiDisplaySource::PlaybackSession::Track::converter() const {
173    return mConverter;
174}
175
176const sp<RepeaterSource> &
177WifiDisplaySource::PlaybackSession::Track::repeaterSource() const {
178    return mRepeaterSource;
179}
180
181ssize_t WifiDisplaySource::PlaybackSession::Track::mediaSenderTrackIndex() const {
182    CHECK_GE(mMediaSenderTrackIndex, 0);
183    return mMediaSenderTrackIndex;
184}
185
186void WifiDisplaySource::PlaybackSession::Track::setMediaSenderTrackIndex(
187        size_t index) {
188    mMediaSenderTrackIndex = index;
189}
190
191status_t WifiDisplaySource::PlaybackSession::Track::start() {
192    ALOGV("Track::start isAudio=%d", mIsAudio);
193
194    CHECK(!mStarted);
195
196    status_t err = OK;
197
198    if (mMediaPuller != NULL) {
199        err = mMediaPuller->start();
200    }
201
202    if (err == OK) {
203        mStarted = true;
204    }
205
206    return err;
207}
208
209void WifiDisplaySource::PlaybackSession::Track::stopAsync() {
210    ALOGV("Track::stopAsync isAudio=%d", mIsAudio);
211
212    if (mConverter != NULL) {
213        mConverter->shutdownAsync();
214    }
215
216    sp<AMessage> msg = new AMessage(kWhatMediaPullerStopped, id());
217
218    if (mStarted && mMediaPuller != NULL) {
219        if (mRepeaterSource != NULL) {
220            // Let's unblock MediaPuller's MediaSource::read().
221            mRepeaterSource->wakeUp();
222        }
223
224        mMediaPuller->stopAsync(msg);
225    } else {
226        mStarted = false;
227        msg->post();
228    }
229}
230
231void WifiDisplaySource::PlaybackSession::Track::pause() {
232    mMediaPuller->pause();
233}
234
235void WifiDisplaySource::PlaybackSession::Track::resume() {
236    mMediaPuller->resume();
237}
238
239void WifiDisplaySource::PlaybackSession::Track::onMessageReceived(
240        const sp<AMessage> &msg) {
241    switch (msg->what()) {
242        case kWhatMediaPullerStopped:
243        {
244            mConverter.clear();
245
246            mStarted = false;
247
248            sp<AMessage> notify = mNotify->dup();
249            notify->setInt32("what", kWhatStopped);
250            notify->post();
251
252            ALOGI("kWhatStopped %s posted", mIsAudio ? "audio" : "video");
253            break;
254        }
255
256        default:
257            TRESPASS();
258    }
259}
260
261void WifiDisplaySource::PlaybackSession::Track::queueAccessUnit(
262        const sp<ABuffer> &accessUnit) {
263    mQueuedAccessUnits.push_back(accessUnit);
264}
265
266sp<ABuffer> WifiDisplaySource::PlaybackSession::Track::dequeueAccessUnit() {
267    if (mQueuedAccessUnits.empty()) {
268        return NULL;
269    }
270
271    sp<ABuffer> accessUnit = *mQueuedAccessUnits.begin();
272    CHECK(accessUnit != NULL);
273
274    mQueuedAccessUnits.erase(mQueuedAccessUnits.begin());
275
276    return accessUnit;
277}
278
279void WifiDisplaySource::PlaybackSession::Track::setRepeaterSource(
280        const sp<RepeaterSource> &source) {
281    mRepeaterSource = source;
282}
283
284void WifiDisplaySource::PlaybackSession::Track::requestIDRFrame() {
285    if (mIsAudio) {
286        return;
287    }
288
289    if (mRepeaterSource != NULL) {
290        mRepeaterSource->wakeUp();
291    }
292
293    mConverter->requestIDRFrame();
294}
295
296bool WifiDisplaySource::PlaybackSession::Track::hasOutputBuffer(
297        int64_t *timeUs) const {
298    *timeUs = 0ll;
299
300    if (mQueuedOutputBuffers.empty()) {
301        return false;
302    }
303
304    const sp<ABuffer> &outputBuffer = *mQueuedOutputBuffers.begin();
305
306    CHECK(outputBuffer->meta()->findInt64("timeUs", timeUs));
307
308    return true;
309}
310
311void WifiDisplaySource::PlaybackSession::Track::queueOutputBuffer(
312        const sp<ABuffer> &accessUnit) {
313    mQueuedOutputBuffers.push_back(accessUnit);
314    mLastOutputBufferQueuedTimeUs = ALooper::GetNowUs();
315}
316
317sp<ABuffer> WifiDisplaySource::PlaybackSession::Track::dequeueOutputBuffer() {
318    CHECK(!mQueuedOutputBuffers.empty());
319
320    sp<ABuffer> outputBuffer = *mQueuedOutputBuffers.begin();
321    mQueuedOutputBuffers.erase(mQueuedOutputBuffers.begin());
322
323    return outputBuffer;
324}
325
326#if SUSPEND_VIDEO_IF_IDLE
327bool WifiDisplaySource::PlaybackSession::Track::isSuspended() const {
328    if (!mQueuedOutputBuffers.empty()) {
329        return false;
330    }
331
332    if (mLastOutputBufferQueuedTimeUs < 0ll) {
333        // We've never seen an output buffer queued, but tracks start
334        // out live, not suspended.
335        return false;
336    }
337
338    // If we've not seen new output data for 60ms or more, we consider
339    // this track suspended for the time being.
340    return (ALooper::GetNowUs() - mLastOutputBufferQueuedTimeUs) > 60000ll;
341}
342#endif
343
344////////////////////////////////////////////////////////////////////////////////
345
346WifiDisplaySource::PlaybackSession::PlaybackSession(
347        const sp<ANetworkSession> &netSession,
348        const sp<AMessage> &notify,
349        const in_addr &interfaceAddr,
350        const sp<IHDCP> &hdcp,
351        const char *path)
352    : mNetSession(netSession),
353      mNotify(notify),
354      mInterfaceAddr(interfaceAddr),
355      mHDCP(hdcp),
356      mLocalRTPPort(-1),
357      mWeAreDead(false),
358      mPaused(false),
359      mLastLifesignUs(),
360      mVideoTrackIndex(-1),
361      mPrevTimeUs(-1ll),
362      mPullExtractorPending(false),
363      mPullExtractorGeneration(0),
364      mFirstSampleTimeRealUs(-1ll),
365      mFirstSampleTimeUs(-1ll) {
366    if (path != NULL) {
367        mMediaPath.setTo(path);
368    }
369}
370
371status_t WifiDisplaySource::PlaybackSession::init(
372        const char *clientIP,
373        int32_t clientRtp,
374        RTPSender::TransportMode rtpMode,
375        int32_t clientRtcp,
376        RTPSender::TransportMode rtcpMode,
377        bool enableAudio,
378        bool usePCMAudio,
379        bool enableVideo,
380        VideoFormats::ResolutionType videoResolutionType,
381        size_t videoResolutionIndex) {
382    sp<AMessage> notify = new AMessage(kWhatMediaSenderNotify, id());
383    mMediaSender = new MediaSender(mNetSession, notify);
384    looper()->registerHandler(mMediaSender);
385
386    mMediaSender->setHDCP(mHDCP);
387
388    status_t err = setupPacketizer(
389            enableAudio,
390            usePCMAudio,
391            enableVideo,
392            videoResolutionType,
393            videoResolutionIndex);
394
395    if (err == OK) {
396        err = mMediaSender->initAsync(
397                -1 /* trackIndex */,
398                clientIP,
399                clientRtp,
400                rtpMode,
401                clientRtcp,
402                rtcpMode,
403                &mLocalRTPPort);
404    }
405
406    if (err != OK) {
407        mLocalRTPPort = -1;
408
409        looper()->unregisterHandler(mMediaSender->id());
410        mMediaSender.clear();
411
412        return err;
413    }
414
415    updateLiveness();
416
417    return OK;
418}
419
420WifiDisplaySource::PlaybackSession::~PlaybackSession() {
421}
422
423int32_t WifiDisplaySource::PlaybackSession::getRTPPort() const {
424    return mLocalRTPPort;
425}
426
427int64_t WifiDisplaySource::PlaybackSession::getLastLifesignUs() const {
428    return mLastLifesignUs;
429}
430
431void WifiDisplaySource::PlaybackSession::updateLiveness() {
432    mLastLifesignUs = ALooper::GetNowUs();
433}
434
435status_t WifiDisplaySource::PlaybackSession::play() {
436    updateLiveness();
437
438    (new AMessage(kWhatResume, id()))->post();
439
440    return OK;
441}
442
443status_t WifiDisplaySource::PlaybackSession::onMediaSenderInitialized() {
444    for (size_t i = 0; i < mTracks.size(); ++i) {
445        CHECK_EQ((status_t)OK, mTracks.editValueAt(i)->start());
446    }
447
448    sp<AMessage> notify = mNotify->dup();
449    notify->setInt32("what", kWhatSessionEstablished);
450    notify->post();
451
452    return OK;
453}
454
455status_t WifiDisplaySource::PlaybackSession::pause() {
456    updateLiveness();
457
458    (new AMessage(kWhatPause, id()))->post();
459
460    return OK;
461}
462
463void WifiDisplaySource::PlaybackSession::destroyAsync() {
464    ALOGI("destroyAsync");
465
466    for (size_t i = 0; i < mTracks.size(); ++i) {
467        mTracks.valueAt(i)->stopAsync();
468    }
469}
470
471void WifiDisplaySource::PlaybackSession::onMessageReceived(
472        const sp<AMessage> &msg) {
473    switch (msg->what()) {
474        case kWhatConverterNotify:
475        {
476            if (mWeAreDead) {
477                ALOGV("dropping msg '%s' because we're dead",
478                      msg->debugString().c_str());
479
480                break;
481            }
482
483            int32_t what;
484            CHECK(msg->findInt32("what", &what));
485
486            size_t trackIndex;
487            CHECK(msg->findSize("trackIndex", &trackIndex));
488
489            if (what == Converter::kWhatAccessUnit) {
490                sp<ABuffer> accessUnit;
491                CHECK(msg->findBuffer("accessUnit", &accessUnit));
492
493                const sp<Track> &track = mTracks.valueFor(trackIndex);
494
495                status_t err = mMediaSender->queueAccessUnit(
496                        track->mediaSenderTrackIndex(),
497                        accessUnit);
498
499                if (err != OK) {
500                    notifySessionDead();
501                }
502                break;
503            } else if (what == Converter::kWhatEOS) {
504                CHECK_EQ(what, Converter::kWhatEOS);
505
506                ALOGI("output EOS on track %d", trackIndex);
507
508                ssize_t index = mTracks.indexOfKey(trackIndex);
509                CHECK_GE(index, 0);
510
511                const sp<Converter> &converter =
512                    mTracks.valueAt(index)->converter();
513                looper()->unregisterHandler(converter->id());
514
515                mTracks.removeItemsAt(index);
516
517                if (mTracks.isEmpty()) {
518                    ALOGI("Reached EOS");
519                }
520            } else {
521                CHECK_EQ(what, Converter::kWhatError);
522
523                status_t err;
524                CHECK(msg->findInt32("err", &err));
525
526                ALOGE("converter signaled error %d", err);
527
528                notifySessionDead();
529            }
530            break;
531        }
532
533        case kWhatMediaSenderNotify:
534        {
535            int32_t what;
536            CHECK(msg->findInt32("what", &what));
537
538            if (what == MediaSender::kWhatInitDone) {
539                status_t err;
540                CHECK(msg->findInt32("err", &err));
541
542                if (err == OK) {
543                    onMediaSenderInitialized();
544                } else {
545                    notifySessionDead();
546                }
547            } else if (what == MediaSender::kWhatError) {
548                notifySessionDead();
549            } else if (what == MediaSender::kWhatNetworkStall) {
550                size_t numBytesQueued;
551                CHECK(msg->findSize("numBytesQueued", &numBytesQueued));
552
553                if (mVideoTrackIndex >= 0) {
554                    const sp<Track> &videoTrack =
555                        mTracks.valueFor(mVideoTrackIndex);
556
557                    sp<Converter> converter = videoTrack->converter();
558                    if (converter != NULL) {
559                        converter->dropAFrame();
560                    }
561                }
562            } else {
563                TRESPASS();
564            }
565            break;
566        }
567
568        case kWhatTrackNotify:
569        {
570            int32_t what;
571            CHECK(msg->findInt32("what", &what));
572
573            size_t trackIndex;
574            CHECK(msg->findSize("trackIndex", &trackIndex));
575
576            if (what == Track::kWhatStopped) {
577                ALOGI("Track %d stopped", trackIndex);
578
579                sp<Track> track = mTracks.valueFor(trackIndex);
580                looper()->unregisterHandler(track->id());
581                mTracks.removeItem(trackIndex);
582                track.clear();
583
584                if (!mTracks.isEmpty()) {
585                    ALOGI("not all tracks are stopped yet");
586                    break;
587                }
588
589                looper()->unregisterHandler(mMediaSender->id());
590                mMediaSender.clear();
591
592                sp<AMessage> notify = mNotify->dup();
593                notify->setInt32("what", kWhatSessionDestroyed);
594                notify->post();
595            }
596            break;
597        }
598
599        case kWhatPause:
600        {
601            if (mExtractor != NULL) {
602                ++mPullExtractorGeneration;
603                mFirstSampleTimeRealUs = -1ll;
604                mFirstSampleTimeUs = -1ll;
605            }
606
607            if (mPaused) {
608                break;
609            }
610
611            for (size_t i = 0; i < mTracks.size(); ++i) {
612                mTracks.editValueAt(i)->pause();
613            }
614
615            mPaused = true;
616            break;
617        }
618
619        case kWhatResume:
620        {
621            if (mExtractor != NULL) {
622                schedulePullExtractor();
623            }
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        case kWhatPullExtractorSample:
638        {
639            int32_t generation;
640            CHECK(msg->findInt32("generation", &generation));
641
642            if (generation != mPullExtractorGeneration) {
643                break;
644            }
645
646            mPullExtractorPending = false;
647
648            onPullExtractor();
649            break;
650        }
651
652        default:
653            TRESPASS();
654    }
655}
656
657status_t WifiDisplaySource::PlaybackSession::setupMediaPacketizer(
658        bool enableAudio, bool enableVideo) {
659    DataSource::RegisterDefaultSniffers();
660
661    mExtractor = new NuMediaExtractor;
662
663    status_t err = mExtractor->setDataSource(mMediaPath.c_str());
664
665    if (err != OK) {
666        return err;
667    }
668
669    size_t n = mExtractor->countTracks();
670    bool haveAudio = false;
671    bool haveVideo = false;
672    for (size_t i = 0; i < n; ++i) {
673        sp<AMessage> format;
674        err = mExtractor->getTrackFormat(i, &format);
675
676        if (err != OK) {
677            continue;
678        }
679
680        AString mime;
681        CHECK(format->findString("mime", &mime));
682
683        bool isAudio = !strncasecmp(mime.c_str(), "audio/", 6);
684        bool isVideo = !strncasecmp(mime.c_str(), "video/", 6);
685
686        if (isAudio && enableAudio && !haveAudio) {
687            haveAudio = true;
688        } else if (isVideo && enableVideo && !haveVideo) {
689            haveVideo = true;
690        } else {
691            continue;
692        }
693
694        err = mExtractor->selectTrack(i);
695
696        size_t trackIndex = mTracks.size();
697
698        sp<AMessage> notify = new AMessage(kWhatTrackNotify, id());
699        notify->setSize("trackIndex", trackIndex);
700
701        sp<Track> track = new Track(notify, format);
702        looper()->registerHandler(track);
703
704        mTracks.add(trackIndex, track);
705
706        mExtractorTrackToInternalTrack.add(i, trackIndex);
707
708        if (isVideo) {
709            mVideoTrackIndex = trackIndex;
710        }
711
712        uint32_t flags = MediaSender::FLAG_MANUALLY_PREPEND_SPS_PPS;
713
714        ssize_t mediaSenderTrackIndex =
715            mMediaSender->addTrack(format, flags);
716        CHECK_GE(mediaSenderTrackIndex, 0);
717
718        track->setMediaSenderTrackIndex(mediaSenderTrackIndex);
719
720        if ((haveAudio || !enableAudio) && (haveVideo || !enableVideo)) {
721            break;
722        }
723    }
724
725    return OK;
726}
727
728void WifiDisplaySource::PlaybackSession::schedulePullExtractor() {
729    if (mPullExtractorPending) {
730        return;
731    }
732
733    int64_t sampleTimeUs;
734    status_t err = mExtractor->getSampleTime(&sampleTimeUs);
735
736    int64_t nowUs = ALooper::GetNowUs();
737
738    if (mFirstSampleTimeRealUs < 0ll) {
739        mFirstSampleTimeRealUs = nowUs;
740        mFirstSampleTimeUs = sampleTimeUs;
741    }
742
743    int64_t whenUs = sampleTimeUs - mFirstSampleTimeUs + mFirstSampleTimeRealUs;
744
745    sp<AMessage> msg = new AMessage(kWhatPullExtractorSample, id());
746    msg->setInt32("generation", mPullExtractorGeneration);
747    msg->post(whenUs - nowUs);
748
749    mPullExtractorPending = true;
750}
751
752void WifiDisplaySource::PlaybackSession::onPullExtractor() {
753    sp<ABuffer> accessUnit = new ABuffer(1024 * 1024);
754    status_t err = mExtractor->readSampleData(accessUnit);
755    if (err != OK) {
756        // EOS.
757        return;
758    }
759
760    int64_t timeUs;
761    CHECK_EQ((status_t)OK, mExtractor->getSampleTime(&timeUs));
762
763    accessUnit->meta()->setInt64(
764            "timeUs", mFirstSampleTimeRealUs + timeUs - mFirstSampleTimeUs);
765
766    size_t trackIndex;
767    CHECK_EQ((status_t)OK, mExtractor->getSampleTrackIndex(&trackIndex));
768
769    sp<AMessage> msg = new AMessage(kWhatConverterNotify, id());
770
771    msg->setSize(
772            "trackIndex", mExtractorTrackToInternalTrack.valueFor(trackIndex));
773
774    msg->setInt32("what", Converter::kWhatAccessUnit);
775    msg->setBuffer("accessUnit", accessUnit);
776    msg->post();
777
778    mExtractor->advance();
779
780    schedulePullExtractor();
781}
782
783status_t WifiDisplaySource::PlaybackSession::setupPacketizer(
784        bool enableAudio,
785        bool usePCMAudio,
786        bool enableVideo,
787        VideoFormats::ResolutionType videoResolutionType,
788        size_t videoResolutionIndex) {
789    CHECK(enableAudio || enableVideo);
790
791    if (!mMediaPath.empty()) {
792        return setupMediaPacketizer(enableAudio, enableVideo);
793    }
794
795    if (enableVideo) {
796        status_t err = addVideoSource(
797                videoResolutionType, videoResolutionIndex);
798
799        if (err != OK) {
800            return err;
801        }
802    }
803
804    if (!enableAudio) {
805        return OK;
806    }
807
808    return addAudioSource(usePCMAudio);
809}
810
811status_t WifiDisplaySource::PlaybackSession::addSource(
812        bool isVideo, const sp<MediaSource> &source, bool isRepeaterSource,
813        bool usePCMAudio, size_t *numInputBuffers) {
814    CHECK(!usePCMAudio || !isVideo);
815    CHECK(!isRepeaterSource || isVideo);
816
817    sp<ALooper> pullLooper = new ALooper;
818    pullLooper->setName("pull_looper");
819
820    pullLooper->start(
821            false /* runOnCallingThread */,
822            false /* canCallJava */,
823            PRIORITY_AUDIO);
824
825    sp<ALooper> codecLooper = new ALooper;
826    codecLooper->setName("codec_looper");
827
828    codecLooper->start(
829            false /* runOnCallingThread */,
830            false /* canCallJava */,
831            PRIORITY_AUDIO);
832
833    size_t trackIndex;
834
835    sp<AMessage> notify;
836
837    trackIndex = mTracks.size();
838
839    sp<AMessage> format;
840    status_t err = convertMetaDataToMessage(source->getFormat(), &format);
841    CHECK_EQ(err, (status_t)OK);
842
843    if (isVideo) {
844        format->setInt32("store-metadata-in-buffers", true);
845
846        format->setInt32(
847                "color-format", OMX_COLOR_FormatAndroidOpaque);
848    }
849
850    notify = new AMessage(kWhatConverterNotify, id());
851    notify->setSize("trackIndex", trackIndex);
852
853    sp<Converter> converter =
854        new Converter(notify, codecLooper, format, usePCMAudio);
855
856    err = converter->initCheck();
857    if (err != OK) {
858        ALOGE("%s converter returned err %d", isVideo ? "video" : "audio", err);
859        return err;
860    }
861
862    looper()->registerHandler(converter);
863
864    notify = new AMessage(Converter::kWhatMediaPullerNotify, converter->id());
865    notify->setSize("trackIndex", trackIndex);
866
867    sp<MediaPuller> puller = new MediaPuller(source, notify);
868    pullLooper->registerHandler(puller);
869
870    if (numInputBuffers != NULL) {
871        *numInputBuffers = converter->getInputBufferCount();
872    }
873
874    notify = new AMessage(kWhatTrackNotify, id());
875    notify->setSize("trackIndex", trackIndex);
876
877    sp<Track> track = new Track(
878            notify, pullLooper, codecLooper, puller, converter);
879
880    if (isRepeaterSource) {
881        track->setRepeaterSource(static_cast<RepeaterSource *>(source.get()));
882    }
883
884    looper()->registerHandler(track);
885
886    mTracks.add(trackIndex, track);
887
888    if (isVideo) {
889        mVideoTrackIndex = trackIndex;
890    }
891
892    uint32_t flags = 0;
893    if (converter->needToManuallyPrependSPSPPS()) {
894        flags |= MediaSender::FLAG_MANUALLY_PREPEND_SPS_PPS;
895    }
896
897    ssize_t mediaSenderTrackIndex =
898        mMediaSender->addTrack(converter->getOutputFormat(), flags);
899    CHECK_GE(mediaSenderTrackIndex, 0);
900
901    track->setMediaSenderTrackIndex(mediaSenderTrackIndex);
902
903    return OK;
904}
905
906status_t WifiDisplaySource::PlaybackSession::addVideoSource(
907        VideoFormats::ResolutionType videoResolutionType,
908        size_t videoResolutionIndex) {
909    size_t width, height, framesPerSecond;
910    bool interlaced;
911    CHECK(VideoFormats::GetConfiguration(
912                videoResolutionType,
913                videoResolutionIndex,
914                &width,
915                &height,
916                &framesPerSecond,
917                &interlaced));
918
919    sp<SurfaceMediaSource> source = new SurfaceMediaSource(width, height);
920
921    source->setUseAbsoluteTimestamps();
922
923    sp<RepeaterSource> videoSource =
924        new RepeaterSource(source, framesPerSecond);
925
926    size_t numInputBuffers;
927    status_t err = addSource(
928            true /* isVideo */, videoSource, true /* isRepeaterSource */,
929            false /* usePCMAudio */, &numInputBuffers);
930
931    if (err != OK) {
932        return err;
933    }
934
935    err = source->setMaxAcquiredBufferCount(numInputBuffers);
936    CHECK_EQ(err, (status_t)OK);
937
938    mBufferQueue = source->getBufferQueue();
939
940    return OK;
941}
942
943status_t WifiDisplaySource::PlaybackSession::addAudioSource(bool usePCMAudio) {
944    sp<AudioSource> audioSource = new AudioSource(
945            AUDIO_SOURCE_REMOTE_SUBMIX,
946            48000 /* sampleRate */,
947            2 /* channelCount */);
948
949    if (audioSource->initCheck() == OK) {
950        return addSource(
951                false /* isVideo */, audioSource, false /* isRepeaterSource */,
952                usePCMAudio, NULL /* numInputBuffers */);
953    }
954
955    ALOGW("Unable to instantiate audio source");
956
957    return OK;
958}
959
960sp<IGraphicBufferProducer> WifiDisplaySource::PlaybackSession::getSurfaceTexture() {
961    return mBufferQueue;
962}
963
964void WifiDisplaySource::PlaybackSession::requestIDRFrame() {
965    for (size_t i = 0; i < mTracks.size(); ++i) {
966        const sp<Track> &track = mTracks.valueAt(i);
967
968        track->requestIDRFrame();
969    }
970}
971
972void WifiDisplaySource::PlaybackSession::notifySessionDead() {
973    // Inform WifiDisplaySource of our premature death (wish).
974    sp<AMessage> notify = mNotify->dup();
975    notify->setInt32("what", kWhatSessionDead);
976    notify->post();
977
978    mWeAreDead = true;
979}
980
981}  // namespace android
982
983