MediaSender.cpp revision 6e98aba4d23d00cab236d993d895f57ea76ea0e5
1/*
2 * Copyright 2013, 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 "MediaSender"
19#include <utils/Log.h>
20
21#include "MediaSender.h"
22
23#include "ANetworkSession.h"
24#include "rtp/RTPSender.h"
25#include "source/TSPacketizer.h"
26
27#include "include/avc_utils.h"
28
29#include <media/IHDCP.h>
30#include <media/stagefright/foundation/ABuffer.h>
31#include <media/stagefright/foundation/ADebug.h>
32#include <media/stagefright/foundation/AMessage.h>
33
34namespace android {
35
36MediaSender::MediaSender(
37        const sp<ANetworkSession> &netSession,
38        const sp<AMessage> &notify)
39    : mNetSession(netSession),
40      mNotify(notify),
41      mMode(MODE_UNDEFINED),
42      mGeneration(0),
43      mPrevTimeUs(-1ll),
44      mInitDoneCount(0),
45      mLogFile(NULL) {
46    // mLogFile = fopen("/data/misc/log.ts", "wb");
47}
48
49MediaSender::~MediaSender() {
50    if (mLogFile != NULL) {
51        fclose(mLogFile);
52        mLogFile = NULL;
53    }
54}
55
56status_t MediaSender::setHDCP(const sp<IHDCP> &hdcp) {
57    if (mMode != MODE_UNDEFINED) {
58        return INVALID_OPERATION;
59    }
60
61    mHDCP = hdcp;
62
63    return OK;
64}
65
66ssize_t MediaSender::addTrack(const sp<AMessage> &format, uint32_t flags) {
67    if (mMode != MODE_UNDEFINED) {
68        return INVALID_OPERATION;
69    }
70
71    TrackInfo info;
72    info.mFormat = format;
73    info.mFlags = flags;
74    info.mPacketizerTrackIndex = -1;
75
76    AString mime;
77    CHECK(format->findString("mime", &mime));
78    info.mIsAudio = !strncasecmp("audio/", mime.c_str(), 6);
79
80    size_t index = mTrackInfos.size();
81    mTrackInfos.push_back(info);
82
83    return index;
84}
85
86status_t MediaSender::initAsync(
87        ssize_t trackIndex,
88        RTPSender::TransportMode transportMode,
89        const char *remoteHost,
90        int32_t remoteRTPPort,
91        int32_t remoteRTCPPort,
92        int32_t *localRTPPort) {
93    if (trackIndex < 0) {
94        if (mMode != MODE_UNDEFINED) {
95            return INVALID_OPERATION;
96        }
97
98        uint32_t flags = 0;
99        if (mHDCP != NULL) {
100            // XXX Determine proper HDCP version.
101            flags |= TSPacketizer::EMIT_HDCP20_DESCRIPTOR;
102        }
103        mTSPacketizer = new TSPacketizer(flags);
104
105        status_t err = OK;
106        for (size_t i = 0; i < mTrackInfos.size(); ++i) {
107            TrackInfo *info = &mTrackInfos.editItemAt(i);
108
109            ssize_t packetizerTrackIndex =
110                mTSPacketizer->addTrack(info->mFormat);
111
112            if (packetizerTrackIndex < 0) {
113                err = packetizerTrackIndex;
114                break;
115            }
116
117            info->mPacketizerTrackIndex = packetizerTrackIndex;
118        }
119
120        if (err == OK) {
121            sp<AMessage> notify = new AMessage(kWhatSenderNotify, id());
122            notify->setInt32("generation", mGeneration);
123            mTSSender = new RTPSender(mNetSession, notify);
124            looper()->registerHandler(mTSSender);
125
126            err = mTSSender->initAsync(
127                    remoteHost,
128                    remoteRTPPort,
129                    transportMode,  // rtpMode
130                    remoteRTCPPort,
131                    (transportMode == RTPSender::TRANSPORT_UDP
132                        && remoteRTCPPort >= 0)
133                        ? transportMode
134                        : RTPSender::TRANSPORT_NONE,  // rtcpMode
135                    localRTPPort);
136
137            if (err != OK) {
138                looper()->unregisterHandler(mTSSender->id());
139                mTSSender.clear();
140            }
141        }
142
143        if (err != OK) {
144            for (size_t i = 0; i < mTrackInfos.size(); ++i) {
145                TrackInfo *info = &mTrackInfos.editItemAt(i);
146                info->mPacketizerTrackIndex = -1;
147            }
148
149            mTSPacketizer.clear();
150            return err;
151        }
152
153        mMode = MODE_TRANSPORT_STREAM;
154        mInitDoneCount = 1;
155
156        return OK;
157    }
158
159    if (mMode == MODE_TRANSPORT_STREAM) {
160        return INVALID_OPERATION;
161    }
162
163    if ((size_t)trackIndex >= mTrackInfos.size()) {
164        return -ERANGE;
165    }
166
167    TrackInfo *info = &mTrackInfos.editItemAt(trackIndex);
168
169    if (info->mSender != NULL) {
170        return INVALID_OPERATION;
171    }
172
173    sp<AMessage> notify = new AMessage(kWhatSenderNotify, id());
174    notify->setInt32("generation", mGeneration);
175    notify->setSize("trackIndex", trackIndex);
176
177    info->mSender = new RTPSender(mNetSession, notify);
178    looper()->registerHandler(info->mSender);
179
180    status_t err = info->mSender->initAsync(
181            remoteHost,
182            remoteRTPPort,
183            transportMode,  // rtpMode
184            remoteRTCPPort,
185            (transportMode == RTPSender::TRANSPORT_UDP && remoteRTCPPort >= 0)
186                ? transportMode
187                : RTPSender::TRANSPORT_NONE,  // rtcpMode
188            localRTPPort);
189
190    if (err != OK) {
191        looper()->unregisterHandler(info->mSender->id());
192        info->mSender.clear();
193
194        return err;
195    }
196
197    if (mMode == MODE_UNDEFINED) {
198        mInitDoneCount = mTrackInfos.size();
199    }
200
201    mMode = MODE_ELEMENTARY_STREAMS;
202
203    return OK;
204}
205
206status_t MediaSender::queueAccessUnit(
207        size_t trackIndex, const sp<ABuffer> &accessUnit) {
208    if (mMode == MODE_UNDEFINED) {
209        return INVALID_OPERATION;
210    }
211
212    if (trackIndex >= mTrackInfos.size()) {
213        return -ERANGE;
214    }
215
216    if (mMode == MODE_TRANSPORT_STREAM) {
217        TrackInfo *info = &mTrackInfos.editItemAt(trackIndex);
218        info->mAccessUnits.push_back(accessUnit);
219
220        mTSPacketizer->extractCSDIfNecessary(info->mPacketizerTrackIndex);
221
222        for (;;) {
223            ssize_t minTrackIndex = -1;
224            int64_t minTimeUs = -1ll;
225
226            for (size_t i = 0; i < mTrackInfos.size(); ++i) {
227                const TrackInfo &info = mTrackInfos.itemAt(i);
228
229                if (info.mAccessUnits.empty()) {
230                    minTrackIndex = -1;
231                    minTimeUs = -1ll;
232                    break;
233                }
234
235                int64_t timeUs;
236                const sp<ABuffer> &accessUnit = *info.mAccessUnits.begin();
237                CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
238
239                if (minTrackIndex < 0 || timeUs < minTimeUs) {
240                    minTrackIndex = i;
241                    minTimeUs = timeUs;
242                }
243            }
244
245            if (minTrackIndex < 0) {
246                return OK;
247            }
248
249            TrackInfo *info = &mTrackInfos.editItemAt(minTrackIndex);
250            sp<ABuffer> accessUnit = *info->mAccessUnits.begin();
251            info->mAccessUnits.erase(info->mAccessUnits.begin());
252
253            sp<ABuffer> tsPackets;
254            status_t err = packetizeAccessUnit(
255                    minTrackIndex, accessUnit, &tsPackets);
256
257            if (err == OK) {
258                if (mLogFile != NULL) {
259                    fwrite(tsPackets->data(), 1, tsPackets->size(), mLogFile);
260                }
261
262                int64_t timeUs;
263                CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
264                tsPackets->meta()->setInt64("timeUs", timeUs);
265
266                err = mTSSender->queueBuffer(
267                        tsPackets,
268                        33 /* packetType */,
269                        RTPSender::PACKETIZATION_TRANSPORT_STREAM);
270
271#if 0
272                {
273                    int64_t nowUs = ALooper::GetNowUs();
274
275                    int64_t timeUs;
276                    CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
277
278                    int64_t delayMs = (nowUs - timeUs) / 1000ll;
279
280                    static const int64_t kMinDelayMs = 0;
281                    static const int64_t kMaxDelayMs = 300;
282
283                    const char *kPattern = "########################################";
284                    size_t kPatternSize = strlen(kPattern);
285
286                    int n = (kPatternSize * (delayMs - kMinDelayMs))
287                                / (kMaxDelayMs - kMinDelayMs);
288
289                    if (n < 0) {
290                        n = 0;
291                    } else if ((size_t)n > kPatternSize) {
292                        n = kPatternSize;
293                    }
294
295                    ALOGI("[%lld]: (%4lld ms) %s\n",
296                          timeUs / 1000,
297                          delayMs,
298                          kPattern + kPatternSize - n);
299                }
300#endif
301            }
302
303            if (err != OK) {
304                return err;
305            }
306        }
307    }
308
309    TrackInfo *info = &mTrackInfos.editItemAt(trackIndex);
310
311    return info->mSender->queueBuffer(
312            accessUnit,
313            info->mIsAudio ? 96 : 97 /* packetType */,
314            info->mIsAudio
315                ? RTPSender::PACKETIZATION_AAC : RTPSender::PACKETIZATION_H264);
316}
317
318void MediaSender::onMessageReceived(const sp<AMessage> &msg) {
319    switch (msg->what()) {
320        case kWhatSenderNotify:
321        {
322            int32_t generation;
323            CHECK(msg->findInt32("generation", &generation));
324            if (generation != mGeneration) {
325                break;
326            }
327
328            onSenderNotify(msg);
329            break;
330        }
331
332        default:
333            TRESPASS();
334    }
335}
336
337void MediaSender::onSenderNotify(const sp<AMessage> &msg) {
338    int32_t what;
339    CHECK(msg->findInt32("what", &what));
340
341    switch (what) {
342        case RTPSender::kWhatInitDone:
343        {
344            --mInitDoneCount;
345
346            int32_t err;
347            CHECK(msg->findInt32("err", &err));
348
349            if (err != OK) {
350                notifyInitDone(err);
351                ++mGeneration;
352                break;
353            }
354
355            if (mInitDoneCount == 0) {
356                notifyInitDone(OK);
357            }
358            break;
359        }
360
361        case RTPSender::kWhatError:
362        {
363            int32_t err;
364            CHECK(msg->findInt32("err", &err));
365
366            notifyError(err);
367            break;
368        }
369
370        case kWhatNetworkStall:
371        {
372            size_t numBytesQueued;
373            CHECK(msg->findSize("numBytesQueued", &numBytesQueued));
374
375            notifyNetworkStall(numBytesQueued);
376            break;
377        }
378
379        default:
380            TRESPASS();
381    }
382}
383
384void MediaSender::notifyInitDone(status_t err) {
385    sp<AMessage> notify = mNotify->dup();
386    notify->setInt32("what", kWhatInitDone);
387    notify->setInt32("err", err);
388    notify->post();
389}
390
391void MediaSender::notifyError(status_t err) {
392    sp<AMessage> notify = mNotify->dup();
393    notify->setInt32("what", kWhatError);
394    notify->setInt32("err", err);
395    notify->post();
396}
397
398void MediaSender::notifyNetworkStall(size_t numBytesQueued) {
399    sp<AMessage> notify = mNotify->dup();
400    notify->setInt32("what", kWhatNetworkStall);
401    notify->setSize("numBytesQueued", numBytesQueued);
402    notify->post();
403}
404
405status_t MediaSender::packetizeAccessUnit(
406        size_t trackIndex,
407        sp<ABuffer> accessUnit,
408        sp<ABuffer> *tsPackets) {
409    const TrackInfo &info = mTrackInfos.itemAt(trackIndex);
410
411    uint32_t flags = 0;
412
413    bool isHDCPEncrypted = false;
414    uint64_t inputCTR;
415    uint8_t HDCP_private_data[16];
416
417    bool manuallyPrependSPSPPS =
418        !info.mIsAudio
419        && (info.mFlags & FLAG_MANUALLY_PREPEND_SPS_PPS)
420        && IsIDR(accessUnit);
421
422    if (mHDCP != NULL && !info.mIsAudio) {
423        isHDCPEncrypted = true;
424
425        if (manuallyPrependSPSPPS) {
426            accessUnit = mTSPacketizer->prependCSD(
427                    info.mPacketizerTrackIndex, accessUnit);
428        }
429
430        status_t err = mHDCP->encrypt(
431                accessUnit->data(), accessUnit->size(),
432                trackIndex  /* streamCTR */,
433                &inputCTR,
434                accessUnit->data());
435
436        if (err != OK) {
437            ALOGE("Failed to HDCP-encrypt media data (err %d)",
438                  err);
439
440            return err;
441        }
442
443        HDCP_private_data[0] = 0x00;
444
445        HDCP_private_data[1] =
446            (((trackIndex >> 30) & 3) << 1) | 1;
447
448        HDCP_private_data[2] = (trackIndex >> 22) & 0xff;
449
450        HDCP_private_data[3] =
451            (((trackIndex >> 15) & 0x7f) << 1) | 1;
452
453        HDCP_private_data[4] = (trackIndex >> 7) & 0xff;
454
455        HDCP_private_data[5] =
456            ((trackIndex & 0x7f) << 1) | 1;
457
458        HDCP_private_data[6] = 0x00;
459
460        HDCP_private_data[7] =
461            (((inputCTR >> 60) & 0x0f) << 1) | 1;
462
463        HDCP_private_data[8] = (inputCTR >> 52) & 0xff;
464
465        HDCP_private_data[9] =
466            (((inputCTR >> 45) & 0x7f) << 1) | 1;
467
468        HDCP_private_data[10] = (inputCTR >> 37) & 0xff;
469
470        HDCP_private_data[11] =
471            (((inputCTR >> 30) & 0x7f) << 1) | 1;
472
473        HDCP_private_data[12] = (inputCTR >> 22) & 0xff;
474
475        HDCP_private_data[13] =
476            (((inputCTR >> 15) & 0x7f) << 1) | 1;
477
478        HDCP_private_data[14] = (inputCTR >> 7) & 0xff;
479
480        HDCP_private_data[15] =
481            ((inputCTR & 0x7f) << 1) | 1;
482
483        flags |= TSPacketizer::IS_ENCRYPTED;
484    } else if (manuallyPrependSPSPPS) {
485        flags |= TSPacketizer::PREPEND_SPS_PPS_TO_IDR_FRAMES;
486    }
487
488    int64_t timeUs = ALooper::GetNowUs();
489    if (mPrevTimeUs < 0ll || mPrevTimeUs + 100000ll <= timeUs) {
490        flags |= TSPacketizer::EMIT_PCR;
491        flags |= TSPacketizer::EMIT_PAT_AND_PMT;
492
493        mPrevTimeUs = timeUs;
494    }
495
496    mTSPacketizer->packetize(
497            info.mPacketizerTrackIndex,
498            accessUnit,
499            tsPackets,
500            flags,
501            !isHDCPEncrypted ? NULL : HDCP_private_data,
502            !isHDCPEncrypted ? 0 : sizeof(HDCP_private_data),
503            info.mIsAudio ? 2 : 0 /* numStuffingBytes */);
504
505    return OK;
506}
507
508}  // namespace android
509
510