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