OSDN Git Service

heif: fix decoding of image size different from full tiled area
authorChong Zhang <chz@google.com>
Wed, 23 Aug 2017 20:51:17 +0000 (13:51 -0700)
committerChong Zhang <chz@google.com>
Wed, 23 Aug 2017 20:51:17 +0000 (13:51 -0700)
Bug: 64077740

Change-Id: I57ee7e1bc05e320be723d224b9328526543cad25

media/libheif/HeifDecoderImpl.cpp
media/libstagefright/ItemTable.cpp
media/libstagefright/StagefrightMetadataRetriever.cpp
media/libstagefright/include/media/stagefright/MetaData.h

index 8b846be..080313c 100644 (file)
@@ -216,8 +216,8 @@ bool HeifDecoderImpl::init(HeifStream* stream, HeifFrameInfo* frameInfo) {
 
     if (frameInfo != nullptr) {
         frameInfo->set(
-                videoFrame->mWidth,
-                videoFrame->mHeight,
+                videoFrame->mDisplayWidth,
+                videoFrame->mDisplayHeight,
                 videoFrame->mRotationAngle,
                 videoFrame->mBytesPerPixel,
                 videoFrame->mIccSize,
@@ -275,8 +275,8 @@ bool HeifDecoderImpl::decode(HeifFrameInfo* frameInfo) {
 
     if (frameInfo != nullptr) {
         frameInfo->set(
-                videoFrame->mWidth,
-                videoFrame->mHeight,
+                videoFrame->mDisplayWidth,
+                videoFrame->mDisplayHeight,
                 videoFrame->mRotationAngle,
                 videoFrame->mBytesPerPixel,
                 videoFrame->mIccSize,
@@ -290,11 +290,12 @@ bool HeifDecoderImpl::getScanline(uint8_t* dst) {
         return false;
     }
     VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->pointer());
-    if (mCurScanline >= videoFrame->mHeight) {
+    if (mCurScanline >= videoFrame->mDisplayHeight) {
+        ALOGE("no more scanline available");
         return false;
     }
     uint8_t* src = videoFrame->getFlattenedData() + videoFrame->mRowBytes * mCurScanline++;
-    memcpy(dst, src, videoFrame->mBytesPerPixel * videoFrame->mWidth);
+    memcpy(dst, src, videoFrame->mBytesPerPixel * videoFrame->mDisplayWidth);
     return true;
 }
 
@@ -306,8 +307,8 @@ size_t HeifDecoderImpl::skipScanlines(size_t count) {
 
     uint32_t oldScanline = mCurScanline;
     mCurScanline += count;
-    if (mCurScanline >= videoFrame->mHeight) {
-        mCurScanline = videoFrame->mHeight;
+    if (mCurScanline > videoFrame->mDisplayHeight) {
+        mCurScanline = videoFrame->mDisplayHeight;
     }
     return (mCurScanline > oldScanline) ? (mCurScanline - oldScanline) : 0;
 }
index b7ff21b..3ec416b 100644 (file)
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "ItemTable"
 //#define LOG_NDEBUG 0
+#define LOG_TAG "ItemTable"
 
 #include <include/ItemTable.h>
 #include <media/MediaDefs.h>
@@ -1434,10 +1434,19 @@ sp<MetaData> ItemTable::getImageMeta() {
         if (tileIndex < 0) {
             return NULL;
         }
-        meta->setInt32(kKeyGridRows, image->rows);
-        meta->setInt32(kKeyGridCols, image->columns);
+        // when there are tiles, (kKeyWidth, kKeyHeight) is the full tiled area,
+        // and (kKeyDisplayWidth, kKeyDisplayHeight) may be smaller than that.
+        meta->setInt32(kKeyDisplayWidth, image->width);
+        meta->setInt32(kKeyDisplayHeight, image->height);
+        int32_t gridRows = image->rows, gridCols = image->columns;
 
+        // point image to the first tile for grid size and HVCC
         image = &mItemIdToImageMap.editValueAt(tileIndex);
+        meta->setInt32(kKeyWidth, image->width * gridCols);
+        meta->setInt32(kKeyHeight, image->height * gridRows);
+        meta->setInt32(kKeyGridWidth, image->width);
+        meta->setInt32(kKeyGridHeight, image->height);
+        meta->setInt32(kKeyMaxInputSize, image->width * image->height * 1.5);
     }
 
     if (image->hvcc == NULL) {
index f36ff97..a53897f 100644 (file)
@@ -250,6 +250,8 @@ static VideoFrame *extractVideoFrame(
          && trackMeta->findInt32(kKeyThumbnailHeight, &thumbnailHeight)
          && trackMeta->findData(kKeyThumbnailHVCC, &type, &data, &size)){
             overrideMeta = new MetaData(*trackMeta);
+            overrideMeta->remove(kKeyDisplayWidth);
+            overrideMeta->remove(kKeyDisplayHeight);
             overrideMeta->setInt32(kKeyWidth, thumbnailWidth);
             overrideMeta->setInt32(kKeyHeight, thumbnailHeight);
             overrideMeta->setData(kKeyHVCC, type, data, size);
@@ -266,32 +268,39 @@ static VideoFrame *extractVideoFrame(
     }
 
     int32_t gridRows = 1, gridCols = 1;
-    int32_t numTiles = 1, tilesDecoded = 0;
     if (overrideMeta == NULL) {
         // check if we're dealing with a tiled heif
-        if (trackMeta->findInt32(kKeyGridRows, &gridRows) && gridRows > 0
-         && trackMeta->findInt32(kKeyGridCols, &gridCols) && gridCols > 0) {
-            int32_t width, height;
+        int32_t gridWidth, gridHeight;
+        if (trackMeta->findInt32(kKeyGridWidth, &gridWidth) && gridWidth > 0
+         && trackMeta->findInt32(kKeyGridHeight, &gridHeight) && gridHeight > 0) {
+            int32_t width, height, displayWidth, displayHeight;
             CHECK(trackMeta->findInt32(kKeyWidth, &width));
             CHECK(trackMeta->findInt32(kKeyHeight, &height));
+            CHECK(trackMeta->findInt32(kKeyDisplayWidth, &displayWidth));
+            CHECK(trackMeta->findInt32(kKeyDisplayHeight, &displayHeight));
 
-            if ((width % gridCols == 0) && (height % gridRows == 0)) {
-                width /= gridCols;
-                height /= gridRows;
-                numTiles = gridCols * gridRows;
-
-                ALOGV("tile: %dx%d, numTiles %d", width, height, numTiles);
+            if (width >= displayWidth && height >= displayHeight
+                    && (width % gridWidth == 0) && (height % gridHeight == 0)) {
+                ALOGV("grid config: %dx%d, display %dx%d, grid %dx%d",
+                        width, height, displayWidth, displayHeight, gridWidth, gridHeight);
 
                 overrideMeta = new MetaData(*trackMeta);
-                overrideMeta->setInt32(kKeyWidth, width);
-                overrideMeta->setInt32(kKeyHeight, height);
+                overrideMeta->remove(kKeyDisplayWidth);
+                overrideMeta->remove(kKeyDisplayHeight);
+                overrideMeta->setInt32(kKeyWidth, gridWidth);
+                overrideMeta->setInt32(kKeyHeight, gridHeight);
+                gridCols = width / gridWidth;
+                gridRows = height / gridHeight;
+            } else {
+                ALOGE("Bad grid config: %dx%d, display %dx%d, grid %dx%d",
+                        width, height, displayWidth, displayHeight, gridWidth, gridHeight);
             }
         }
         if (overrideMeta == NULL) {
-            gridRows = gridCols = numTiles = 1;
             overrideMeta = trackMeta;
         }
     }
+    int32_t numTiles = gridRows * gridCols;
 
     sp<AMessage> videoFormat;
     if (convertMetaDataToMessage(overrideMeta, &videoFormat) != OK) {
@@ -383,6 +392,7 @@ static VideoFrame *extractVideoFrame(
     int64_t targetTimeUs = -1ll;
 
     VideoFrame *frame = NULL;
+    int32_t tilesDecoded = 0;
 
     do {
         size_t inputIndex = -1;
@@ -500,7 +510,7 @@ static VideoFrame *extractVideoFrame(
 
                     if (frame == NULL) {
                         frame = allocVideoFrame(
-                                overrideMeta,
+                                trackMeta,
                                 (crop_right - crop_left + 1) * gridCols,
                                 (crop_bottom - crop_top + 1) * gridRows,
                                 dstBpp,
index 65ad3e4..6cfde9c 100644 (file)
@@ -213,9 +213,9 @@ enum {
     kKeyTemporalLayerId  = 'iLyr', // int32_t, temporal layer-id. 0-based (0 => base layer)
     kKeyTemporalLayerCount = 'cLyr', // int32_t, number of temporal layers encoded
 
-    kKeyGridRows         = 'rows', // int32_t, HEIF grid rows
-    kKeyGridCols         = 'clms', // int32_t, HEIF grid columns
-    kKeyIccProfile       = 'prof', // raw data
+    kKeyGridWidth        = 'grdW', // int32_t, HEIF grid width
+    kKeyGridHeight       = 'grdH', // int32_t, HEIF grid height
+    kKeyIccProfile       = 'prof', // raw data, ICC prifile data
 };
 
 enum {