我正在尝试使用MediaCodec解码器(通过NDK API)从.mp4文件中获取视频帧(用于进一步处理)。下面是设置解码器以渲染到曲面(由ImageReader拥有)的示例代码:
<?php
$str='a=123&b=456&Signature=aaaa/bbb+i8=&Satus=bbbb';
$new_string = str_replace('+', '.', $str);
parse_str($new_string,$old_string);
$signature = str_replace('.', '+', $old_string['Signature']);
?>
在其他地方,下面是我如何设置ImageReader的回调:
// Omitting most error handling for clarity
AMediaExtractor* ex = AMediaExtractor_new();
media_status_t err = AMediaExtractor_setDataSourceFd(ex, fd /*opened previously*/, outStart, outLen);
close(fd);
int numtracks = AMediaExtractor_getTrackCount(ex);
AMediaCodec* decoder = NULL;
for (int i = 0; i < numtracks; i++) {
AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i);
const char *s = AMediaFormat_toString(format);
LOGV("track %d format: %s", i, s);
const char *mime;
if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) {
LOGV("no mime type");
return JNI_FALSE;
} else if (!strncmp(mime, "video/", 6)) {
AMediaExtractor_selectTrack(ex, i);
decoder = AMediaCodec_createDecoderByType(mime);
AImageReader* imageReader;
ANativeWindow* surface;
// This setting doesn’t works
media_status_t status = AImageReader_new(480, 360, AIMAGE_FORMAT_RGBA_8888, 1, &imageReader);
// This setting works
//media_status_t status = AImageReader_new(480, 360, AIMAGE_FORMAT_YUV_420_888, 1, &imageReader);
status = AImageReader_getWindow(imageReader, &surface);
// Configure the decoder to render to a surface
AMediaCodec_configure(codec, format, surface, NULL, 0);
AMediaCodec_start(codec);
}
AMediaFormat_delete(format);
}
最后,下面是回调的样子:
AImageReader_ImageListener* imageListener = new AImageReader_ImageListener();
imageListener->onImageAvailable = &imageCallback;
AImageReader_setImageListener(imageReader, imageListener);
我遇到的问题是,如果我将ImageReader配置为RGBA格式,则回调中的 image 总是为NULL:
void imageCallback(void *context, AImageReader *reader) {
int32_t format;
media_status_t status = AImageReader_getFormat (reader, &format);
AImage* image;
status = AImageReader_acquireLatestImage(reader, &image);
status = AImage_getFormat(image, &format);
// further processing to follow
...
}
我在这里正确使用NDK API吗?我要提一点的是,RGBA不会出现在通过以下API获取的解码器功能列表中(不是通过NDK提供,在Java层中尝试过):
// Always NULL for ImageReader configured with RGBA
// OK for ImageReader configured with YUV_420_888
AImage* image;
status = AImageReader_acquireLatestImage(reader, &image);
答案 0 :(得分:0)
视频解码器通常不支持以RGB格式输出(正如您在colorformats编解码器信息中所注意到的那样),这就是为什么它不起作用。
如果使用表面纹理作为解码器的输出,则视频解码器输出可以透明地转换为RGB - 然后解码的视频数据在OpenGL上下文中可用。如果您只是对表面纹理进行简单的1:1复制/渲染并将OpenGL上下文设置为渲染到ImageReader中,我希望您能获得所需的RGB数据。
这有点迂回(我不确定所有API在本机代码上下文中是否容易访问),但据我所知应该可行。