我正在使用StageFright视频编码器在Android 4.4中对视频进行编码;
sp<AMessage> format = new AMessage;
format->setInt32("width", 1080);
format->setInt32("height", 1920);
format->setString("mime", "video/avc");
format->setInt32("color-format", OMX_COLOR_FormatYUV420Planar);
format->setInt32("bitrate", 1000000);
format->setFloat("frame-rate", 25);
format->setInt32("i-frame-interval", 5);
sp<MediaCodec> videoEncoder = MediaCodec::CreateByType(looper, "video/avc", true);
videoEncoder->configure(format, NULL, NULL,MediaCodec::CONFIGURE_FLAG_ENCODE);
videoEncoder->start();
但是当我打电话给:
status_t err = gSpVideoEncoder->dequeueOutputBuffer(&bufIndex, &offset, &size, &ptsUsec, &flags, kTimeout);
我得到了:
err === INFO_FORMAT_CHANGED
下一步,我打电话给:
sp<AMessage> newFormat;
videoEncoder->getOutputFormat(&newFormat);
uint32_t width = 0, height = 0;
newFormat->findInt32("width", (int32_t *)(&width));
newFormat->findInt32("height", (int32_t *)(&height));
fprintf(stderr, "new width: %d, height: %dn", width, height)
我得到了结果:
new width: 1088, height: 1920
我很困惑(不是1080x1920),我是否应该为videoEncoder提供新的输入帧(1088x1920)?
视频编码要求帧尺寸与 16 的倍数对齐,即宏块尺寸。高清分辨率,即 1920 x 1080 是一种特例,因为 1080 不是 16 的倍数。基础编码器期望客户端提供对齐的边界。
在这种情况下,您可以提供窗口化的数据,如下所示。对于Luma
,您必须对齐 16 的倍数,对于 Chroma
,您必须对齐 8 的倍数。剩余的像素可以用零预填充。
请注意:如果编码器能够处理 1920 x 1080 作为编码分辨率,则输出应该没问题。如果编码器使用 1920 x 1088 编码,由于零填充,您将在生成的比特流中在图片底部观察到一个绿色带。
---------------------------------------------
| |
| |
| |
| Luma |
| 1920 x 1080 |
| filled into |
| a buffer of |
| 1920 x 1088 |
| |
| Last 8 lines could |
| be filled with zeroes |
| |
---------------------------------------------
-----------------------
| Cb |
| 960 x 540 |
| filled into |
| a buffer of |
| 960 x 544 |
| |
-----------------------
-----------------------
| Cr |
| 960 x 540 |
| filled into |
| a buffer of |
| 960 x 544 |
| |
-----------------------