使用NDK MediaCodec访问已解码视频的裁剪边界

时间:2017-08-10 17:56:42

标签: android-ndk mediacodec

我正在尝试通过NDK的MediaCodec API读取裁剪边界。

我正在阅读以下数据:

AMediaFormat* fmt = initialized();
if (AMediaFormat_getInt32(fmt, "crop-left", &cropLeft)) {
    LOGI("crop-left: %d", cropLeft);
}

但是,我无法读取我尝试过的各种视频的cropLeft值。我试图在第一帧之后读取它,并且一旦检测到格式更改,我就试图读取它。

我在vlc code base中看到了类似的代码。

在这里寻找可能存在的错误。

2 个答案:

答案 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()