我正在尝试通过NDK的MediaCodec API读取裁剪边界。
我正在阅读以下数据:
AMediaFormat* fmt = initialized();
if (AMediaFormat_getInt32(fmt, "crop-left", &cropLeft)) {
LOGI("crop-left: %d", cropLeft);
}
但是,我无法读取我尝试过的各种视频的cropLeft值。我试图在第一帧之后读取它,并且一旦检测到格式更改,我就试图读取它。
我在vlc code base中看到了类似的代码。
在这里寻找可能存在的错误。
答案 0 :(得分:2)
尚无法读取裁剪值。 在引擎盖下,AMediaFormat包含一个消息结构(AMessage),它由stagefright发送,包含所有裁剪值。裁剪值是特殊类型的Rect,除了已经在AMediaFormat(int32,int64,string,buffer)中定义的方法之外,还需要一个新的read方法。 不幸的是,甚至没有AMediaFormat_toString方法处理Rect类型。我们可以看到输出为" crop:unknown(9)"农作物价值观。
更新:
这是我在使用Android 7.0的Galaxy S6上使用的丑陋黑客。 它不能用于生产代码。它仅用于测试和演示。它将在其他Android版本和供应商手机上崩溃。 预计结构会在其他Android版本中发生变化,因此需要修复偏移,填充和其他值。 无论如何,AMediaFormat是一个结构,它有一个指向AMessage的指针。预计这是前4个字节。 AMessage是RefBase的子类,使用mainoffset [24]我们将一些字节转发到AMessage类中的Items数组。我们期望Items结构的大小为32字节,并且它有一个指向" crop"的char指针。串。当我们找到作物项目时,我们可以读出作物值。
AMediaFormat* format = AMediaCodec_getOutputFormat(_codec);
typedef struct {
char mainoffset[24];
struct {
char itemoffset[8];
int32_t cropLeft;
int32_t cropTop;
int32_t cropRight;
int32_t cropBottom;
unsigned char* name;
char padding[4];
}items[64];
}AMessage;
AMessage* amessage = *((AMessage**)format);
int n = 0;
while ( amessage->items[n].name ) {
if ( !strcmp((const char*)amessage->items[n].name, "crop") ) {
int32_t width = amessage->items[n].cropRight - amessage->items[n].cropLeft + 1;
int32_t height = amessage->items[n].cropBottom - amessage->items[n].cropTop + 1;
__android_log_print(ANDROID_LOG_VERBOSE, "FORMAT", "width=%d height=%d", width, height);
break;
}
n++;
}
答案 1 :(得分:1)
您没有说明代码中的initialized()
。请注意,实际输出MediaFormat
不能立即使用,但是当您从解码器返回INFO_OUTPUT_FORMAT_CHANGED
时,您应该使用MediaCodec.getOutputFormat()
获取它。您无法事先获取MediaFormat
对象并在获得该返回值时从旧对象读取,您需要再次调用getOutputFormat()
。