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> ¬ify) 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