使用NDK MediaCodec获取已解码视频的作物边界

问题描述:

我试图通过NDK的MediaCodec API读取作物边界。使用NDK MediaCodec获取已解码视频的作物边界

我读值如下:

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

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

我已经在vlc code基地看到过类似的代码。

寻找什么可能在这里可能是错误的。

目前还不可能读取作物数值。 AMediaFormat包含一个消息struct(AMessage),它由stagefright发送,并带有所有的裁切值。裁切值是特殊类型的Rect,除了已经在AMediaFormat(int32,int64,string,buffer)中定义的值之外,还需要一个新的读取方法。 不幸的是,Rect类型甚至没有被AMediaFormat_toString方法处理。我们可以看到输出为“作物:未知(9)”作物值的未读数。

UPDATE:

这里是一个丑陋的黑客攻击我使用的Galaxy S6与Android 7.0。 它不能用于生产代码。它仅用于测试和演示。它会在其他Android版本和供应商手机上崩溃。 结构预计会在其他Android版本中发生变化,因此需要修正偏移量,填充和其他值。 无论如何,AMediaFormat是一个具有指向AMessage的指针的结构。预计这是在前4个字节。 AMessage是RefBase的一个子类,在mainoffset [24]中,我们正在向AMessage类中的Items数组转发一些字节。我们期待Items结构的大小为32字节,并且它有一个指向“裁剪”字符串的字符指针。当我们找到作物项目时,我们可以读出作物值。

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++; 
} 
+0

这就是我所发现的。 – Ketan

你不说什么initialized()在你的代码中。请记住,实际输出MediaFormat不立即可用,但当您从解码器获得INFO_OUTPUT_FORMAT_CHANGED时,应该使用MediaCodec.getOutputFormat()。您无法事先获取MediaFormat对象,并在获取该返回值时从旧对象中读取,您需要再次调用getOutputFormat()

+0

对不起,不清楚。我在调整格式之后调用函数来分析农作物的价值。部分代码如下所示:'.... else if(bufId == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED){... AMediaFormat * format = AMediaCodec_getOutputFormat(track.codec); getRawImageInfo(format,_rawImageInfo); ..'。但是,我使用原始格式来执行编解码器配置,并在调用getRawImageInfo后实际销毁新格式。还有其他事情要做吗? – Ketan