wseemann / FFmpegMediaMetadataRetriever

FFmpegMediaMetadataRetriever provides a unified interface for retrieving frame and meta data from an input media file.
1.72k stars 387 forks source link

getFrameAtTime Rotation issue #190

Closed HBiSoft closed 5 years ago

HBiSoft commented 6 years ago

When using the following:

Bitmap bt = mmr.getFrameAtTime(mPresentationTime, FFmpegMediaMetadataRetriever.OPTION_CLOSEST);

The bitmap rotation is incorrect.

Any idea how I can resolve this issue?

HBiSoft commented 5 years ago

I can't imagine that nobody has experienced this, I have tested with multiple video files with the same issue, the rotation is incorrect.

This is how I get the Bitmap, if someone would like to try and reproduce the issue:

FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever();
mmr.setDataSource(mStringFilePath);
//Time is us
int mPresentationTime = mFramePlayerView.getPresentationTime();
Bitmap mBitmap = mmr.getFrameAtTime(mPresentationTime, FFmpegMediaMetadataRetriever.OPTION_CLOSEST);

File mFileBitmap = new File(directoryToStore, "test.png");
try {
    FileOutputStream outputStream = new FileOutputStream(mFileBitmap);
    mBitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
    outputStream.close();
    } catch (Exception e) {
        e.printStackTrace();
}

I used a portrait video captured with my Samsung J7 Pro.

This doesn't happen when using MediaMetadataRetriever.

HBiSoft commented 5 years ago

@wseemann I also asked a question on StackOverflow about this issue, if you want to take a look - https://stackoverflow.com/questions/52198519/saved-bitmap-has-incorrect-orientation.

I can also provide a sample video, if you want to use it for testing.

HBiSoft commented 5 years ago

Apparently, this is a issue on some Samsung devices. But what I don't understand is why this doesn't happen when using MediaMetadataRetriever. I managed to get a temporary solution (I'm not sure how this will react on different device's).

This is what I do now:


Bitmap mBitmapBeforeRotation = mmr.getFrameAtTime(mPresentationTime, FFmpegMediaMetadataRetriever.OPTION_CLOSEST);

int mBitW = Integer.parseInt(String.valueOf(mBitmapBeforeRotation.getWidth())); 
int mBitH = Integer.parseInt(String.valueOf(mBitmapBeforeRotation.getHeight())); 

int orientation = getResources().getConfiguration().orientation; 
if (orientation == Configuration.ORIENTATION_LANDSCAPE) { 
    // Do nothing because Landscape doesn't give wrong Bitmap rotation 
} else { 
    if (mBitW>mBitH){ 
       Matrix matrix = new Matrix(); 
       matrix.postRotate(90); 
       Bitmap fixedBitmapRotation = Bitmap.createBitmap(mBitmapBeforeRotation, 0, 0, mBitmapBeforeRotation.getWidth(), mBitmapBeforeRotation.getHeight(), matrix, true); 

       String nameOfImage = "nameOfImage" + ".jpeg"; 
       final File mFile = new File(directoryyToStore, nameOfImage); 

       try { 
            FileOutputStream outputStream = new FileOutputStream(mFile);
            fixedBitmapRotation.compress(Bitmap.CompressFormat.JPEG, 100, outputStream); 
            outputStream.close();
        } catch (Exception e) { 
            e.printStackTrace();
        }
    }
    texeBit = mp.getPath(); 
}

For a more detailed explanation why I used orientation, please look at my answer in the link in the previous comment.

Even though this seems to be working (on my device), it would be nice if this library could resolve the issue, because like I said, with MediaMetadataRetriever this doesn't happen.

zivids commented 5 years ago

MediaMetadataRetriever will rotate the image according to the video rotation,FFmpegMediaMetadataRetriever don‘t rotate bitmap,my solution is get the rotation by retriever.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION), and then rotate the bitmap

HBiSoft commented 4 years ago

@zivids You can't assume that METADATA_KEY_VIDEO_ROTATION will be available.

Here is what the docs state:

This key retrieves the video rotation angle in degrees, if available. The video rotation angle may be 0, 90, 180, or 270 degrees.