Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 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 "TSPacketizer" |
| 19 | #include <utils/Log.h> |
| 20 | |
| 21 | #include "TSPacketizer.h" |
| 22 | #include "include/avc_utils.h" |
| 23 | |
| 24 | #include <media/stagefright/foundation/ABuffer.h> |
| 25 | #include <media/stagefright/foundation/ADebug.h> |
| 26 | #include <media/stagefright/foundation/AMessage.h> |
| 27 | #include <media/stagefright/foundation/hexdump.h> |
| 28 | #include <media/stagefright/MediaDefs.h> |
| 29 | #include <media/stagefright/MediaErrors.h> |
| 30 | |
| 31 | #include <arpa/inet.h> |
| 32 | |
| 33 | namespace android { |
| 34 | |
| 35 | struct TSPacketizer::Track : public RefBase { |
| 36 | Track(const sp<AMessage> &format, |
| 37 | unsigned PID, unsigned streamType, unsigned streamID); |
| 38 | |
| 39 | unsigned PID() const; |
| 40 | unsigned streamType() const; |
| 41 | unsigned streamID() const; |
| 42 | |
| 43 | // Returns the previous value. |
| 44 | unsigned incrementContinuityCounter(); |
| 45 | |
| 46 | bool isAudio() const; |
| 47 | bool isVideo() const; |
| 48 | |
| 49 | bool isH264() const; |
Andreas Huber | e7bd24a | 2012-10-04 11:46:29 -0700 | [diff] [blame] | 50 | bool isAAC() const; |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 51 | bool lacksADTSHeader() const; |
Andreas Huber | 90a9205 | 2012-10-30 15:53:03 -0700 | [diff] [blame] | 52 | bool isPCMAudio() const; |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 53 | |
| 54 | sp<ABuffer> prependCSD(const sp<ABuffer> &accessUnit) const; |
| 55 | sp<ABuffer> prependADTSHeader(const sp<ABuffer> &accessUnit) const; |
| 56 | |
Andreas Huber | 90a9205 | 2012-10-30 15:53:03 -0700 | [diff] [blame] | 57 | size_t countDescriptors() const; |
| 58 | sp<ABuffer> descriptorAt(size_t index) const; |
| 59 | |
| 60 | void finalize(); |
Andreas Huber | a556c48 | 2013-03-05 10:56:27 -0800 | [diff] [blame] | 61 | void extractCSDIfNecessary(); |
Andreas Huber | 90a9205 | 2012-10-30 15:53:03 -0700 | [diff] [blame] | 62 | |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 63 | protected: |
| 64 | virtual ~Track(); |
| 65 | |
| 66 | private: |
| 67 | sp<AMessage> mFormat; |
| 68 | |
| 69 | unsigned mPID; |
| 70 | unsigned mStreamType; |
| 71 | unsigned mStreamID; |
| 72 | unsigned mContinuityCounter; |
| 73 | |
| 74 | AString mMIME; |
| 75 | Vector<sp<ABuffer> > mCSD; |
| 76 | |
Andreas Huber | 90a9205 | 2012-10-30 15:53:03 -0700 | [diff] [blame] | 77 | Vector<sp<ABuffer> > mDescriptors; |
| 78 | |
Andreas Huber | b8c7bd4 | 2012-09-18 14:47:48 -0700 | [diff] [blame] | 79 | bool mAudioLacksATDSHeaders; |
Andreas Huber | 90a9205 | 2012-10-30 15:53:03 -0700 | [diff] [blame] | 80 | bool mFinalized; |
Andreas Huber | a556c48 | 2013-03-05 10:56:27 -0800 | [diff] [blame] | 81 | bool mExtractedCSD; |
Andreas Huber | b8c7bd4 | 2012-09-18 14:47:48 -0700 | [diff] [blame] | 82 | |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 83 | DISALLOW_EVIL_CONSTRUCTORS(Track); |
| 84 | }; |
| 85 | |
| 86 | TSPacketizer::Track::Track( |
| 87 | const sp<AMessage> &format, |
| 88 | unsigned PID, unsigned streamType, unsigned streamID) |
| 89 | : mFormat(format), |
| 90 | mPID(PID), |
| 91 | mStreamType(streamType), |
| 92 | mStreamID(streamID), |
Andreas Huber | b8c7bd4 | 2012-09-18 14:47:48 -0700 | [diff] [blame] | 93 | mContinuityCounter(0), |
Andreas Huber | 90a9205 | 2012-10-30 15:53:03 -0700 | [diff] [blame] | 94 | mAudioLacksATDSHeaders(false), |
Andreas Huber | a556c48 | 2013-03-05 10:56:27 -0800 | [diff] [blame] | 95 | mFinalized(false), |
| 96 | mExtractedCSD(false) { |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 97 | CHECK(format->findString("mime", &mMIME)); |
Andreas Huber | a556c48 | 2013-03-05 10:56:27 -0800 | [diff] [blame] | 98 | } |
| 99 | |
| 100 | void TSPacketizer::Track::extractCSDIfNecessary() { |
| 101 | if (mExtractedCSD) { |
| 102 | return; |
| 103 | } |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 104 | |
| 105 | if (!strcasecmp(mMIME.c_str(), MEDIA_MIMETYPE_VIDEO_AVC) |
| 106 | || !strcasecmp(mMIME.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) { |
| 107 | for (size_t i = 0;; ++i) { |
| 108 | sp<ABuffer> csd; |
Andreas Huber | a556c48 | 2013-03-05 10:56:27 -0800 | [diff] [blame] | 109 | if (!mFormat->findBuffer(StringPrintf("csd-%d", i).c_str(), &csd)) { |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 110 | break; |
| 111 | } |
| 112 | |
| 113 | mCSD.push(csd); |
| 114 | } |
Andreas Huber | b8c7bd4 | 2012-09-18 14:47:48 -0700 | [diff] [blame] | 115 | |
| 116 | if (!strcasecmp(mMIME.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) { |
| 117 | int32_t isADTS; |
| 118 | if (!mFormat->findInt32("is-adts", &isADTS) || isADTS == 0) { |
| 119 | mAudioLacksATDSHeaders = true; |
| 120 | } |
| 121 | } |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 122 | } |
Andreas Huber | a556c48 | 2013-03-05 10:56:27 -0800 | [diff] [blame] | 123 | |
| 124 | mExtractedCSD = true; |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 125 | } |
| 126 | |
| 127 | TSPacketizer::Track::~Track() { |
| 128 | } |
| 129 | |
| 130 | unsigned TSPacketizer::Track::PID() const { |
| 131 | return mPID; |
| 132 | } |
| 133 | |
| 134 | unsigned TSPacketizer::Track::streamType() const { |
| 135 | return mStreamType; |
| 136 | } |
| 137 | |
| 138 | unsigned TSPacketizer::Track::streamID() const { |
| 139 | return mStreamID; |
| 140 | } |
| 141 | |
| 142 | unsigned TSPacketizer::Track::incrementContinuityCounter() { |
| 143 | unsigned prevCounter = mContinuityCounter; |
| 144 | |
| 145 | if (++mContinuityCounter == 16) { |
| 146 | mContinuityCounter = 0; |
| 147 | } |
| 148 | |
| 149 | return prevCounter; |
| 150 | } |
| 151 | |
| 152 | bool TSPacketizer::Track::isAudio() const { |
| 153 | return !strncasecmp("audio/", mMIME.c_str(), 6); |
| 154 | } |
| 155 | |
| 156 | bool TSPacketizer::Track::isVideo() const { |
| 157 | return !strncasecmp("video/", mMIME.c_str(), 6); |
| 158 | } |
| 159 | |
| 160 | bool TSPacketizer::Track::isH264() const { |
| 161 | return !strcasecmp(mMIME.c_str(), MEDIA_MIMETYPE_VIDEO_AVC); |
| 162 | } |
| 163 | |
Andreas Huber | e7bd24a | 2012-10-04 11:46:29 -0700 | [diff] [blame] | 164 | bool TSPacketizer::Track::isAAC() const { |
| 165 | return !strcasecmp(mMIME.c_str(), MEDIA_MIMETYPE_AUDIO_AAC); |
| 166 | } |
| 167 | |
Andreas Huber | 90a9205 | 2012-10-30 15:53:03 -0700 | [diff] [blame] | 168 | bool TSPacketizer::Track::isPCMAudio() const { |
| 169 | return !strcasecmp(mMIME.c_str(), MEDIA_MIMETYPE_AUDIO_RAW); |
| 170 | } |
| 171 | |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 172 | bool TSPacketizer::Track::lacksADTSHeader() const { |
Andreas Huber | b8c7bd4 | 2012-09-18 14:47:48 -0700 | [diff] [blame] | 173 | return mAudioLacksATDSHeaders; |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 174 | } |
| 175 | |
| 176 | sp<ABuffer> TSPacketizer::Track::prependCSD( |
| 177 | const sp<ABuffer> &accessUnit) const { |
| 178 | size_t size = 0; |
| 179 | for (size_t i = 0; i < mCSD.size(); ++i) { |
| 180 | size += mCSD.itemAt(i)->size(); |
| 181 | } |
| 182 | |
| 183 | sp<ABuffer> dup = new ABuffer(accessUnit->size() + size); |
| 184 | size_t offset = 0; |
| 185 | for (size_t i = 0; i < mCSD.size(); ++i) { |
| 186 | const sp<ABuffer> &csd = mCSD.itemAt(i); |
| 187 | |
| 188 | memcpy(dup->data() + offset, csd->data(), csd->size()); |
| 189 | offset += csd->size(); |
| 190 | } |
| 191 | |
| 192 | memcpy(dup->data() + offset, accessUnit->data(), accessUnit->size()); |
| 193 | |
| 194 | return dup; |
| 195 | } |
| 196 | |
| 197 | sp<ABuffer> TSPacketizer::Track::prependADTSHeader( |
| 198 | const sp<ABuffer> &accessUnit) const { |
| 199 | CHECK_EQ(mCSD.size(), 1u); |
| 200 | |
| 201 | const uint8_t *codec_specific_data = mCSD.itemAt(0)->data(); |
| 202 | |
| 203 | const uint32_t aac_frame_length = accessUnit->size() + 7; |
| 204 | |
| 205 | sp<ABuffer> dup = new ABuffer(aac_frame_length); |
| 206 | |
| 207 | unsigned profile = (codec_specific_data[0] >> 3) - 1; |
| 208 | |
| 209 | unsigned sampling_freq_index = |
| 210 | ((codec_specific_data[0] & 7) << 1) |
| 211 | | (codec_specific_data[1] >> 7); |
| 212 | |
| 213 | unsigned channel_configuration = |
| 214 | (codec_specific_data[1] >> 3) & 0x0f; |
| 215 | |
| 216 | uint8_t *ptr = dup->data(); |
| 217 | |
| 218 | *ptr++ = 0xff; |
| 219 | *ptr++ = 0xf1; // b11110001, ID=0, layer=0, protection_absent=1 |
| 220 | |
| 221 | *ptr++ = |
| 222 | profile << 6 |
| 223 | | sampling_freq_index << 2 |
| 224 | | ((channel_configuration >> 2) & 1); // private_bit=0 |
| 225 | |
| 226 | // original_copy=0, home=0, copyright_id_bit=0, copyright_id_start=0 |
| 227 | *ptr++ = |
| 228 | (channel_configuration & 3) << 6 |
| 229 | | aac_frame_length >> 11; |
| 230 | *ptr++ = (aac_frame_length >> 3) & 0xff; |
| 231 | *ptr++ = (aac_frame_length & 7) << 5; |
| 232 | |
| 233 | // adts_buffer_fullness=0, number_of_raw_data_blocks_in_frame=0 |
| 234 | *ptr++ = 0; |
| 235 | |
| 236 | memcpy(ptr, accessUnit->data(), accessUnit->size()); |
| 237 | |
| 238 | return dup; |
| 239 | } |
| 240 | |
Andreas Huber | 90a9205 | 2012-10-30 15:53:03 -0700 | [diff] [blame] | 241 | size_t TSPacketizer::Track::countDescriptors() const { |
| 242 | return mDescriptors.size(); |
| 243 | } |
| 244 | |
| 245 | sp<ABuffer> TSPacketizer::Track::descriptorAt(size_t index) const { |
| 246 | CHECK_LT(index, mDescriptors.size()); |
| 247 | return mDescriptors.itemAt(index); |
| 248 | } |
| 249 | |
| 250 | void TSPacketizer::Track::finalize() { |
| 251 | if (mFinalized) { |
| 252 | return; |
| 253 | } |
| 254 | |
| 255 | if (isH264()) { |
| 256 | { |
| 257 | // AVC video descriptor (40) |
| 258 | |
| 259 | sp<ABuffer> descriptor = new ABuffer(6); |
| 260 | uint8_t *data = descriptor->data(); |
| 261 | data[0] = 40; // descriptor_tag |
| 262 | data[1] = 4; // descriptor_length |
| 263 | |
| 264 | CHECK_EQ(mCSD.size(), 1u); |
| 265 | const sp<ABuffer> &sps = mCSD.itemAt(0); |
| 266 | CHECK(!memcmp("\x00\x00\x00\x01", sps->data(), 4)); |
| 267 | CHECK_GE(sps->size(), 7u); |
| 268 | // profile_idc, constraint_set*, level_idc |
| 269 | memcpy(&data[2], sps->data() + 4, 3); |
| 270 | |
| 271 | // AVC_still_present=0, AVC_24_hour_picture_flag=0, reserved |
| 272 | data[5] = 0x3f; |
| 273 | |
| 274 | mDescriptors.push_back(descriptor); |
| 275 | } |
| 276 | |
| 277 | { |
| 278 | // AVC timing and HRD descriptor (42) |
| 279 | |
| 280 | sp<ABuffer> descriptor = new ABuffer(4); |
| 281 | uint8_t *data = descriptor->data(); |
| 282 | data[0] = 42; // descriptor_tag |
| 283 | data[1] = 2; // descriptor_length |
| 284 | |
| 285 | // hrd_management_valid_flag = 0 |
| 286 | // reserved = 111111b |
| 287 | // picture_and_timing_info_present = 0 |
| 288 | |
| 289 | data[2] = 0x7e; |
| 290 | |
| 291 | // fixed_frame_rate_flag = 0 |
| 292 | // temporal_poc_flag = 0 |
| 293 | // picture_to_display_conversion_flag = 0 |
| 294 | // reserved = 11111b |
| 295 | data[3] = 0x1f; |
| 296 | |
| 297 | mDescriptors.push_back(descriptor); |
| 298 | } |
| 299 | } else if (isPCMAudio()) { |
| 300 | // LPCM audio stream descriptor (0x83) |
| 301 | |
| 302 | int32_t channelCount; |
| 303 | CHECK(mFormat->findInt32("channel-count", &channelCount)); |
| 304 | CHECK_EQ(channelCount, 2); |
| 305 | |
| 306 | int32_t sampleRate; |
| 307 | CHECK(mFormat->findInt32("sample-rate", &sampleRate)); |
| 308 | CHECK(sampleRate == 44100 || sampleRate == 48000); |
| 309 | |
| 310 | sp<ABuffer> descriptor = new ABuffer(4); |
| 311 | uint8_t *data = descriptor->data(); |
| 312 | data[0] = 0x83; // descriptor_tag |
| 313 | data[1] = 2; // descriptor_length |
| 314 | |
| 315 | unsigned sampling_frequency = (sampleRate == 44100) ? 1 : 2; |
| 316 | |
| 317 | data[2] = (sampling_frequency << 5) |
| 318 | | (3 /* reserved */ << 1) |
| 319 | | 0 /* emphasis_flag */; |
| 320 | |
| 321 | data[3] = |
| 322 | (1 /* number_of_channels = stereo */ << 5) |
| 323 | | 0xf /* reserved */; |
| 324 | |
| 325 | mDescriptors.push_back(descriptor); |
| 326 | } |
| 327 | |
Andreas Huber | bfd79f2 | 2013-03-07 10:33:20 -0800 | [diff] [blame^] | 328 | mFinalized = true; |
| 329 | } |
| 330 | |
| 331 | //////////////////////////////////////////////////////////////////////////////// |
| 332 | |
| 333 | TSPacketizer::TSPacketizer(uint32_t flags) |
| 334 | : mFlags(flags), |
| 335 | mPATContinuityCounter(0), |
| 336 | mPMTContinuityCounter(0) { |
| 337 | initCrcTable(); |
| 338 | |
| 339 | if (flags & (EMIT_HDCP20_DESCRIPTOR | EMIT_HDCP21_DESCRIPTOR)) { |
| 340 | int32_t hdcpVersion; |
| 341 | if (flags & EMIT_HDCP20_DESCRIPTOR) { |
| 342 | CHECK(!(flags & EMIT_HDCP21_DESCRIPTOR)); |
| 343 | hdcpVersion = 0x20; |
| 344 | } else { |
| 345 | CHECK(!(flags & EMIT_HDCP20_DESCRIPTOR)); |
| 346 | |
| 347 | // HDCP2.0 _and_ HDCP 2.1 specs say to set the version |
| 348 | // inside the HDCP descriptor to 0x20!!! |
| 349 | hdcpVersion = 0x20; |
| 350 | } |
| 351 | |
Andreas Huber | 0224bf1 | 2012-11-12 13:08:44 -0800 | [diff] [blame] | 352 | // HDCP descriptor |
Andreas Huber | 0224bf1 | 2012-11-12 13:08:44 -0800 | [diff] [blame] | 353 | sp<ABuffer> descriptor = new ABuffer(7); |
| 354 | uint8_t *data = descriptor->data(); |
| 355 | data[0] = 0x05; // descriptor_tag |
| 356 | data[1] = 5; // descriptor_length |
| 357 | data[2] = 'H'; |
| 358 | data[3] = 'D'; |
| 359 | data[4] = 'C'; |
| 360 | data[5] = 'P'; |
| 361 | data[6] = hdcpVersion; |
| 362 | |
Andreas Huber | bfd79f2 | 2013-03-07 10:33:20 -0800 | [diff] [blame^] | 363 | mProgramInfoDescriptors.push_back(descriptor); |
Andreas Huber | 0224bf1 | 2012-11-12 13:08:44 -0800 | [diff] [blame] | 364 | } |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 365 | } |
| 366 | |
| 367 | TSPacketizer::~TSPacketizer() { |
| 368 | } |
| 369 | |
| 370 | ssize_t TSPacketizer::addTrack(const sp<AMessage> &format) { |
| 371 | AString mime; |
| 372 | CHECK(format->findString("mime", &mime)); |
| 373 | |
| 374 | unsigned PIDStart; |
| 375 | bool isVideo = !strncasecmp("video/", mime.c_str(), 6); |
| 376 | bool isAudio = !strncasecmp("audio/", mime.c_str(), 6); |
| 377 | |
| 378 | if (isVideo) { |
| 379 | PIDStart = 0x1011; |
| 380 | } else if (isAudio) { |
| 381 | PIDStart = 0x1100; |
| 382 | } else { |
| 383 | return ERROR_UNSUPPORTED; |
| 384 | } |
| 385 | |
| 386 | unsigned streamType; |
| 387 | unsigned streamIDStart; |
| 388 | unsigned streamIDStop; |
| 389 | |
| 390 | if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) { |
| 391 | streamType = 0x1b; |
| 392 | streamIDStart = 0xe0; |
| 393 | streamIDStop = 0xef; |
| 394 | } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) { |
| 395 | streamType = 0x0f; |
| 396 | streamIDStart = 0xc0; |
| 397 | streamIDStop = 0xdf; |
Andreas Huber | e7bd24a | 2012-10-04 11:46:29 -0700 | [diff] [blame] | 398 | } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_RAW)) { |
| 399 | streamType = 0x83; |
| 400 | streamIDStart = 0xbd; |
| 401 | streamIDStop = 0xbd; |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 402 | } else { |
| 403 | return ERROR_UNSUPPORTED; |
| 404 | } |
| 405 | |
| 406 | size_t numTracksOfThisType = 0; |
| 407 | unsigned PID = PIDStart; |
| 408 | |
| 409 | for (size_t i = 0; i < mTracks.size(); ++i) { |
| 410 | const sp<Track> &track = mTracks.itemAt(i); |
| 411 | |
| 412 | if (track->streamType() == streamType) { |
| 413 | ++numTracksOfThisType; |
| 414 | } |
| 415 | |
| 416 | if ((isAudio && track->isAudio()) || (isVideo && track->isVideo())) { |
| 417 | ++PID; |
| 418 | } |
| 419 | } |
| 420 | |
| 421 | unsigned streamID = streamIDStart + numTracksOfThisType; |
| 422 | if (streamID > streamIDStop) { |
| 423 | return -ERANGE; |
| 424 | } |
| 425 | |
| 426 | sp<Track> track = new Track(format, PID, streamType, streamID); |
| 427 | return mTracks.add(track); |
| 428 | } |
| 429 | |
Andreas Huber | a556c48 | 2013-03-05 10:56:27 -0800 | [diff] [blame] | 430 | status_t TSPacketizer::extractCSDIfNecessary(size_t trackIndex) { |
| 431 | if (trackIndex >= mTracks.size()) { |
| 432 | return -ERANGE; |
| 433 | } |
| 434 | |
| 435 | const sp<Track> &track = mTracks.itemAt(trackIndex); |
| 436 | track->extractCSDIfNecessary(); |
| 437 | |
| 438 | return OK; |
| 439 | } |
| 440 | |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 441 | status_t TSPacketizer::packetize( |
| 442 | size_t trackIndex, |
| 443 | const sp<ABuffer> &_accessUnit, |
| 444 | sp<ABuffer> *packets, |
Andreas Huber | b8c7bd4 | 2012-09-18 14:47:48 -0700 | [diff] [blame] | 445 | uint32_t flags, |
Andreas Huber | 90a9205 | 2012-10-30 15:53:03 -0700 | [diff] [blame] | 446 | const uint8_t *PES_private_data, size_t PES_private_data_len, |
| 447 | size_t numStuffingBytes) { |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 448 | sp<ABuffer> accessUnit = _accessUnit; |
| 449 | |
Andreas Huber | 28e17ed | 2012-09-25 14:20:08 -0700 | [diff] [blame] | 450 | int64_t timeUs; |
| 451 | CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs)); |
| 452 | |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 453 | packets->clear(); |
| 454 | |
| 455 | if (trackIndex >= mTracks.size()) { |
| 456 | return -ERANGE; |
| 457 | } |
| 458 | |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 459 | const sp<Track> &track = mTracks.itemAt(trackIndex); |
| 460 | |
Andreas Huber | c6920df | 2012-10-02 10:16:47 -0700 | [diff] [blame] | 461 | if (track->isH264() && (flags & PREPEND_SPS_PPS_TO_IDR_FRAMES) |
| 462 | && IsIDR(accessUnit)) { |
| 463 | // prepend codec specific data, i.e. SPS and PPS. |
| 464 | accessUnit = track->prependCSD(accessUnit); |
Andreas Huber | e7bd24a | 2012-10-04 11:46:29 -0700 | [diff] [blame] | 465 | } else if (track->isAAC() && track->lacksADTSHeader()) { |
Andreas Huber | b8c7bd4 | 2012-09-18 14:47:48 -0700 | [diff] [blame] | 466 | CHECK(!(flags & IS_ENCRYPTED)); |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 467 | accessUnit = track->prependADTSHeader(accessUnit); |
| 468 | } |
| 469 | |
| 470 | // 0x47 |
| 471 | // transport_error_indicator = b0 |
| 472 | // payload_unit_start_indicator = b1 |
| 473 | // transport_priority = b0 |
| 474 | // PID |
| 475 | // transport_scrambling_control = b00 |
| 476 | // adaptation_field_control = b?? |
| 477 | // continuity_counter = b???? |
| 478 | // -- payload follows |
| 479 | // packet_startcode_prefix = 0x000001 |
| 480 | // stream_id |
| 481 | // PES_packet_length = 0x???? |
| 482 | // reserved = b10 |
| 483 | // PES_scrambling_control = b00 |
| 484 | // PES_priority = b0 |
| 485 | // data_alignment_indicator = b1 |
| 486 | // copyright = b0 |
| 487 | // original_or_copy = b0 |
| 488 | // PTS_DTS_flags = b10 (PTS only) |
| 489 | // ESCR_flag = b0 |
| 490 | // ES_rate_flag = b0 |
| 491 | // DSM_trick_mode_flag = b0 |
| 492 | // additional_copy_info_flag = b0 |
| 493 | // PES_CRC_flag = b0 |
| 494 | // PES_extension_flag = b0 |
| 495 | // PES_header_data_length = 0x05 |
| 496 | // reserved = b0010 (PTS) |
| 497 | // PTS[32..30] = b??? |
| 498 | // reserved = b1 |
| 499 | // PTS[29..15] = b??? ???? ???? ???? (15 bits) |
| 500 | // reserved = b1 |
| 501 | // PTS[14..0] = b??? ???? ???? ???? (15 bits) |
| 502 | // reserved = b1 |
| 503 | // the first fragment of "buffer" follows |
| 504 | |
Andreas Huber | 90a9205 | 2012-10-30 15:53:03 -0700 | [diff] [blame] | 505 | size_t PES_packet_length = accessUnit->size() + 8 + numStuffingBytes; |
Andreas Huber | b8c7bd4 | 2012-09-18 14:47:48 -0700 | [diff] [blame] | 506 | if (PES_private_data_len > 0) { |
| 507 | PES_packet_length += PES_private_data_len + 1; |
| 508 | } |
| 509 | |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 510 | size_t numTSPackets; |
Andreas Huber | b8c7bd4 | 2012-09-18 14:47:48 -0700 | [diff] [blame] | 511 | if (PES_packet_length <= 178) { |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 512 | numTSPackets = 1; |
| 513 | } else { |
Andreas Huber | b8c7bd4 | 2012-09-18 14:47:48 -0700 | [diff] [blame] | 514 | numTSPackets = 1 + ((PES_packet_length - 178) + 183) / 184; |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 515 | } |
| 516 | |
| 517 | if (flags & EMIT_PAT_AND_PMT) { |
| 518 | numTSPackets += 2; |
| 519 | } |
| 520 | |
| 521 | if (flags & EMIT_PCR) { |
| 522 | ++numTSPackets; |
| 523 | } |
| 524 | |
| 525 | sp<ABuffer> buffer = new ABuffer(numTSPackets * 188); |
| 526 | uint8_t *packetDataStart = buffer->data(); |
| 527 | |
| 528 | if (flags & EMIT_PAT_AND_PMT) { |
| 529 | // Program Association Table (PAT): |
| 530 | // 0x47 |
| 531 | // transport_error_indicator = b0 |
| 532 | // payload_unit_start_indicator = b1 |
| 533 | // transport_priority = b0 |
| 534 | // PID = b0000000000000 (13 bits) |
| 535 | // transport_scrambling_control = b00 |
| 536 | // adaptation_field_control = b01 (no adaptation field, payload only) |
| 537 | // continuity_counter = b???? |
| 538 | // skip = 0x00 |
| 539 | // --- payload follows |
| 540 | // table_id = 0x00 |
| 541 | // section_syntax_indicator = b1 |
| 542 | // must_be_zero = b0 |
| 543 | // reserved = b11 |
| 544 | // section_length = 0x00d |
| 545 | // transport_stream_id = 0x0000 |
| 546 | // reserved = b11 |
| 547 | // version_number = b00001 |
| 548 | // current_next_indicator = b1 |
| 549 | // section_number = 0x00 |
| 550 | // last_section_number = 0x00 |
| 551 | // one program follows: |
| 552 | // program_number = 0x0001 |
| 553 | // reserved = b111 |
| 554 | // program_map_PID = kPID_PMT (13 bits!) |
| 555 | // CRC = 0x???????? |
| 556 | |
| 557 | if (++mPATContinuityCounter == 16) { |
| 558 | mPATContinuityCounter = 0; |
| 559 | } |
| 560 | |
| 561 | uint8_t *ptr = packetDataStart; |
| 562 | *ptr++ = 0x47; |
| 563 | *ptr++ = 0x40; |
| 564 | *ptr++ = 0x00; |
| 565 | *ptr++ = 0x10 | mPATContinuityCounter; |
| 566 | *ptr++ = 0x00; |
| 567 | |
Andreas Huber | 90a9205 | 2012-10-30 15:53:03 -0700 | [diff] [blame] | 568 | uint8_t *crcDataStart = ptr; |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 569 | *ptr++ = 0x00; |
| 570 | *ptr++ = 0xb0; |
| 571 | *ptr++ = 0x0d; |
| 572 | *ptr++ = 0x00; |
| 573 | *ptr++ = 0x00; |
| 574 | *ptr++ = 0xc3; |
| 575 | *ptr++ = 0x00; |
| 576 | *ptr++ = 0x00; |
| 577 | *ptr++ = 0x00; |
| 578 | *ptr++ = 0x01; |
| 579 | *ptr++ = 0xe0 | (kPID_PMT >> 8); |
| 580 | *ptr++ = kPID_PMT & 0xff; |
| 581 | |
| 582 | CHECK_EQ(ptr - crcDataStart, 12); |
| 583 | uint32_t crc = htonl(crc32(crcDataStart, ptr - crcDataStart)); |
| 584 | memcpy(ptr, &crc, 4); |
| 585 | ptr += 4; |
| 586 | |
| 587 | size_t sizeLeft = packetDataStart + 188 - ptr; |
| 588 | memset(ptr, 0xff, sizeLeft); |
| 589 | |
| 590 | packetDataStart += 188; |
| 591 | |
| 592 | // Program Map (PMT): |
| 593 | // 0x47 |
| 594 | // transport_error_indicator = b0 |
| 595 | // payload_unit_start_indicator = b1 |
| 596 | // transport_priority = b0 |
| 597 | // PID = kPID_PMT (13 bits) |
| 598 | // transport_scrambling_control = b00 |
| 599 | // adaptation_field_control = b01 (no adaptation field, payload only) |
| 600 | // continuity_counter = b???? |
| 601 | // skip = 0x00 |
| 602 | // -- payload follows |
| 603 | // table_id = 0x02 |
| 604 | // section_syntax_indicator = b1 |
| 605 | // must_be_zero = b0 |
| 606 | // reserved = b11 |
| 607 | // section_length = 0x??? |
| 608 | // program_number = 0x0001 |
| 609 | // reserved = b11 |
| 610 | // version_number = b00001 |
| 611 | // current_next_indicator = b1 |
| 612 | // section_number = 0x00 |
| 613 | // last_section_number = 0x00 |
| 614 | // reserved = b111 |
| 615 | // PCR_PID = kPCR_PID (13 bits) |
| 616 | // reserved = b1111 |
Andreas Huber | bfd79f2 | 2013-03-07 10:33:20 -0800 | [diff] [blame^] | 617 | // program_info_length = 0x??? |
| 618 | // program_info_descriptors follow |
| 619 | // one or more elementary stream descriptions follow: |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 620 | // stream_type = 0x?? |
| 621 | // reserved = b111 |
| 622 | // elementary_PID = b? ???? ???? ???? (13 bits) |
| 623 | // reserved = b1111 |
| 624 | // ES_info_length = 0x000 |
| 625 | // CRC = 0x???????? |
| 626 | |
| 627 | if (++mPMTContinuityCounter == 16) { |
| 628 | mPMTContinuityCounter = 0; |
| 629 | } |
| 630 | |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 631 | ptr = packetDataStart; |
| 632 | *ptr++ = 0x47; |
| 633 | *ptr++ = 0x40 | (kPID_PMT >> 8); |
| 634 | *ptr++ = kPID_PMT & 0xff; |
| 635 | *ptr++ = 0x10 | mPMTContinuityCounter; |
| 636 | *ptr++ = 0x00; |
| 637 | |
| 638 | crcDataStart = ptr; |
| 639 | *ptr++ = 0x02; |
Andreas Huber | 90a9205 | 2012-10-30 15:53:03 -0700 | [diff] [blame] | 640 | |
| 641 | *ptr++ = 0x00; // section_length to be filled in below. |
| 642 | *ptr++ = 0x00; |
| 643 | |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 644 | *ptr++ = 0x00; |
| 645 | *ptr++ = 0x01; |
| 646 | *ptr++ = 0xc3; |
| 647 | *ptr++ = 0x00; |
| 648 | *ptr++ = 0x00; |
| 649 | *ptr++ = 0xe0 | (kPID_PCR >> 8); |
| 650 | *ptr++ = kPID_PCR & 0xff; |
Andreas Huber | bfd79f2 | 2013-03-07 10:33:20 -0800 | [diff] [blame^] | 651 | |
| 652 | size_t program_info_length = 0; |
| 653 | for (size_t i = 0; i < mProgramInfoDescriptors.size(); ++i) { |
| 654 | program_info_length += mProgramInfoDescriptors.itemAt(i)->size(); |
| 655 | } |
| 656 | |
| 657 | CHECK_LT(program_info_length, 0x400); |
| 658 | *ptr++ = 0xf0 | (program_info_length >> 8); |
| 659 | *ptr++ = (program_info_length & 0xff); |
| 660 | |
| 661 | for (size_t i = 0; i < mProgramInfoDescriptors.size(); ++i) { |
| 662 | const sp<ABuffer> &desc = mProgramInfoDescriptors.itemAt(i); |
| 663 | memcpy(ptr, desc->data(), desc->size()); |
| 664 | ptr += desc->size(); |
| 665 | } |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 666 | |
| 667 | for (size_t i = 0; i < mTracks.size(); ++i) { |
| 668 | const sp<Track> &track = mTracks.itemAt(i); |
| 669 | |
Andreas Huber | 90a9205 | 2012-10-30 15:53:03 -0700 | [diff] [blame] | 670 | // Make sure all the decriptors have been added. |
| 671 | track->finalize(); |
| 672 | |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 673 | *ptr++ = track->streamType(); |
| 674 | *ptr++ = 0xe0 | (track->PID() >> 8); |
| 675 | *ptr++ = track->PID() & 0xff; |
Andreas Huber | 90a9205 | 2012-10-30 15:53:03 -0700 | [diff] [blame] | 676 | |
| 677 | size_t ES_info_length = 0; |
| 678 | for (size_t i = 0; i < track->countDescriptors(); ++i) { |
| 679 | ES_info_length += track->descriptorAt(i)->size(); |
| 680 | } |
| 681 | CHECK_LE(ES_info_length, 0xfff); |
| 682 | |
| 683 | *ptr++ = 0xf0 | (ES_info_length >> 8); |
| 684 | *ptr++ = (ES_info_length & 0xff); |
| 685 | |
| 686 | for (size_t i = 0; i < track->countDescriptors(); ++i) { |
| 687 | const sp<ABuffer> &descriptor = track->descriptorAt(i); |
| 688 | memcpy(ptr, descriptor->data(), descriptor->size()); |
| 689 | ptr += descriptor->size(); |
| 690 | } |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 691 | } |
| 692 | |
Andreas Huber | 90a9205 | 2012-10-30 15:53:03 -0700 | [diff] [blame] | 693 | size_t section_length = ptr - (crcDataStart + 3) + 4 /* CRC */; |
| 694 | |
| 695 | crcDataStart[1] = 0xb0 | (section_length >> 8); |
| 696 | crcDataStart[2] = section_length & 0xff; |
| 697 | |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 698 | crc = htonl(crc32(crcDataStart, ptr - crcDataStart)); |
| 699 | memcpy(ptr, &crc, 4); |
| 700 | ptr += 4; |
| 701 | |
| 702 | sizeLeft = packetDataStart + 188 - ptr; |
| 703 | memset(ptr, 0xff, sizeLeft); |
| 704 | |
| 705 | packetDataStart += 188; |
| 706 | } |
| 707 | |
| 708 | if (flags & EMIT_PCR) { |
| 709 | // PCR stream |
| 710 | // 0x47 |
| 711 | // transport_error_indicator = b0 |
| 712 | // payload_unit_start_indicator = b1 |
| 713 | // transport_priority = b0 |
| 714 | // PID = kPCR_PID (13 bits) |
| 715 | // transport_scrambling_control = b00 |
| 716 | // adaptation_field_control = b10 (adaptation field only, no payload) |
| 717 | // continuity_counter = b0000 (does not increment) |
| 718 | // adaptation_field_length = 183 |
| 719 | // discontinuity_indicator = b0 |
| 720 | // random_access_indicator = b0 |
| 721 | // elementary_stream_priority_indicator = b0 |
| 722 | // PCR_flag = b1 |
| 723 | // OPCR_flag = b0 |
| 724 | // splicing_point_flag = b0 |
| 725 | // transport_private_data_flag = b0 |
| 726 | // adaptation_field_extension_flag = b0 |
| 727 | // program_clock_reference_base = b????????????????????????????????? |
| 728 | // reserved = b111111 |
| 729 | // program_clock_reference_extension = b????????? |
| 730 | |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 731 | int64_t nowUs = ALooper::GetNowUs(); |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 732 | |
| 733 | uint64_t PCR = nowUs * 27; // PCR based on a 27MHz clock |
| 734 | uint64_t PCR_base = PCR / 300; |
| 735 | uint32_t PCR_ext = PCR % 300; |
| 736 | |
| 737 | uint8_t *ptr = packetDataStart; |
| 738 | *ptr++ = 0x47; |
| 739 | *ptr++ = 0x40 | (kPID_PCR >> 8); |
| 740 | *ptr++ = kPID_PCR & 0xff; |
| 741 | *ptr++ = 0x20; |
| 742 | *ptr++ = 0xb7; // adaptation_field_length |
| 743 | *ptr++ = 0x10; |
| 744 | *ptr++ = (PCR_base >> 25) & 0xff; |
| 745 | *ptr++ = (PCR_base >> 17) & 0xff; |
| 746 | *ptr++ = (PCR_base >> 9) & 0xff; |
| 747 | *ptr++ = ((PCR_base & 1) << 7) | 0x7e | ((PCR_ext >> 8) & 1); |
| 748 | *ptr++ = (PCR_ext & 0xff); |
| 749 | |
| 750 | size_t sizeLeft = packetDataStart + 188 - ptr; |
| 751 | memset(ptr, 0xff, sizeLeft); |
| 752 | |
| 753 | packetDataStart += 188; |
| 754 | } |
| 755 | |
Andreas Huber | 28e17ed | 2012-09-25 14:20:08 -0700 | [diff] [blame] | 756 | uint64_t PTS = (timeUs * 9ll) / 100ll; |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 757 | |
Andreas Huber | b8c7bd4 | 2012-09-18 14:47:48 -0700 | [diff] [blame] | 758 | bool padding = (PES_packet_length < (188 - 10)); |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 759 | |
| 760 | if (PES_packet_length >= 65536) { |
| 761 | // This really should only happen for video. |
| 762 | CHECK(track->isVideo()); |
| 763 | |
| 764 | // It's valid to set this to 0 for video according to the specs. |
| 765 | PES_packet_length = 0; |
| 766 | } |
| 767 | |
| 768 | uint8_t *ptr = packetDataStart; |
| 769 | *ptr++ = 0x47; |
| 770 | *ptr++ = 0x40 | (track->PID() >> 8); |
| 771 | *ptr++ = track->PID() & 0xff; |
| 772 | *ptr++ = (padding ? 0x30 : 0x10) | track->incrementContinuityCounter(); |
| 773 | |
| 774 | if (padding) { |
Andreas Huber | b8c7bd4 | 2012-09-18 14:47:48 -0700 | [diff] [blame] | 775 | size_t paddingSize = 188 - 10 - PES_packet_length; |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 776 | *ptr++ = paddingSize - 1; |
| 777 | if (paddingSize >= 2) { |
| 778 | *ptr++ = 0x00; |
| 779 | memset(ptr, 0xff, paddingSize - 2); |
| 780 | ptr += paddingSize - 2; |
| 781 | } |
| 782 | } |
| 783 | |
| 784 | *ptr++ = 0x00; |
| 785 | *ptr++ = 0x00; |
| 786 | *ptr++ = 0x01; |
| 787 | *ptr++ = track->streamID(); |
| 788 | *ptr++ = PES_packet_length >> 8; |
| 789 | *ptr++ = PES_packet_length & 0xff; |
| 790 | *ptr++ = 0x84; |
Andreas Huber | b8c7bd4 | 2012-09-18 14:47:48 -0700 | [diff] [blame] | 791 | *ptr++ = (PES_private_data_len > 0) ? 0x81 : 0x80; |
| 792 | |
Andreas Huber | 90a9205 | 2012-10-30 15:53:03 -0700 | [diff] [blame] | 793 | size_t headerLength = 0x05 + numStuffingBytes; |
| 794 | if (PES_private_data_len > 0) { |
| 795 | headerLength += 1 + PES_private_data_len; |
| 796 | } |
| 797 | |
| 798 | *ptr++ = headerLength; |
Andreas Huber | b8c7bd4 | 2012-09-18 14:47:48 -0700 | [diff] [blame] | 799 | |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 800 | *ptr++ = 0x20 | (((PTS >> 30) & 7) << 1) | 1; |
| 801 | *ptr++ = (PTS >> 22) & 0xff; |
| 802 | *ptr++ = (((PTS >> 15) & 0x7f) << 1) | 1; |
| 803 | *ptr++ = (PTS >> 7) & 0xff; |
| 804 | *ptr++ = ((PTS & 0x7f) << 1) | 1; |
| 805 | |
Andreas Huber | b8c7bd4 | 2012-09-18 14:47:48 -0700 | [diff] [blame] | 806 | if (PES_private_data_len > 0) { |
| 807 | *ptr++ = 0x8e; // PES_private_data_flag, reserved. |
| 808 | memcpy(ptr, PES_private_data, PES_private_data_len); |
| 809 | ptr += PES_private_data_len; |
| 810 | } |
| 811 | |
Andreas Huber | 90a9205 | 2012-10-30 15:53:03 -0700 | [diff] [blame] | 812 | for (size_t i = 0; i < numStuffingBytes; ++i) { |
| 813 | *ptr++ = 0xff; |
| 814 | } |
| 815 | |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 816 | // 18 bytes of TS/PES header leave 188 - 18 = 170 bytes for the payload |
| 817 | |
| 818 | size_t sizeLeft = packetDataStart + 188 - ptr; |
| 819 | size_t copy = accessUnit->size(); |
| 820 | if (copy > sizeLeft) { |
| 821 | copy = sizeLeft; |
| 822 | } |
| 823 | |
| 824 | memcpy(ptr, accessUnit->data(), copy); |
| 825 | ptr += copy; |
| 826 | CHECK_EQ(sizeLeft, copy); |
| 827 | memset(ptr, 0xff, sizeLeft - copy); |
| 828 | |
| 829 | packetDataStart += 188; |
| 830 | |
| 831 | size_t offset = copy; |
| 832 | while (offset < accessUnit->size()) { |
| 833 | bool padding = (accessUnit->size() - offset) < (188 - 4); |
| 834 | |
| 835 | // for subsequent fragments of "buffer": |
| 836 | // 0x47 |
| 837 | // transport_error_indicator = b0 |
| 838 | // payload_unit_start_indicator = b0 |
| 839 | // transport_priority = b0 |
| 840 | // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex] |
| 841 | // transport_scrambling_control = b00 |
| 842 | // adaptation_field_control = b?? |
| 843 | // continuity_counter = b???? |
| 844 | // the fragment of "buffer" follows. |
| 845 | |
| 846 | uint8_t *ptr = packetDataStart; |
| 847 | *ptr++ = 0x47; |
| 848 | *ptr++ = 0x00 | (track->PID() >> 8); |
| 849 | *ptr++ = track->PID() & 0xff; |
| 850 | |
| 851 | *ptr++ = (padding ? 0x30 : 0x10) | track->incrementContinuityCounter(); |
| 852 | |
| 853 | if (padding) { |
| 854 | size_t paddingSize = 188 - 4 - (accessUnit->size() - offset); |
| 855 | *ptr++ = paddingSize - 1; |
| 856 | if (paddingSize >= 2) { |
| 857 | *ptr++ = 0x00; |
| 858 | memset(ptr, 0xff, paddingSize - 2); |
| 859 | ptr += paddingSize - 2; |
| 860 | } |
| 861 | } |
| 862 | |
| 863 | // 4 bytes of TS header leave 188 - 4 = 184 bytes for the payload |
| 864 | |
| 865 | size_t sizeLeft = packetDataStart + 188 - ptr; |
| 866 | size_t copy = accessUnit->size() - offset; |
| 867 | if (copy > sizeLeft) { |
| 868 | copy = sizeLeft; |
| 869 | } |
| 870 | |
| 871 | memcpy(ptr, accessUnit->data() + offset, copy); |
| 872 | ptr += copy; |
| 873 | CHECK_EQ(sizeLeft, copy); |
| 874 | memset(ptr, 0xff, sizeLeft - copy); |
| 875 | |
| 876 | offset += copy; |
| 877 | packetDataStart += 188; |
| 878 | } |
| 879 | |
| 880 | CHECK(packetDataStart == buffer->data() + buffer->capacity()); |
| 881 | |
| 882 | *packets = buffer; |
| 883 | |
| 884 | return OK; |
| 885 | } |
| 886 | |
| 887 | void TSPacketizer::initCrcTable() { |
| 888 | uint32_t poly = 0x04C11DB7; |
| 889 | |
| 890 | for (int i = 0; i < 256; i++) { |
| 891 | uint32_t crc = i << 24; |
| 892 | for (int j = 0; j < 8; j++) { |
| 893 | crc = (crc << 1) ^ ((crc & 0x80000000) ? (poly) : 0); |
| 894 | } |
| 895 | mCrcTable[i] = crc; |
| 896 | } |
| 897 | } |
| 898 | |
| 899 | uint32_t TSPacketizer::crc32(const uint8_t *start, size_t size) const { |
| 900 | uint32_t crc = 0xFFFFFFFF; |
| 901 | const uint8_t *p; |
| 902 | |
| 903 | for (p = start; p < start + size; ++p) { |
| 904 | crc = (crc << 8) ^ mCrcTable[((crc >> 24) ^ *p) & 0xFF]; |
| 905 | } |
| 906 | |
| 907 | return crc; |
| 908 | } |
| 909 | |
Andreas Huber | e399acc | 2012-09-27 08:53:23 -0700 | [diff] [blame] | 910 | sp<ABuffer> TSPacketizer::prependCSD( |
| 911 | size_t trackIndex, const sp<ABuffer> &accessUnit) const { |
| 912 | CHECK_LT(trackIndex, mTracks.size()); |
| 913 | |
| 914 | const sp<Track> &track = mTracks.itemAt(trackIndex); |
| 915 | CHECK(track->isH264() && IsIDR(accessUnit)); |
| 916 | |
| 917 | int64_t timeUs; |
| 918 | CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs)); |
| 919 | |
| 920 | sp<ABuffer> accessUnit2 = track->prependCSD(accessUnit); |
| 921 | |
| 922 | accessUnit2->meta()->setInt64("timeUs", timeUs); |
| 923 | |
| 924 | return accessUnit2; |
| 925 | } |
| 926 | |
Andreas Huber | d7bee3a | 2012-08-29 11:41:50 -0700 | [diff] [blame] | 927 | } // namespace android |
| 928 | |