Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ android {
applicationId "com.openipc.decoder"
minSdk 21
targetSdk 36
versionCode 28
versionName "2.03"
versionCode 29
versionName "2.04"

buildConfigField "String", "GIT_HASH", "\"${getGitHash()}\""
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -490,20 +490,42 @@ boolean decodeFrame(Frame buffer, boolean codecH265, long watchdogRef) {
return needCreate;
}

/**
* The picture's size: the crop rectangle when the decoder gives one. KEY_WIDTH / KEY_HEIGHT
* are the buffer, padded to the decoder's alignment (1080 → 1088; one H.265 decoder made
* 1920 wide 2304), which skewed the picture's aspect ratio and the size shown (#166).
*/
static int[] visibleSize(MediaFormat format) {
return visibleSize(format.getInteger(MediaFormat.KEY_WIDTH),
format.getInteger(MediaFormat.KEY_HEIGHT),
cropKey(format, "crop-left"), cropKey(format, "crop-top"),
cropKey(format, "crop-right"), cropKey(format, "crop-bottom"));
}

private static int cropKey(MediaFormat format, String key) {
return format.containsKey(key) ? format.getInteger(key) : -1;
}

/** As above from plain values; a crop value < 0 is missing. Crop right / bottom are inclusive. */
static int[] visibleSize(int width, int height, int left, int top, int right, int bottom) {
// A crop edge outside the buffer is not believed: that axis keeps the buffer size
int w = left >= 0 && right > left && right < width ? right - left + 1 : width;
int h = top >= 0 && bottom > top && bottom < height ? bottom - top + 1 : height;
return new int[]{w, h};
}

/** Renders every decoded frame that is ready; caller holds decoderLock. */
private void drainOutput(MediaCodec codec) {
MediaCodec.BufferInfo info = bufferInfo;
int outputBufferId;
while ((outputBufferId = codec.dequeueOutputBuffer(info, 0)) >= 0
|| outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
MediaFormat format = codec.getOutputFormat();
int mWidth = format.getInteger(MediaFormat.KEY_WIDTH);
int mHeight = format.getInteger(MediaFormat.KEY_HEIGHT);
outWidth = mWidth;
outHeight = mHeight;
int[] size = visibleSize(codec.getOutputFormat());
outWidth = size[0];
outHeight = size[1];
if (listener != null) {
listener.onResolutionChanged(mWidth, mHeight);
listener.onResolutionChanged(size[0], size[1]);
}
} else {
codec.releaseOutputBuffer(outputBufferId, true);
Expand Down
47 changes: 47 additions & 0 deletions android/app/src/test/java/com/openipc/decoder/VisibleSizeTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) OpenIPC https://openipc.org Prosperity Public License 3.0.0
*
* VisibleSizeTest.java — picture size from the decoder's crop rectangle, not the padded buffer (#166)
*
*/

package com.openipc.decoder;

import static org.junit.Assert.assertArrayEquals;

import org.junit.Test;

public class VisibleSizeTest {
@Test
public void cropGivesThePictureSize() {
// H.264 1080p: 16-line macroblocks pad the buffer to 1088
assertArrayEquals(new int[]{1920, 1080},
MediaCodecManager.visibleSize(1920, 1088, 0, 0, 1919, 1079));
// H.265 1080p on a decoder that pads the width to 2304 (#166)
assertArrayEquals(new int[]{1920, 1080},
MediaCodecManager.visibleSize(2304, 1088, 0, 0, 1919, 1079));
// An offset crop
assertArrayEquals(new int[]{1280, 720},
MediaCodecManager.visibleSize(1280, 736, 0, 8, 1279, 727));
}

@Test
public void withoutCropTheBufferSizeStays() {
assertArrayEquals(new int[]{1920, 1088},
MediaCodecManager.visibleSize(1920, 1088, -1, -1, -1, -1));
assertArrayEquals(new int[]{640, 480},
MediaCodecManager.visibleSize(640, 480, 0, 0, 0, 0));
}

@Test
public void cropOutsideTheBufferIsIgnored() {
assertArrayEquals(new int[]{1920, 1088},
MediaCodecManager.visibleSize(1920, 1088, 0, 0, 3839, 2159));
// Wholly outside, narrower than the buffer (Qodo on #167)
assertArrayEquals(new int[]{1920, 1088},
MediaCodecManager.visibleSize(1920, 1088, 3000, 2000, 3100, 2100));
// One axis bad, the other kept
assertArrayEquals(new int[]{1920, 1080},
MediaCodecManager.visibleSize(1920, 1088, 0, 0, 1920, 1079));
}
}
Loading