blob: 105c642117a567c6c56275aae9db5bcd899c9ace [file] [log] [blame]
Andreas Hubera556c482013-03-05 10:56:27 -08001/*
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),
Andreas Huberbfd79f22013-03-07 10:33:20 -080044 mInitDoneCount(0),
45 mLogFile(NULL) {
46 // mLogFile = fopen("/data/misc/log.ts", "wb");
Andreas Hubera556c482013-03-05 10:56:27 -080047}
48
49MediaSender::~MediaSender() {
Andreas Huberbfd79f22013-03-07 10:33:20 -080050 if (mLogFile != NULL) {
51 fclose(mLogFile);
52 mLogFile = NULL;
53 }
Andreas Hubera556c482013-03-05 10:56:27 -080054}
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
Andreas Huberbfd79f22013-03-07 10:33:20 -080098 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);
Andreas Hubera556c482013-03-05 10:56:27 -0800104
105 status_t err = OK;
106 for (size_t i = 0; i < mTrackInfos.size(); ++i) {
107 TrackInfo *info = &mTrackInfos.editItemAt(i);
108
Andreas Hubera556c482013-03-05 10:56:27 -0800109 ssize_t packetizerTrackIndex =
Andreas Huberbfd79f22013-03-07 10:33:20 -0800110 mTSPacketizer->addTrack(info->mFormat);
Andreas Hubera556c482013-03-05 10:56:27 -0800111
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 transportMode,
128 remoteHost,
129 remoteRTPPort,
130 remoteRTCPPort,
131 localRTPPort);
132
133 if (err != OK) {
134 looper()->unregisterHandler(mTSSender->id());
135 mTSSender.clear();
136 }
137 }
138
139 if (err != OK) {
140 for (size_t i = 0; i < mTrackInfos.size(); ++i) {
141 TrackInfo *info = &mTrackInfos.editItemAt(i);
142 info->mPacketizerTrackIndex = -1;
143 }
144
145 mTSPacketizer.clear();
146 return err;
147 }
148
149 mMode = MODE_TRANSPORT_STREAM;
150 mInitDoneCount = 1;
151
152 return OK;
153 }
154
155 if (mMode == MODE_TRANSPORT_STREAM) {
156 return INVALID_OPERATION;
157 }
158
159 if ((size_t)trackIndex >= mTrackInfos.size()) {
160 return -ERANGE;
161 }
162
163 TrackInfo *info = &mTrackInfos.editItemAt(trackIndex);
164
165 if (info->mSender != NULL) {
166 return INVALID_OPERATION;
167 }
168
169 sp<AMessage> notify = new AMessage(kWhatSenderNotify, id());
170 notify->setInt32("generation", mGeneration);
171 notify->setSize("trackIndex", trackIndex);
172
173 info->mSender = new RTPSender(mNetSession, notify);
174 looper()->registerHandler(info->mSender);
175
176 status_t err = info->mSender->initAsync(
177 transportMode,
178 remoteHost,
179 remoteRTPPort,
180 remoteRTCPPort,
181 localRTPPort);
182
183 if (err != OK) {
184 looper()->unregisterHandler(info->mSender->id());
185 info->mSender.clear();
186
187 return err;
188 }
189
190 if (mMode == MODE_UNDEFINED) {
191 mInitDoneCount = mTrackInfos.size();
192 }
193
194 mMode = MODE_ELEMENTARY_STREAMS;
195
196 return OK;
197}
198
199status_t MediaSender::queueAccessUnit(
200 size_t trackIndex, const sp<ABuffer> &accessUnit) {
201 if (mMode == MODE_UNDEFINED) {
202 return INVALID_OPERATION;
203 }
204
205 if (trackIndex >= mTrackInfos.size()) {
206 return -ERANGE;
207 }
208
209 if (mMode == MODE_TRANSPORT_STREAM) {
210 TrackInfo *info = &mTrackInfos.editItemAt(trackIndex);
211 info->mAccessUnits.push_back(accessUnit);
212
213 mTSPacketizer->extractCSDIfNecessary(info->mPacketizerTrackIndex);
214
215 for (;;) {
216 ssize_t minTrackIndex = -1;
217 int64_t minTimeUs = -1ll;
218
219 for (size_t i = 0; i < mTrackInfos.size(); ++i) {
220 const TrackInfo &info = mTrackInfos.itemAt(i);
221
222 if (info.mAccessUnits.empty()) {
223 minTrackIndex = -1;
224 minTimeUs = -1ll;
225 break;
226 }
227
228 int64_t timeUs;
229 const sp<ABuffer> &accessUnit = *info.mAccessUnits.begin();
230 CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
231
232 if (minTrackIndex < 0 || timeUs < minTimeUs) {
233 minTrackIndex = i;
234 minTimeUs = timeUs;
235 }
236 }
237
238 if (minTrackIndex < 0) {
239 return OK;
240 }
241
242 TrackInfo *info = &mTrackInfos.editItemAt(minTrackIndex);
243 sp<ABuffer> accessUnit = *info->mAccessUnits.begin();
244 info->mAccessUnits.erase(info->mAccessUnits.begin());
245
246 sp<ABuffer> tsPackets;
247 status_t err = packetizeAccessUnit(
248 minTrackIndex, accessUnit, &tsPackets);
249
250 if (err == OK) {
Andreas Huberbfd79f22013-03-07 10:33:20 -0800251 if (mLogFile != NULL) {
252 fwrite(tsPackets->data(), 1, tsPackets->size(), mLogFile);
253 }
254
Andreas Hubera556c482013-03-05 10:56:27 -0800255 err = mTSSender->queueBuffer(
256 tsPackets,
257 33 /* packetType */,
258 RTPSender::PACKETIZATION_TRANSPORT_STREAM);
259 }
260
261 if (err != OK) {
262 return err;
263 }
264 }
265 }
266
267 TrackInfo *info = &mTrackInfos.editItemAt(trackIndex);
268
269 return info->mSender->queueBuffer(
270 accessUnit,
271 info->mIsAudio ? 96 : 97 /* packetType */,
272 info->mIsAudio
273 ? RTPSender::PACKETIZATION_AAC : RTPSender::PACKETIZATION_H264);
274}
275
276void MediaSender::onMessageReceived(const sp<AMessage> &msg) {
277 switch (msg->what()) {
278 case kWhatSenderNotify:
279 {
280 int32_t generation;
281 CHECK(msg->findInt32("generation", &generation));
282 if (generation != mGeneration) {
283 break;
284 }
285
286 onSenderNotify(msg);
287 break;
288 }
289
290 default:
291 TRESPASS();
292 }
293}
294
295void MediaSender::onSenderNotify(const sp<AMessage> &msg) {
296 int32_t what;
297 CHECK(msg->findInt32("what", &what));
298
299 switch (what) {
300 case RTPSender::kWhatInitDone:
301 {
302 --mInitDoneCount;
303
304 int32_t err;
305 CHECK(msg->findInt32("err", &err));
306
307 if (err != OK) {
308 notifyInitDone(err);
309 ++mGeneration;
310 break;
311 }
312
313 if (mInitDoneCount == 0) {
314 notifyInitDone(OK);
315 }
316 break;
317 }
318
319 case RTPSender::kWhatError:
320 {
321 int32_t err;
322 CHECK(msg->findInt32("err", &err));
323
324 notifyError(err);
325 break;
326 }
327
328 default:
329 TRESPASS();
330 }
331}
332
333void MediaSender::notifyInitDone(status_t err) {
334 sp<AMessage> notify = mNotify->dup();
335 notify->setInt32("what", kWhatInitDone);
336 notify->setInt32("err", err);
337 notify->post();
338}
339
340void MediaSender::notifyError(status_t err) {
341 sp<AMessage> notify = mNotify->dup();
342 notify->setInt32("what", kWhatError);
343 notify->setInt32("err", err);
344 notify->post();
345}
346
347status_t MediaSender::packetizeAccessUnit(
348 size_t trackIndex,
349 sp<ABuffer> accessUnit,
350 sp<ABuffer> *tsPackets) {
351 const TrackInfo &info = mTrackInfos.itemAt(trackIndex);
352
353 uint32_t flags = 0;
354
355 bool isHDCPEncrypted = false;
356 uint64_t inputCTR;
357 uint8_t HDCP_private_data[16];
358
359 bool manuallyPrependSPSPPS =
360 !info.mIsAudio
361 && (info.mFlags & FLAG_MANUALLY_PREPEND_SPS_PPS)
362 && IsIDR(accessUnit);
363
364 if (mHDCP != NULL && !info.mIsAudio) {
365 isHDCPEncrypted = true;
366
367 if (manuallyPrependSPSPPS) {
368 accessUnit = mTSPacketizer->prependCSD(
369 info.mPacketizerTrackIndex, accessUnit);
370 }
371
372 status_t err = mHDCP->encrypt(
373 accessUnit->data(), accessUnit->size(),
374 trackIndex /* streamCTR */,
375 &inputCTR,
376 accessUnit->data());
377
378 if (err != OK) {
379 ALOGE("Failed to HDCP-encrypt media data (err %d)",
380 err);
381
382 return err;
383 }
384
385 HDCP_private_data[0] = 0x00;
386
387 HDCP_private_data[1] =
388 (((trackIndex >> 30) & 3) << 1) | 1;
389
390 HDCP_private_data[2] = (trackIndex >> 22) & 0xff;
391
392 HDCP_private_data[3] =
393 (((trackIndex >> 15) & 0x7f) << 1) | 1;
394
395 HDCP_private_data[4] = (trackIndex >> 7) & 0xff;
396
397 HDCP_private_data[5] =
398 ((trackIndex & 0x7f) << 1) | 1;
399
400 HDCP_private_data[6] = 0x00;
401
402 HDCP_private_data[7] =
403 (((inputCTR >> 60) & 0x0f) << 1) | 1;
404
405 HDCP_private_data[8] = (inputCTR >> 52) & 0xff;
406
407 HDCP_private_data[9] =
408 (((inputCTR >> 45) & 0x7f) << 1) | 1;
409
410 HDCP_private_data[10] = (inputCTR >> 37) & 0xff;
411
412 HDCP_private_data[11] =
413 (((inputCTR >> 30) & 0x7f) << 1) | 1;
414
415 HDCP_private_data[12] = (inputCTR >> 22) & 0xff;
416
417 HDCP_private_data[13] =
418 (((inputCTR >> 15) & 0x7f) << 1) | 1;
419
420 HDCP_private_data[14] = (inputCTR >> 7) & 0xff;
421
422 HDCP_private_data[15] =
423 ((inputCTR & 0x7f) << 1) | 1;
424
425 flags |= TSPacketizer::IS_ENCRYPTED;
426 } else if (manuallyPrependSPSPPS) {
427 flags |= TSPacketizer::PREPEND_SPS_PPS_TO_IDR_FRAMES;
428 }
429
430 int64_t timeUs = ALooper::GetNowUs();
431 if (mPrevTimeUs < 0ll || mPrevTimeUs + 100000ll <= timeUs) {
432 flags |= TSPacketizer::EMIT_PCR;
433 flags |= TSPacketizer::EMIT_PAT_AND_PMT;
434
435 mPrevTimeUs = timeUs;
436 }
437
438 mTSPacketizer->packetize(
439 info.mPacketizerTrackIndex,
440 accessUnit,
441 tsPackets,
442 flags,
443 !isHDCPEncrypted ? NULL : HDCP_private_data,
444 !isHDCPEncrypted ? 0 : sizeof(HDCP_private_data),
445 info.mIsAudio ? 2 : 0 /* numStuffingBytes */);
446
447 return OK;
448}
449
450} // namespace android
451