MPEG4Writer.cpp revision 7837c17063a4c50bc856ba59418516fdab731de7
1/* 2 * Copyright (C) 2009 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 "MPEG4Writer" 19#include <utils/Log.h> 20 21#include <arpa/inet.h> 22 23#include <ctype.h> 24#include <pthread.h> 25 26#include <media/stagefright/MPEG4Writer.h> 27#include <media/stagefright/MediaBuffer.h> 28#include <media/stagefright/MetaData.h> 29#include <media/stagefright/MediaDebug.h> 30#include <media/stagefright/MediaDefs.h> 31#include <media/stagefright/MediaErrors.h> 32#include <media/stagefright/MediaSource.h> 33#include <media/stagefright/Utils.h> 34 35namespace android { 36 37class MPEG4Writer::Track { 38public: 39 Track(MPEG4Writer *owner, const sp<MediaSource> &source); 40 ~Track(); 41 42 status_t start(); 43 void stop(); 44 bool reachedEOS(); 45 46 int64_t getDurationUs() const; 47 void writeTrackHeader(int32_t trackID); 48 49private: 50 MPEG4Writer *mOwner; 51 sp<MetaData> mMeta; 52 sp<MediaSource> mSource; 53 volatile bool mDone; 54 int64_t mMaxTimeStampUs; 55 56 pthread_t mThread; 57 58 struct SampleInfo { 59 size_t size; 60 int64_t timestamp; 61 }; 62 List<SampleInfo> mSampleInfos; 63 bool mSamplesHaveSameSize; 64 65 List<MediaBuffer *> mChunkSamples; 66 List<off_t> mChunkOffsets; 67 68 struct StscTableEntry { 69 70 StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id) 71 : firstChunk(chunk), 72 samplesPerChunk(samples), 73 sampleDescriptionId(id) {} 74 75 uint32_t firstChunk; 76 uint32_t samplesPerChunk; 77 uint32_t sampleDescriptionId; 78 }; 79 List<StscTableEntry> mStscTableEntries; 80 81 List<int32_t> mStssTableEntries; 82 83 struct SttsTableEntry { 84 85 SttsTableEntry(uint32_t count, uint32_t duration) 86 : sampleCount(count), sampleDuration(duration) {} 87 88 uint32_t sampleCount; 89 uint32_t sampleDuration; 90 }; 91 List<SttsTableEntry> mSttsTableEntries; 92 93 void *mCodecSpecificData; 94 size_t mCodecSpecificDataSize; 95 bool mGotAllCodecSpecificData; 96 97 bool mReachedEOS; 98 99 static void *ThreadWrapper(void *me); 100 void threadEntry(); 101 102 status_t makeAVCCodecSpecificData( 103 const uint8_t *data, size_t size); 104 void writeOneChunk(bool isAvc); 105 106 Track(const Track &); 107 Track &operator=(const Track &); 108}; 109 110#define USE_NALLEN_FOUR 1 111 112MPEG4Writer::MPEG4Writer(const char *filename) 113 : mFile(fopen(filename, "wb")), 114 mOffset(0), 115 mMdatOffset(0), 116 mEstimatedMoovBoxSize(0), 117 mInterleaveDurationUs(500000) { 118 CHECK(mFile != NULL); 119} 120 121MPEG4Writer::MPEG4Writer(int fd) 122 : mFile(fdopen(fd, "wb")), 123 mOffset(0), 124 mMdatOffset(0), 125 mEstimatedMoovBoxSize(0), 126 mInterleaveDurationUs(500000) { 127 CHECK(mFile != NULL); 128} 129 130MPEG4Writer::~MPEG4Writer() { 131 stop(); 132 133 for (List<Track *>::iterator it = mTracks.begin(); 134 it != mTracks.end(); ++it) { 135 delete *it; 136 } 137 mTracks.clear(); 138} 139 140status_t MPEG4Writer::addSource(const sp<MediaSource> &source) { 141 Track *track = new Track(this, source); 142 mTracks.push_back(track); 143 144 return OK; 145} 146 147status_t MPEG4Writer::start() { 148 if (mFile == NULL) { 149 return UNKNOWN_ERROR; 150 } 151 152 mStreamableFile = true; 153 mWriteMoovBoxToMemory = false; 154 mMoovBoxBuffer = NULL; 155 mMoovBoxBufferOffset = 0; 156 157 beginBox("ftyp"); 158 writeFourcc("isom"); 159 writeInt32(0); 160 writeFourcc("isom"); 161 endBox(); 162 163 mFreeBoxOffset = mOffset; 164 165 if (mEstimatedMoovBoxSize == 0) { 166 // XXX: Estimate the moov box size 167 // based on max file size or duration limit 168 mEstimatedMoovBoxSize = 0x0F00; 169 } 170 CHECK(mEstimatedMoovBoxSize >= 8); 171 fseeko(mFile, mFreeBoxOffset, SEEK_SET); 172 writeInt32(mEstimatedMoovBoxSize); 173 write("free", 4); 174 175 mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize; 176 mOffset = mMdatOffset; 177 fseeko(mFile, mMdatOffset, SEEK_SET); 178 write("\x00\x00\x00\x01mdat????????", 16); 179 for (List<Track *>::iterator it = mTracks.begin(); 180 it != mTracks.end(); ++it) { 181 status_t err = (*it)->start(); 182 183 if (err != OK) { 184 for (List<Track *>::iterator it2 = mTracks.begin(); 185 it2 != it; ++it2) { 186 (*it2)->stop(); 187 } 188 189 return err; 190 } 191 } 192 193 return OK; 194} 195 196void MPEG4Writer::stop() { 197 if (mFile == NULL) { 198 return; 199 } 200 201 int64_t max_duration = 0; 202 for (List<Track *>::iterator it = mTracks.begin(); 203 it != mTracks.end(); ++it) { 204 (*it)->stop(); 205 206 int64_t duration = (*it)->getDurationUs(); 207 if (duration > max_duration) { 208 max_duration = duration; 209 } 210 } 211 212 213 // Fix up the size of the 'mdat' chunk. 214 fseeko(mFile, mMdatOffset + 8, SEEK_SET); 215 int64_t size = mOffset - mMdatOffset; 216 size = hton64(size); 217 fwrite(&size, 1, 8, mFile); 218 fseeko(mFile, mOffset, SEEK_SET); 219 220 time_t now = time(NULL); 221 const off_t moovOffset = mOffset; 222 mWriteMoovBoxToMemory = true; 223 mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize); 224 mMoovBoxBufferOffset = 0; 225 CHECK(mMoovBoxBuffer != NULL); 226 227 beginBox("moov"); 228 229 beginBox("mvhd"); 230 writeInt32(0); // version=0, flags=0 231 writeInt32(now); // creation time 232 writeInt32(now); // modification time 233 writeInt32(1000); // timescale 234 writeInt32(max_duration / 1000); 235 writeInt32(0x10000); // rate 236 writeInt16(0x100); // volume 237 writeInt16(0); // reserved 238 writeInt32(0); // reserved 239 writeInt32(0); // reserved 240 writeInt32(0x10000); // matrix 241 writeInt32(0); 242 writeInt32(0); 243 writeInt32(0); 244 writeInt32(0x10000); 245 writeInt32(0); 246 writeInt32(0); 247 writeInt32(0); 248 writeInt32(0x40000000); 249 writeInt32(0); // predefined 250 writeInt32(0); // predefined 251 writeInt32(0); // predefined 252 writeInt32(0); // predefined 253 writeInt32(0); // predefined 254 writeInt32(0); // predefined 255 writeInt32(mTracks.size() + 1); // nextTrackID 256 endBox(); // mvhd 257 258 int32_t id = 1; 259 for (List<Track *>::iterator it = mTracks.begin(); 260 it != mTracks.end(); ++it, ++id) { 261 (*it)->writeTrackHeader(id); 262 } 263 endBox(); // moov 264 265 mWriteMoovBoxToMemory = false; 266 if (mStreamableFile) { 267 CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize); 268 269 // Moov box 270 fseeko(mFile, mFreeBoxOffset, SEEK_SET); 271 mOffset = mFreeBoxOffset; 272 write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile); 273 274 // Free box 275 mFreeBoxOffset = mStreamableFile? mOffset: mFreeBoxOffset; 276 fseeko(mFile, mFreeBoxOffset, SEEK_SET); 277 writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset); 278 write("free", 4); 279 280 // Free temp memory 281 free(mMoovBoxBuffer); 282 mMoovBoxBuffer = NULL; 283 mMoovBoxBufferOffset = 0; 284 } 285 286 CHECK(mBoxes.empty()); 287 288 fflush(mFile); 289 fclose(mFile); 290 mFile = NULL; 291} 292 293status_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { 294 mInterleaveDurationUs = durationUs; 295 return OK; 296} 297 298void MPEG4Writer::lock() { 299 mLock.lock(); 300} 301 302void MPEG4Writer::unlock() { 303 mLock.unlock(); 304} 305 306off_t MPEG4Writer::addSample_l(MediaBuffer *buffer) { 307 off_t old_offset = mOffset; 308 309 fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 310 1, buffer->range_length(), mFile); 311 312 mOffset += buffer->range_length(); 313 314 return old_offset; 315} 316 317static void StripStartcode(MediaBuffer *buffer) { 318 if (buffer->range_length() < 4) { 319 return; 320 } 321 322 const uint8_t *ptr = 323 (const uint8_t *)buffer->data() + buffer->range_offset(); 324 325 if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 326 buffer->set_range( 327 buffer->range_offset() + 4, buffer->range_length() - 4); 328 } 329} 330 331off_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) { 332 StripStartcode(buffer); 333 334 off_t old_offset = mOffset; 335 336 size_t length = buffer->range_length(); 337 338#if USE_NALLEN_FOUR 339 uint8_t x = length >> 24; 340 fwrite(&x, 1, 1, mFile); 341 x = (length >> 16) & 0xff; 342 fwrite(&x, 1, 1, mFile); 343 x = (length >> 8) & 0xff; 344 fwrite(&x, 1, 1, mFile); 345 x = length & 0xff; 346 fwrite(&x, 1, 1, mFile); 347#else 348 CHECK(length < 65536); 349 350 uint8_t x = length >> 8; 351 fwrite(&x, 1, 1, mFile); 352 x = length & 0xff; 353 fwrite(&x, 1, 1, mFile); 354#endif 355 356 fwrite((const uint8_t *)buffer->data() + buffer->range_offset(), 357 1, length, mFile); 358 359#if USE_NALLEN_FOUR 360 mOffset += length + 4; 361#else 362 mOffset += length + 2; 363#endif 364 365 return old_offset; 366} 367 368size_t MPEG4Writer::write( 369 const void *ptr, size_t size, size_t nmemb, FILE *stream) { 370 371 const size_t bytes = size * nmemb; 372 if (mWriteMoovBoxToMemory) { 373 if (8 + mMoovBoxBufferOffset + bytes > mEstimatedMoovBoxSize) { 374 for (List<off_t>::iterator it = mBoxes.begin(); 375 it != mBoxes.end(); ++it) { 376 (*it) += mOffset; 377 } 378 fseeko(mFile, mOffset, SEEK_SET); 379 fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream); 380 fwrite(ptr, size, nmemb, stream); 381 mOffset += (bytes + mMoovBoxBufferOffset); 382 free(mMoovBoxBuffer); 383 mMoovBoxBuffer = NULL; 384 mMoovBoxBufferOffset = 0; 385 mWriteMoovBoxToMemory = false; 386 mStreamableFile = false; 387 } else { 388 memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes); 389 mMoovBoxBufferOffset += bytes; 390 } 391 } else { 392 fwrite(ptr, size, nmemb, stream); 393 mOffset += bytes; 394 } 395 return bytes; 396} 397 398void MPEG4Writer::beginBox(const char *fourcc) { 399 CHECK_EQ(strlen(fourcc), 4); 400 401 mBoxes.push_back(mWriteMoovBoxToMemory? 402 mMoovBoxBufferOffset: mOffset); 403 404 writeInt32(0); 405 writeFourcc(fourcc); 406} 407 408void MPEG4Writer::endBox() { 409 CHECK(!mBoxes.empty()); 410 411 off_t offset = *--mBoxes.end(); 412 mBoxes.erase(--mBoxes.end()); 413 414 if (mWriteMoovBoxToMemory) { 415 int32_t x = htonl(mMoovBoxBufferOffset - offset); 416 memcpy(mMoovBoxBuffer + offset, &x, 4); 417 } else { 418 fseeko(mFile, offset, SEEK_SET); 419 writeInt32(mOffset - offset); 420 mOffset -= 4; 421 fseeko(mFile, mOffset, SEEK_SET); 422 } 423} 424 425void MPEG4Writer::writeInt8(int8_t x) { 426 write(&x, 1, 1, mFile); 427} 428 429void MPEG4Writer::writeInt16(int16_t x) { 430 x = htons(x); 431 write(&x, 1, 2, mFile); 432} 433 434void MPEG4Writer::writeInt32(int32_t x) { 435 x = htonl(x); 436 write(&x, 1, 4, mFile); 437} 438 439void MPEG4Writer::writeInt64(int64_t x) { 440 x = hton64(x); 441 write(&x, 1, 8, mFile); 442} 443 444void MPEG4Writer::writeCString(const char *s) { 445 size_t n = strlen(s); 446 write(s, 1, n + 1, mFile); 447} 448 449void MPEG4Writer::writeFourcc(const char *s) { 450 CHECK_EQ(strlen(s), 4); 451 write(s, 1, 4, mFile); 452} 453 454void MPEG4Writer::write(const void *data, size_t size) { 455 write(data, 1, size, mFile); 456} 457 458bool MPEG4Writer::reachedEOS() { 459 bool allDone = true; 460 for (List<Track *>::iterator it = mTracks.begin(); 461 it != mTracks.end(); ++it) { 462 if (!(*it)->reachedEOS()) { 463 allDone = false; 464 break; 465 } 466 } 467 468 return allDone; 469} 470 471//////////////////////////////////////////////////////////////////////////////// 472 473MPEG4Writer::Track::Track( 474 MPEG4Writer *owner, const sp<MediaSource> &source) 475 : mOwner(owner), 476 mMeta(source->getFormat()), 477 mSource(source), 478 mDone(false), 479 mMaxTimeStampUs(0), 480 mSamplesHaveSameSize(true), 481 mCodecSpecificData(NULL), 482 mCodecSpecificDataSize(0), 483 mGotAllCodecSpecificData(false), 484 mReachedEOS(false) { 485} 486 487MPEG4Writer::Track::~Track() { 488 stop(); 489 490 if (mCodecSpecificData != NULL) { 491 free(mCodecSpecificData); 492 mCodecSpecificData = NULL; 493 } 494} 495 496status_t MPEG4Writer::Track::start() { 497 status_t err = mSource->start(); 498 499 if (err != OK) { 500 mDone = mReachedEOS = true; 501 return err; 502 } 503 504 pthread_attr_t attr; 505 pthread_attr_init(&attr); 506 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 507 508 mDone = false; 509 mMaxTimeStampUs = 0; 510 mReachedEOS = false; 511 512 pthread_create(&mThread, &attr, ThreadWrapper, this); 513 pthread_attr_destroy(&attr); 514 515 return OK; 516} 517 518void MPEG4Writer::Track::stop() { 519 if (mDone) { 520 return; 521 } 522 523 mDone = true; 524 525 void *dummy; 526 pthread_join(mThread, &dummy); 527 528 mSource->stop(); 529} 530 531bool MPEG4Writer::Track::reachedEOS() { 532 return mReachedEOS; 533} 534 535// static 536void *MPEG4Writer::Track::ThreadWrapper(void *me) { 537 Track *track = static_cast<Track *>(me); 538 539 track->threadEntry(); 540 541 return NULL; 542} 543 544#include <ctype.h> 545static void hexdump(const void *_data, size_t size) { 546 const uint8_t *data = (const uint8_t *)_data; 547 size_t offset = 0; 548 while (offset < size) { 549 printf("0x%04x ", offset); 550 551 size_t n = size - offset; 552 if (n > 16) { 553 n = 16; 554 } 555 556 for (size_t i = 0; i < 16; ++i) { 557 if (i == 8) { 558 printf(" "); 559 } 560 561 if (offset + i < size) { 562 printf("%02x ", data[offset + i]); 563 } else { 564 printf(" "); 565 } 566 } 567 568 printf(" "); 569 570 for (size_t i = 0; i < n; ++i) { 571 if (isprint(data[offset + i])) { 572 printf("%c", data[offset + i]); 573 } else { 574 printf("."); 575 } 576 } 577 578 printf("\n"); 579 580 offset += 16; 581 } 582} 583 584 585status_t MPEG4Writer::Track::makeAVCCodecSpecificData( 586 const uint8_t *data, size_t size) { 587 // hexdump(data, size); 588 589 if (mCodecSpecificData != NULL) { 590 LOGE("Already have codec specific data"); 591 return ERROR_MALFORMED; 592 } 593 594 if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) { 595 LOGE("Must start with a start code"); 596 return ERROR_MALFORMED; 597 } 598 599 size_t picParamOffset = 4; 600 while (picParamOffset + 3 < size 601 && memcmp("\x00\x00\x00\x01", &data[picParamOffset], 4)) { 602 ++picParamOffset; 603 } 604 605 if (picParamOffset + 3 >= size) { 606 LOGE("Could not find start-code for pictureParameterSet"); 607 return ERROR_MALFORMED; 608 } 609 610 size_t seqParamSetLength = picParamOffset - 4; 611 size_t picParamSetLength = size - picParamOffset - 4; 612 613 mCodecSpecificDataSize = 614 6 + 1 + seqParamSetLength + 2 + picParamSetLength + 2; 615 616 mCodecSpecificData = malloc(mCodecSpecificDataSize); 617 uint8_t *header = (uint8_t *)mCodecSpecificData; 618 header[0] = 1; 619 header[1] = 0x42; // profile 620 header[2] = 0x80; 621 header[3] = 0x1e; // level 622 623#if USE_NALLEN_FOUR 624 header[4] = 0xfc | 3; // length size == 4 bytes 625#else 626 header[4] = 0xfc | 1; // length size == 2 bytes 627#endif 628 629 header[5] = 0xe0 | 1; 630 header[6] = seqParamSetLength >> 8; 631 header[7] = seqParamSetLength & 0xff; 632 memcpy(&header[8], &data[4], seqParamSetLength); 633 header += 8 + seqParamSetLength; 634 header[0] = 1; 635 header[1] = picParamSetLength >> 8; 636 header[2] = picParamSetLength & 0xff; 637 memcpy(&header[3], &data[picParamOffset + 4], picParamSetLength); 638 639 return OK; 640} 641 642void MPEG4Writer::Track::threadEntry() { 643 sp<MetaData> meta = mSource->getFormat(); 644 const char *mime; 645 meta->findCString(kKeyMIMEType, &mime); 646 bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || 647 !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); 648 bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 649 int32_t count = 0; 650 const int64_t interleaveDurationUs = mOwner->interleaveDuration(); 651 int64_t chunkTimestampUs = 0; 652 int32_t nChunks = 0; 653 int32_t nZeroLengthFrames = 0; 654 int64_t lastTimestamp = 0; // Timestamp of the previous sample 655 int64_t lastDuration = 0; // Time spacing between the previous two samples 656 int32_t sampleCount = 1; // Sample count in the current stts table entry 657 uint32_t previousSampleSize = 0; // Size of the previous sample 658 659 MediaBuffer *buffer; 660 while (!mDone && mSource->read(&buffer) == OK) { 661 if (buffer->range_length() == 0) { 662 buffer->release(); 663 buffer = NULL; 664 ++nZeroLengthFrames; 665 continue; 666 } 667 668 ++count; 669 670 int32_t isCodecConfig; 671 if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig) 672 && isCodecConfig) { 673 CHECK(!mGotAllCodecSpecificData); 674 675 if (is_avc) { 676 status_t err = makeAVCCodecSpecificData( 677 (const uint8_t *)buffer->data() 678 + buffer->range_offset(), 679 buffer->range_length()); 680 CHECK_EQ(OK, err); 681 } else if (is_mpeg4) { 682 mCodecSpecificDataSize = buffer->range_length(); 683 mCodecSpecificData = malloc(mCodecSpecificDataSize); 684 memcpy(mCodecSpecificData, 685 (const uint8_t *)buffer->data() 686 + buffer->range_offset(), 687 buffer->range_length()); 688 } 689 690 buffer->release(); 691 buffer = NULL; 692 693 mGotAllCodecSpecificData = true; 694 continue; 695 } else if (!mGotAllCodecSpecificData && 696 count == 1 && is_mpeg4 && mCodecSpecificData == NULL) { 697 // The TI mpeg4 encoder does not properly set the 698 // codec-specific-data flag. 699 700 const uint8_t *data = 701 (const uint8_t *)buffer->data() + buffer->range_offset(); 702 703 const size_t size = buffer->range_length(); 704 705 size_t offset = 0; 706 while (offset + 3 < size) { 707 if (data[offset] == 0x00 && data[offset + 1] == 0x00 708 && data[offset + 2] == 0x01 && data[offset + 3] == 0xb6) { 709 break; 710 } 711 712 ++offset; 713 } 714 715 // CHECK(offset + 3 < size); 716 if (offset + 3 >= size) { 717 // XXX assume the entire first chunk of data is the codec specific 718 // data. 719 offset = size; 720 } 721 722 mCodecSpecificDataSize = offset; 723 mCodecSpecificData = malloc(offset); 724 memcpy(mCodecSpecificData, data, offset); 725 726 buffer->set_range(buffer->range_offset() + offset, size - offset); 727 728 if (size == offset) { 729 buffer->release(); 730 buffer = NULL; 731 732 continue; 733 } 734 735 mGotAllCodecSpecificData = true; 736 } else if (!mGotAllCodecSpecificData && is_avc && count < 3) { 737 // The TI video encoder does not flag codec specific data 738 // as such and also splits up SPS and PPS across two buffers. 739 740 const uint8_t *data = 741 (const uint8_t *)buffer->data() + buffer->range_offset(); 742 743 size_t size = buffer->range_length(); 744 745 CHECK(count == 2 || mCodecSpecificData == NULL); 746 747 size_t offset = mCodecSpecificDataSize; 748 mCodecSpecificDataSize += size + 4; 749 mCodecSpecificData = 750 realloc(mCodecSpecificData, mCodecSpecificDataSize); 751 752 memcpy((uint8_t *)mCodecSpecificData + offset, 753 "\x00\x00\x00\x01", 4); 754 755 memcpy((uint8_t *)mCodecSpecificData + offset + 4, data, size); 756 757 buffer->release(); 758 buffer = NULL; 759 760 if (count == 2) { 761 void *tmp = mCodecSpecificData; 762 size = mCodecSpecificDataSize; 763 mCodecSpecificData = NULL; 764 mCodecSpecificDataSize = 0; 765 766 status_t err = makeAVCCodecSpecificData( 767 (const uint8_t *)tmp, size); 768 free(tmp); 769 tmp = NULL; 770 CHECK_EQ(OK, err); 771 772 mGotAllCodecSpecificData = true; 773 } 774 775 continue; 776 } 777 778 SampleInfo info; 779 info.size = is_avc 780#if USE_NALLEN_FOUR 781 ? buffer->range_length() + 4 782#else 783 ? buffer->range_length() + 2 784#endif 785 : buffer->range_length(); 786 787 bool is_audio = !strncasecmp(mime, "audio/", 6); 788 789 int64_t timestampUs; 790 CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs)); 791 792 if (timestampUs > mMaxTimeStampUs) { 793 mMaxTimeStampUs = timestampUs; 794 } 795 796 // Our timestamp is in ms. 797 info.timestamp = (timestampUs + 500) / 1000; 798 mSampleInfos.push_back(info); 799 if (mSampleInfos.size() > 2) { 800 if (lastDuration != info.timestamp - lastTimestamp) { 801 SttsTableEntry sttsEntry(sampleCount, lastDuration); 802 mSttsTableEntries.push_back(sttsEntry); 803 sampleCount = 1; 804 } else { 805 ++sampleCount; 806 } 807 } 808 if (mSamplesHaveSameSize) { 809 if (mSampleInfos.size() >= 2 && previousSampleSize != info.size) { 810 mSamplesHaveSameSize = false; 811 } 812 previousSampleSize = info.size; 813 } 814 lastDuration = info.timestamp - lastTimestamp; 815 lastTimestamp = info.timestamp; 816 817//////////////////////////////////////////////////////////////////////////////// 818 // Make a deep copy of the MediaBuffer less Metadata 819 MediaBuffer *copy = new MediaBuffer(buffer->range_length()); 820 memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(), 821 buffer->range_length()); 822 copy->set_range(0, buffer->range_length()); 823 824 mChunkSamples.push_back(copy); 825 if (interleaveDurationUs == 0) { 826 StscTableEntry stscEntry(++nChunks, 1, 1); 827 mStscTableEntries.push_back(stscEntry); 828 writeOneChunk(is_avc); 829 } else { 830 if (chunkTimestampUs == 0) { 831 chunkTimestampUs = timestampUs; 832 } else { 833 if (timestampUs - chunkTimestampUs > interleaveDurationUs) { 834 ++nChunks; 835 if (nChunks == 1 || // First chunk 836 (--(mStscTableEntries.end()))->samplesPerChunk != 837 mChunkSamples.size()) { 838 StscTableEntry stscEntry(nChunks, 839 mChunkSamples.size(), 1); 840 mStscTableEntries.push_back(stscEntry); 841 } 842 writeOneChunk(is_avc); 843 chunkTimestampUs = timestampUs; 844 } 845 } 846 } 847 848 int32_t isSync = false; 849 if (buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync) && 850 isSync != 0) { 851 mStssTableEntries.push_back(mSampleInfos.size()); 852 } 853 854 buffer->release(); 855 buffer = NULL; 856 } 857 858 CHECK(!mSampleInfos.empty()); 859 860 // Last chunk 861 if (!mChunkSamples.empty()) { 862 ++nChunks; 863 StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1); 864 mStscTableEntries.push_back(stscEntry); 865 writeOneChunk(is_avc); 866 } 867 868 // We don't really know how long the last frame lasts, since 869 // there is no frame time after it, just repeat the previous 870 // frame's duration. 871 if (mSampleInfos.size() == 1) { 872 lastDuration = 0; // A single sample's duration 873 } else { 874 ++sampleCount; // Count for the last sample 875 } 876 SttsTableEntry sttsEntry(sampleCount, lastDuration); 877 mSttsTableEntries.push_back(sttsEntry); 878 mReachedEOS = true; 879 LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames", 880 count, nZeroLengthFrames, mSampleInfos.size()); 881} 882 883void MPEG4Writer::Track::writeOneChunk(bool isAvc) { 884 mOwner->lock(); 885 for (List<MediaBuffer *>::iterator it = mChunkSamples.begin(); 886 it != mChunkSamples.end(); ++it) { 887 off_t offset = isAvc? mOwner->addLengthPrefixedSample_l(*it) 888 : mOwner->addSample_l(*it); 889 if (it == mChunkSamples.begin()) { 890 mChunkOffsets.push_back(offset); 891 } 892 } 893 mOwner->unlock(); 894 while (!mChunkSamples.empty()) { 895 List<MediaBuffer *>::iterator it = mChunkSamples.begin(); 896 (*it)->release(); 897 (*it) = NULL; 898 mChunkSamples.erase(it); 899 } 900 mChunkSamples.clear(); 901} 902 903int64_t MPEG4Writer::Track::getDurationUs() const { 904 return mMaxTimeStampUs; 905} 906 907void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { 908 const char *mime; 909 bool success = mMeta->findCString(kKeyMIMEType, &mime); 910 CHECK(success); 911 912 bool is_audio = !strncasecmp(mime, "audio/", 6); 913 914 time_t now = time(NULL); 915 916 mOwner->beginBox("trak"); 917 918 mOwner->beginBox("tkhd"); 919 mOwner->writeInt32(0); // version=0, flags=0 920 mOwner->writeInt32(now); // creation time 921 mOwner->writeInt32(now); // modification time 922 mOwner->writeInt32(trackID); 923 mOwner->writeInt32(0); // reserved 924 mOwner->writeInt32(getDurationUs() / 1000); 925 mOwner->writeInt32(0); // reserved 926 mOwner->writeInt32(0); // reserved 927 mOwner->writeInt16(0); // layer 928 mOwner->writeInt16(0); // alternate group 929 mOwner->writeInt16(is_audio ? 0x100 : 0); // volume 930 mOwner->writeInt16(0); // reserved 931 932 mOwner->writeInt32(0x10000); // matrix 933 mOwner->writeInt32(0); 934 mOwner->writeInt32(0); 935 mOwner->writeInt32(0); 936 mOwner->writeInt32(0x10000); 937 mOwner->writeInt32(0); 938 mOwner->writeInt32(0); 939 mOwner->writeInt32(0); 940 mOwner->writeInt32(0x40000000); 941 942 if (is_audio) { 943 mOwner->writeInt32(0); 944 mOwner->writeInt32(0); 945 } else { 946 int32_t width, height; 947 bool success = mMeta->findInt32(kKeyWidth, &width); 948 success = success && mMeta->findInt32(kKeyHeight, &height); 949 CHECK(success); 950 951 mOwner->writeInt32(width << 16); // 32-bit fixed-point value 952 mOwner->writeInt32(height << 16); // 32-bit fixed-point value 953 } 954 mOwner->endBox(); // tkhd 955 956 mOwner->beginBox("mdia"); 957 958 mOwner->beginBox("mdhd"); 959 mOwner->writeInt32(0); // version=0, flags=0 960 mOwner->writeInt32(now); // creation time 961 mOwner->writeInt32(now); // modification time 962 mOwner->writeInt32(1000); // timescale 963 mOwner->writeInt32(getDurationUs() / 1000); 964 mOwner->writeInt16(0); // language code XXX 965 mOwner->writeInt16(0); // predefined 966 mOwner->endBox(); 967 968 mOwner->beginBox("hdlr"); 969 mOwner->writeInt32(0); // version=0, flags=0 970 mOwner->writeInt32(0); // component type: should be mhlr 971 mOwner->writeFourcc(is_audio ? "soun" : "vide"); // component subtype 972 mOwner->writeInt32(0); // reserved 973 mOwner->writeInt32(0); // reserved 974 mOwner->writeInt32(0); // reserved 975 mOwner->writeCString("SoundHandler"); // name 976 mOwner->endBox(); 977 978 mOwner->beginBox("minf"); 979 if (is_audio) { 980 mOwner->beginBox("smhd"); 981 mOwner->writeInt32(0); // version=0, flags=0 982 mOwner->writeInt16(0); // balance 983 mOwner->writeInt16(0); // reserved 984 mOwner->endBox(); 985 } else { 986 mOwner->beginBox("vmhd"); 987 mOwner->writeInt32(0x00000001); // version=0, flags=1 988 mOwner->writeInt16(0); // graphics mode 989 mOwner->writeInt16(0); // opcolor 990 mOwner->writeInt16(0); 991 mOwner->writeInt16(0); 992 mOwner->endBox(); 993 } 994 995 mOwner->beginBox("dinf"); 996 mOwner->beginBox("dref"); 997 mOwner->writeInt32(0); // version=0, flags=0 998 mOwner->writeInt32(1); 999 mOwner->beginBox("url "); 1000 mOwner->writeInt32(1); // version=0, flags=1 1001 mOwner->endBox(); // url 1002 mOwner->endBox(); // dref 1003 mOwner->endBox(); // dinf 1004 1005 mOwner->endBox(); // minf 1006 1007 mOwner->beginBox("stbl"); 1008 1009 mOwner->beginBox("stsd"); 1010 mOwner->writeInt32(0); // version=0, flags=0 1011 mOwner->writeInt32(1); // entry count 1012 if (is_audio) { 1013 const char *fourcc = NULL; 1014 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) { 1015 fourcc = "samr"; 1016 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { 1017 fourcc = "sawb"; 1018 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 1019 fourcc = "mp4a"; 1020 } else { 1021 LOGE("Unknown mime type '%s'.", mime); 1022 CHECK(!"should not be here, unknown mime type."); 1023 } 1024 1025 mOwner->beginBox(fourcc); // audio format 1026 mOwner->writeInt32(0); // reserved 1027 mOwner->writeInt16(0); // reserved 1028 mOwner->writeInt16(0x1); // data ref index 1029 mOwner->writeInt32(0); // reserved 1030 mOwner->writeInt32(0); // reserved 1031 int32_t nChannels; 1032 CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); 1033 mOwner->writeInt16(nChannels); // channel count 1034 mOwner->writeInt16(16); // sample size 1035 mOwner->writeInt16(0); // predefined 1036 mOwner->writeInt16(0); // reserved 1037 1038 int32_t samplerate; 1039 bool success = mMeta->findInt32(kKeySampleRate, &samplerate); 1040 CHECK(success); 1041 1042 mOwner->writeInt32(samplerate << 16); 1043 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { 1044 mOwner->beginBox("esds"); 1045 1046 mOwner->writeInt32(0); // version=0, flags=0 1047 mOwner->writeInt8(0x03); // ES_DescrTag 1048 mOwner->writeInt8(23 + mCodecSpecificDataSize); 1049 mOwner->writeInt16(0x0000);// ES_ID 1050 mOwner->writeInt8(0x00); 1051 1052 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 1053 mOwner->writeInt8(15 + mCodecSpecificDataSize); 1054 mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 1055 mOwner->writeInt8(0x15); // streamType AudioStream 1056 1057 mOwner->writeInt16(0x03); // XXX 1058 mOwner->writeInt8(0x00); // buffer size 24-bit 1059 mOwner->writeInt32(96000); // max bit rate 1060 mOwner->writeInt32(96000); // avg bit rate 1061 1062 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 1063 mOwner->writeInt8(mCodecSpecificDataSize); 1064 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 1065 1066 static const uint8_t kData2[] = { 1067 0x06, // SLConfigDescriptorTag 1068 0x01, 1069 0x02 1070 }; 1071 mOwner->write(kData2, sizeof(kData2)); 1072 1073 mOwner->endBox(); // esds 1074 } 1075 mOwner->endBox(); 1076 } else { 1077 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 1078 mOwner->beginBox("mp4v"); 1079 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 1080 mOwner->beginBox("s263"); 1081 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 1082 mOwner->beginBox("avc1"); 1083 } else { 1084 LOGE("Unknown mime type '%s'.", mime); 1085 CHECK(!"should not be here, unknown mime type."); 1086 } 1087 1088 mOwner->writeInt32(0); // reserved 1089 mOwner->writeInt16(0); // reserved 1090 mOwner->writeInt16(0); // data ref index 1091 mOwner->writeInt16(0); // predefined 1092 mOwner->writeInt16(0); // reserved 1093 mOwner->writeInt32(0); // predefined 1094 mOwner->writeInt32(0); // predefined 1095 mOwner->writeInt32(0); // predefined 1096 1097 int32_t width, height; 1098 bool success = mMeta->findInt32(kKeyWidth, &width); 1099 success = success && mMeta->findInt32(kKeyHeight, &height); 1100 CHECK(success); 1101 1102 mOwner->writeInt16(width); 1103 mOwner->writeInt16(height); 1104 mOwner->writeInt32(0x480000); // horiz resolution 1105 mOwner->writeInt32(0x480000); // vert resolution 1106 mOwner->writeInt32(0); // reserved 1107 mOwner->writeInt16(1); // frame count 1108 mOwner->write(" ", 32); 1109 mOwner->writeInt16(0x18); // depth 1110 mOwner->writeInt16(-1); // predefined 1111 1112 CHECK(23 + mCodecSpecificDataSize < 128); 1113 1114 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 1115 mOwner->beginBox("esds"); 1116 1117 mOwner->writeInt32(0); // version=0, flags=0 1118 1119 mOwner->writeInt8(0x03); // ES_DescrTag 1120 mOwner->writeInt8(23 + mCodecSpecificDataSize); 1121 mOwner->writeInt16(0x0000); // ES_ID 1122 mOwner->writeInt8(0x1f); 1123 1124 mOwner->writeInt8(0x04); // DecoderConfigDescrTag 1125 mOwner->writeInt8(15 + mCodecSpecificDataSize); 1126 mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2 1127 mOwner->writeInt8(0x11); // streamType VisualStream 1128 1129 static const uint8_t kData[] = { 1130 0x01, 0x77, 0x00, 1131 0x00, 0x03, 0xe8, 0x00, 1132 0x00, 0x03, 0xe8, 0x00 1133 }; 1134 mOwner->write(kData, sizeof(kData)); 1135 1136 mOwner->writeInt8(0x05); // DecoderSpecificInfoTag 1137 1138 mOwner->writeInt8(mCodecSpecificDataSize); 1139 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 1140 1141 static const uint8_t kData2[] = { 1142 0x06, // SLConfigDescriptorTag 1143 0x01, 1144 0x02 1145 }; 1146 mOwner->write(kData2, sizeof(kData2)); 1147 1148 mOwner->endBox(); // esds 1149 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 1150 mOwner->beginBox("d263"); 1151 1152 mOwner->writeInt32(0); // vendor 1153 mOwner->writeInt8(0); // decoder version 1154 mOwner->writeInt8(10); // level: 10 1155 mOwner->writeInt8(0); // profile: 0 1156 1157 mOwner->endBox(); // d263 1158 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 1159 mOwner->beginBox("avcC"); 1160 mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); 1161 mOwner->endBox(); // avcC 1162 } 1163 1164 mOwner->endBox(); // mp4v, s263 or avc1 1165 } 1166 mOwner->endBox(); // stsd 1167 1168 mOwner->beginBox("stts"); 1169 mOwner->writeInt32(0); // version=0, flags=0 1170 mOwner->writeInt32(mSttsTableEntries.size()); 1171 for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin(); 1172 it != mSttsTableEntries.end(); ++it) { 1173 mOwner->writeInt32(it->sampleCount); 1174 mOwner->writeInt32(it->sampleDuration); 1175 } 1176 mOwner->endBox(); // stts 1177 1178 if (!is_audio) { 1179 mOwner->beginBox("stss"); 1180 mOwner->writeInt32(0); // version=0, flags=0 1181 mOwner->writeInt32(mStssTableEntries.size()); // number of sync frames 1182 for (List<int32_t>::iterator it = mStssTableEntries.begin(); 1183 it != mStssTableEntries.end(); ++it) { 1184 mOwner->writeInt32(*it); 1185 } 1186 mOwner->endBox(); // stss 1187 } 1188 1189 mOwner->beginBox("stsz"); 1190 mOwner->writeInt32(0); // version=0, flags=0 1191 if (mSamplesHaveSameSize) { 1192 List<SampleInfo>::iterator it = mSampleInfos.begin(); 1193 mOwner->writeInt32(it->size); // default sample size 1194 } else { 1195 mOwner->writeInt32(0); 1196 } 1197 mOwner->writeInt32(mSampleInfos.size()); 1198 if (!mSamplesHaveSameSize) { 1199 for (List<SampleInfo>::iterator it = mSampleInfos.begin(); 1200 it != mSampleInfos.end(); ++it) { 1201 mOwner->writeInt32((*it).size); 1202 } 1203 } 1204 mOwner->endBox(); // stsz 1205 1206 mOwner->beginBox("stsc"); 1207 mOwner->writeInt32(0); // version=0, flags=0 1208 mOwner->writeInt32(mStscTableEntries.size()); 1209 for (List<StscTableEntry>::iterator it = mStscTableEntries.begin(); 1210 it != mStscTableEntries.end(); ++it) { 1211 mOwner->writeInt32(it->firstChunk); 1212 mOwner->writeInt32(it->samplesPerChunk); 1213 mOwner->writeInt32(it->sampleDescriptionId); 1214 } 1215 mOwner->endBox(); // stsc 1216 1217 mOwner->beginBox("co64"); 1218 mOwner->writeInt32(0); // version=0, flags=0 1219 mOwner->writeInt32(mChunkOffsets.size()); 1220 for (List<off_t>::iterator it = mChunkOffsets.begin(); 1221 it != mChunkOffsets.end(); ++it) { 1222 mOwner->writeInt64((*it)); 1223 } 1224 mOwner->endBox(); // co64 1225 1226 mOwner->endBox(); // stbl 1227 mOwner->endBox(); // mdia 1228 mOwner->endBox(); // trak 1229} 1230 1231} // namespace android 1232