Merge "heif: fix rotation info writing" into pi-dev
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index a2f4380..768df26 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -1959,6 +1959,17 @@
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'),
@@ -1967,22 +1978,29 @@
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) {
@@ -1992,6 +2010,12 @@
.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),
@@ -2302,7 +2326,8 @@
mStartTimeRealUs = startTimeUs;
int32_t rotationDegrees;
- if (mIsVideo && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
+ if ((mIsVideo || mIsHeic) && params &&
+ params->findInt32(kKeyRotation, &rotationDegrees)) {
mRotation = rotationDegrees;
}
@@ -3427,16 +3452,36 @@
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 {
@@ -4264,24 +4309,38 @@
numProperties = 32767;
}
for (size_t propIndex = 0; propIndex < numProperties; propIndex++) {
- if (mProperties[propIndex].type == FOURCC('h', 'v', 'c', 'C')) {
- beginBox("hvcC");
- sp<ABuffer> hvcc = mProperties[propIndex].hvcc;
- // Patch avcc's lengthSize field to match the number
- // of bytes we use to indicate the size of a nal unit.
- uint8_t *ptr = (uint8_t *)hvcc->data();
- ptr[21] = (ptr[21] & 0xfc) | (useNalLengthFour() ? 3 : 1);
- write(hvcc->data(), hvcc->size());
- endBox();
- } else if (mProperties[propIndex].type == FOURCC('i', 's', 'p', 'e')) {
- beginBox("ispe");
- writeInt32(0); // Version = 0, Flags = 0
- writeInt32(mProperties[propIndex].width);
- writeInt32(mProperties[propIndex].height);
- endBox();
- } else {
- ALOGW("Skipping unrecognized property: type 0x%08x",
- mProperties[propIndex].type);
+ 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
+ // of bytes we use to indicate the size of a nal unit.
+ uint8_t *ptr = (uint8_t *)hvcc->data();
+ ptr[21] = (ptr[21] & 0xfc) | (useNalLengthFour() ? 3 : 1);
+ write(hvcc->data(), hvcc->size());
+ endBox();
+ break;
+ }
+ case FOURCC('i', 's', 'p', 'e'):
+ {
+ beginBox("ispe");
+ writeInt32(0); // Version = 0, Flags = 0
+ writeInt32(mProperties[propIndex].width);
+ writeInt32(mProperties[propIndex].height);
+ endBox();
+ 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);
}
}
endBox();
diff --git a/media/libstagefright/include/media/stagefright/MPEG4Writer.h b/media/libstagefright/include/media/stagefright/MPEG4Writer.h
index 2a062cc..7b41362 100644
--- a/media/libstagefright/include/media/stagefright/MPEG4Writer.h
+++ b/media/libstagefright/include/media/stagefright/MPEG4Writer.h
@@ -195,6 +195,7 @@
uint32_t type;
int32_t width;
int32_t height;
+ int32_t rotation;
sp<ABuffer> hvcc;
} ItemProperty;