Loading media/libstagefright/MPEG4Writer.cpp +93 −34 Original line number Diff line number Diff line Loading @@ -1959,6 +1959,17 @@ void MPEG4Writer::Track::addItemOffsetAndSize(off64_t offset, size_t size) { return; } // Rotation angle in HEIF is CCW, framework angle is CW. int32_t heifRotation = 0; switch(mRotation) { case 90: heifRotation = 3; break; case 180: heifRotation = 2; break; case 270: heifRotation = 1; break; default: break; // don't set if invalid } bool hasGrid = (mNumTiles > 1); if (mProperties.empty()) { mProperties.push_back(mOwner->addProperty_l({ .type = FOURCC('h', 'v', 'c', 'C'), Loading @@ -1967,22 +1978,29 @@ void MPEG4Writer::Track::addItemOffsetAndSize(off64_t offset, size_t size) { mProperties.push_back(mOwner->addProperty_l({ .type = FOURCC('i', 's', 'p', 'e'), .width = (mNumTiles > 1) ? mGridWidth : mWidth, .height = (mNumTiles > 1) ? mGridHeight : mHeight, .width = hasGrid ? mGridWidth : mWidth, .height = hasGrid ? mGridHeight : mHeight, })); if (!hasGrid && heifRotation > 0) { mProperties.push_back(mOwner->addProperty_l({ .type = FOURCC('i', 'r', 'o', 't'), .rotation = heifRotation, })); } } uint16_t itemId = mOwner->addItem_l({ .itemType = "hvc1", .isPrimary = (mNumTiles > 1) ? false : (mIsPrimary != 0), .isHidden = (mNumTiles > 1), .isPrimary = hasGrid ? false : (mIsPrimary != 0), .isHidden = hasGrid, .offset = (uint32_t)offset, .size = (uint32_t)size, .properties = mProperties, }); mTileIndex++; if (mNumTiles > 1) { if (hasGrid) { mDimgRefs.push_back(itemId); if (mTileIndex == mNumTiles) { Loading @@ -1992,6 +2010,12 @@ void MPEG4Writer::Track::addItemOffsetAndSize(off64_t offset, size_t size) { .width = mWidth, .height = mHeight, })); if (heifRotation > 0) { mProperties.push_back(mOwner->addProperty_l({ .type = FOURCC('i', 'r', 'o', 't'), .rotation = heifRotation, })); } mOwner->addItem_l({ .itemType = "grid", .isPrimary = (mIsPrimary != 0), Loading Loading @@ -2302,7 +2326,8 @@ status_t MPEG4Writer::Track::start(MetaData *params) { mStartTimeRealUs = startTimeUs; int32_t rotationDegrees; if (mIsVideo && params && params->findInt32(kKeyRotation, &rotationDegrees)) { if ((mIsVideo || mIsHeic) && params && params->findInt32(kKeyRotation, &rotationDegrees)) { mRotation = rotationDegrees; } Loading Loading @@ -3427,16 +3452,36 @@ int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { int32_t MPEG4Writer::Track::getMetaSizeIncrease() const { CHECK(mIsHeic); return 20 // 1. 'ispe' property + (8 + mCodecSpecificDataSize) // 2. 'hvcC' property + (20 // 3. extra 'ispe' + (8 + 2 + 2 + mNumTiles * 2) // 4. 'dimg' ref + 12) // 5. ImageGrid in 'idat' (worst case) * (mNumTiles > 1) // - (3~5: applicable only if grid) + (16 // 6. increase to 'iloc' + 21 // 7. increase to 'iinf' + (3 + 2 * 2)) // 8. increase to 'ipma' (worst case) * (mNumTiles + 1); // - (6~8: are per-item) int32_t grid = (mNumTiles > 1); // Note that the rotation angle is in the file meta, and we don't have // it until start, so here the calculation has to assume rotation. // increase to ipco int32_t increase = 20 * (grid + 1) // 'ispe' property + (8 + mCodecSpecificDataSize) // 'hvcC' property + 9; // 'irot' property (worst case) // increase to iref and idat if (grid) { increase += (8 + 2 + 2 + mNumTiles * 2) // 'dimg' in iref + 12; // ImageGrid in 'idat' (worst case) } // increase to iloc, iinf and ipma increase += (16 // increase to 'iloc' + 21 // increase to 'iinf' + (3 + 2 * 2)) // increase to 'ipma' (worst case, 2 props x 2 bytes) * (mNumTiles + grid); // adjust to ipma: // if rotation is present and only one tile, it could ref 3 properties if (!grid) { increase += 2; } return increase; } status_t MPEG4Writer::Track::checkCodecSpecificData() const { Loading Loading @@ -4264,7 +4309,9 @@ void MPEG4Writer::writeIpcoBox() { numProperties = 32767; } for (size_t propIndex = 0; propIndex < numProperties; propIndex++) { if (mProperties[propIndex].type == FOURCC('h', 'v', 'c', 'C')) { switch (mProperties[propIndex].type) { case FOURCC('h', 'v', 'c', 'C'): { beginBox("hvcC"); sp<ABuffer> hvcc = mProperties[propIndex].hvcc; // Patch avcc's lengthSize field to match the number Loading @@ -4273,13 +4320,25 @@ void MPEG4Writer::writeIpcoBox() { ptr[21] = (ptr[21] & 0xfc) | (useNalLengthFour() ? 3 : 1); write(hvcc->data(), hvcc->size()); endBox(); } else if (mProperties[propIndex].type == FOURCC('i', 's', 'p', 'e')) { break; } case FOURCC('i', 's', 'p', 'e'): { beginBox("ispe"); writeInt32(0); // Version = 0, Flags = 0 writeInt32(mProperties[propIndex].width); writeInt32(mProperties[propIndex].height); endBox(); } else { break; } case FOURCC('i', 'r', 'o', 't'): { beginBox("irot"); writeInt8(mProperties[propIndex].rotation); endBox(); break; } default: ALOGW("Skipping unrecognized property: type 0x%08x", mProperties[propIndex].type); } Loading media/libstagefright/include/media/stagefright/MPEG4Writer.h +1 −0 Original line number Diff line number Diff line Loading @@ -195,6 +195,7 @@ private: uint32_t type; int32_t width; int32_t height; int32_t rotation; sp<ABuffer> hvcc; } ItemProperty; Loading Loading
media/libstagefright/MPEG4Writer.cpp +93 −34 Original line number Diff line number Diff line Loading @@ -1959,6 +1959,17 @@ void MPEG4Writer::Track::addItemOffsetAndSize(off64_t offset, size_t size) { return; } // Rotation angle in HEIF is CCW, framework angle is CW. int32_t heifRotation = 0; switch(mRotation) { case 90: heifRotation = 3; break; case 180: heifRotation = 2; break; case 270: heifRotation = 1; break; default: break; // don't set if invalid } bool hasGrid = (mNumTiles > 1); if (mProperties.empty()) { mProperties.push_back(mOwner->addProperty_l({ .type = FOURCC('h', 'v', 'c', 'C'), Loading @@ -1967,22 +1978,29 @@ void MPEG4Writer::Track::addItemOffsetAndSize(off64_t offset, size_t size) { mProperties.push_back(mOwner->addProperty_l({ .type = FOURCC('i', 's', 'p', 'e'), .width = (mNumTiles > 1) ? mGridWidth : mWidth, .height = (mNumTiles > 1) ? mGridHeight : mHeight, .width = hasGrid ? mGridWidth : mWidth, .height = hasGrid ? mGridHeight : mHeight, })); if (!hasGrid && heifRotation > 0) { mProperties.push_back(mOwner->addProperty_l({ .type = FOURCC('i', 'r', 'o', 't'), .rotation = heifRotation, })); } } uint16_t itemId = mOwner->addItem_l({ .itemType = "hvc1", .isPrimary = (mNumTiles > 1) ? false : (mIsPrimary != 0), .isHidden = (mNumTiles > 1), .isPrimary = hasGrid ? false : (mIsPrimary != 0), .isHidden = hasGrid, .offset = (uint32_t)offset, .size = (uint32_t)size, .properties = mProperties, }); mTileIndex++; if (mNumTiles > 1) { if (hasGrid) { mDimgRefs.push_back(itemId); if (mTileIndex == mNumTiles) { Loading @@ -1992,6 +2010,12 @@ void MPEG4Writer::Track::addItemOffsetAndSize(off64_t offset, size_t size) { .width = mWidth, .height = mHeight, })); if (heifRotation > 0) { mProperties.push_back(mOwner->addProperty_l({ .type = FOURCC('i', 'r', 'o', 't'), .rotation = heifRotation, })); } mOwner->addItem_l({ .itemType = "grid", .isPrimary = (mIsPrimary != 0), Loading Loading @@ -2302,7 +2326,8 @@ status_t MPEG4Writer::Track::start(MetaData *params) { mStartTimeRealUs = startTimeUs; int32_t rotationDegrees; if (mIsVideo && params && params->findInt32(kKeyRotation, &rotationDegrees)) { if ((mIsVideo || mIsHeic) && params && params->findInt32(kKeyRotation, &rotationDegrees)) { mRotation = rotationDegrees; } Loading Loading @@ -3427,16 +3452,36 @@ int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { int32_t MPEG4Writer::Track::getMetaSizeIncrease() const { CHECK(mIsHeic); return 20 // 1. 'ispe' property + (8 + mCodecSpecificDataSize) // 2. 'hvcC' property + (20 // 3. extra 'ispe' + (8 + 2 + 2 + mNumTiles * 2) // 4. 'dimg' ref + 12) // 5. ImageGrid in 'idat' (worst case) * (mNumTiles > 1) // - (3~5: applicable only if grid) + (16 // 6. increase to 'iloc' + 21 // 7. increase to 'iinf' + (3 + 2 * 2)) // 8. increase to 'ipma' (worst case) * (mNumTiles + 1); // - (6~8: are per-item) int32_t grid = (mNumTiles > 1); // Note that the rotation angle is in the file meta, and we don't have // it until start, so here the calculation has to assume rotation. // increase to ipco int32_t increase = 20 * (grid + 1) // 'ispe' property + (8 + mCodecSpecificDataSize) // 'hvcC' property + 9; // 'irot' property (worst case) // increase to iref and idat if (grid) { increase += (8 + 2 + 2 + mNumTiles * 2) // 'dimg' in iref + 12; // ImageGrid in 'idat' (worst case) } // increase to iloc, iinf and ipma increase += (16 // increase to 'iloc' + 21 // increase to 'iinf' + (3 + 2 * 2)) // increase to 'ipma' (worst case, 2 props x 2 bytes) * (mNumTiles + grid); // adjust to ipma: // if rotation is present and only one tile, it could ref 3 properties if (!grid) { increase += 2; } return increase; } status_t MPEG4Writer::Track::checkCodecSpecificData() const { Loading Loading @@ -4264,7 +4309,9 @@ void MPEG4Writer::writeIpcoBox() { numProperties = 32767; } for (size_t propIndex = 0; propIndex < numProperties; propIndex++) { if (mProperties[propIndex].type == FOURCC('h', 'v', 'c', 'C')) { switch (mProperties[propIndex].type) { case FOURCC('h', 'v', 'c', 'C'): { beginBox("hvcC"); sp<ABuffer> hvcc = mProperties[propIndex].hvcc; // Patch avcc's lengthSize field to match the number Loading @@ -4273,13 +4320,25 @@ void MPEG4Writer::writeIpcoBox() { ptr[21] = (ptr[21] & 0xfc) | (useNalLengthFour() ? 3 : 1); write(hvcc->data(), hvcc->size()); endBox(); } else if (mProperties[propIndex].type == FOURCC('i', 's', 'p', 'e')) { break; } case FOURCC('i', 's', 'p', 'e'): { beginBox("ispe"); writeInt32(0); // Version = 0, Flags = 0 writeInt32(mProperties[propIndex].width); writeInt32(mProperties[propIndex].height); endBox(); } else { break; } case FOURCC('i', 'r', 'o', 't'): { beginBox("irot"); writeInt8(mProperties[propIndex].rotation); endBox(); break; } default: ALOGW("Skipping unrecognized property: type 0x%08x", mProperties[propIndex].type); } Loading
media/libstagefright/include/media/stagefright/MPEG4Writer.h +1 −0 Original line number Diff line number Diff line Loading @@ -195,6 +195,7 @@ private: uint32_t type; int32_t width; int32_t height; int32_t rotation; sp<ABuffer> hvcc; } ItemProperty; Loading