目标:尝试为Android制作带字幕的视频播放器。视频可以是低分辨率但字幕应该是手机的分辨率(如果视频是720p,则字幕应该渲染到屏幕尺寸为1080p)。
问题:在Textureview或Surfaceview上渲染无法通过哪里可以看到它与背景视图混合。我正在使用FFMPEG渲染帧720p,但电话设备是1080p。我需要显示分辨率不同于字幕分辨率的字幕,因此难以进行像素混合。
我首先尝试使用sws_convert缩放帧(AVFrame),但每帧占用80ms因此不是一个选项(因为它正在运行软件)。
然后我尝试了两个表面视图,一个用于视频,一个用于字幕,其中视频为720p,字幕SurfaceView为1080p,然后视频可扩展到手机大小。这里的问题是字幕不是半透明的。黑色不透明度0将是透明的,但是具有α0的白色仍然是白色。这是为什么?
//Code from Java, the view that extends FrameLayout
public VideoView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mVideoSurface = new SurfaceView(context);
mSubtitlesSurface = new SurfaceView(context);
addView(mVideoSurface);
addView(mSubtitlesSurface);
mVideoSurface.getHolder().addCallback(mSurfaceCallback);
mSubtitlesSurface.getHolder().addCallback(mSurfaceCallback);
mSubtitlesSurface.setZOrderMediaOverlay(true);
mSubtitlesSurface.getHolder().setFormat(PixelFormat.TRANSLUCENT);
//etc
}
最终我尝试作为测试来为字幕表面视图(C ++)渲染一个正方形
// Render the video frame, now render the subtitle frame
ANativeWindow_Buffer buffer;
ANativeWindow_setBuffersGeometry(subWindow, width, height, WINDOW_FORMAT_RGBA_8888);
if ((ret = ANativeWindow_lock(subWindow, &buffer, NULL)) < 0) {
return ret;
}
for (int j = height/2; j < height/2 + 100; j++) {
for (int i = width/2; i < width/2 + 100; i++) {
uint8_t * d = (uint8_t*)buffer.bits + j * (buffer.stride * 4) + i * 4;
d[0] = 0xff;
d[1] = 0xff;
d[2] = 0xFF;
d[3] = 0; /* alpha */
}
}
ANativeWindow_unlockAndPost(subWindow);
因此,上面的代码应该在图像中呈现一个带有0 alpha的白色方块(因此应该是不可见的),但它会显示出来。如果我用alpha 0将其更改为黄色,它将是可见的,但不是正确的颜色。如果我用1 alpha变为白色,则为白色且不透明。如果我使用带有alpha 0xCC的黑色,它是不可见的,只有当alpha为0xFF时它才会显示为黑色。即使我将它添加到SurfaceHolder,似乎没有半透明性。为什么会这样?如果需要,我可以添加更多代码。
我唯一的选择就是在OpenGL和(GLSurfaceView)中将帧渲染为纹理,将图像大小调整为手机分辨率并将alpha字幕作为纹理混合到帧上?
提前致谢。